Files
php-security-linter/docs/QUICK_REFERENCE.md
Yutaka Kurosaki 6280290898 Initial commit: PHP/Laravel Security Linter v1.0.0
A static security analysis tool for PHP and Laravel applications
with recursive taint analysis capabilities.

Features:
- Comprehensive vulnerability detection (XSS, SQL Injection,
  Command Injection, Path Traversal, CSRF, Authentication issues)
- Recursive taint analysis across function calls
- Blade template analysis with context-aware XSS detection
- Smart escape detection and escape bypass detection
- Syntax highlighting in terminal output
- Multi-language support (Japanese/English)
- Docker support for easy deployment
- Multiple output formats (text, JSON, HTML, SARIF, Markdown)
- CI/CD integration ready (GitHub Actions, GitLab CI)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 15:18:53 +09:00

8.6 KiB
Raw Permalink Blame History

セキュリティリンター クイックリファレンス

XSS 検出パターン

Blade テンプレート

重大度: CRITICAL
├── <script>{!! $var !!}</script>     # JS内の生出力
└── onclick="{!! $var !!}"            # イベントハンドラ内の生出力

重大度: HIGH
├── {!! $var !!}                      # 生出力
├── {!! func($var) !!}                # 関数がエスケープしない場合
├── {!! html_entity_decode(...) !!}   # エスケープ破壊
├── {!! '<script>...' . $var !!}      # 危険なハードコードHTML
├── onclick="{{ $var }}"              # イベントハンドラ
└── @include($var)                    # テンプレートインジェクション

重大度: MEDIUM
├── <script>{{ $var }}</script>       # JS コンテキスト
├── href="{{ $var }}"                 # URL コンテキスト
├── style="{{ $var }}"                # CSS インジェクション
└── <svg>{{ $var }}</svg>             # SVG コンテキスト

重大度: LOW
├── data-x={{ $var }}                 # 引用符なし属性
└── @json($var) in <script>           # JSON ディレクティブ

安全なパターン(検出されない)

{!! htmlspecialchars($var) !!}        ✓ エスケープ関数
{!! e($var) !!}                       ✓ Laravel ヘルパー
{!! '<div>' . e($var) . '</div>' !!}  ✓ 安全な連結
{!! csrf_field() !!}                  ✓ 組み込み関数
{!! $errors !!}                       ✓ Laravel 組み込み
{!! Markdown::parse($var) !!}         ✓ Markdown プロセッサ
{!! safeFunc($var) !!}                ✓ エスケープを返す関数

SQLインジェクション 検出パターン

重大度: HIGH
├── DB::raw("... $var ...")
├── DB::select("... $var ...")
├── ->whereRaw("... $var ...")
├── ->orderByRaw($var)
├── $pdo->query("... $var ...")
├── $mysqli->query("... $var ...")
└── "SELECT * FROM t WHERE id = $var"

SQLサニタイザー関数これらは安全と判定

intval($var), (int)$var                                  型キャスト
floatval($var), (float)$var                              型キャスト
mysqli_real_escape_string($conn, $var)                   エスケープ
$pdo->quote($var)                                        PDO エスケープ
filter_var($var, FILTER_VALIDATE_INT)                    検証

SQLサニタイザー破壊パターン危険

stripslashes(mysqli_real_escape_string(...))            
urldecode(addslashes($var))                             
html_entity_decode($pdo->quote($var))                   

安全なパターン

DB::select('SELECT * FROM t WHERE id = ?', [$id]);     
$query->where('column', '=', $value);                   
$query->whereRaw('col = ?', [$value]);                  
"SELECT * FROM t WHERE id = " . intval($id)            

コマンドインジェクション 検出パターン

重大度: CRITICAL
├── exec($cmd . $input)
├── shell_exec($cmd . $input)
├── system($cmd . $input)
├── `$cmd $input`
├── eval($code)
├── include($userPath)
└── preg_replace('/.../e', ...)

重大度: HIGH
├── call_user_func($userCallback)
├── Process::fromShellCommandline($cmd)
└── Artisan::call($userCmd)

コマンドサニタイザー関数(これらは安全と判定)

escapeshellarg($arg)                                     引数エスケープ
escapeshellcmd($cmd)                                     コマンドエスケープ
basename($path)                                          ファイル名のみ
intval($var)                                             型キャスト

コマンドサニタイザー破壊パターン(危険)

urldecode(escapeshellarg($var))                         
str_replace("'", "", escapeshellarg($var))              
stripslashes(escapeshellcmd($var))                      

安全なパターン

$process = new Process(['cmd', $arg1, $arg2]);          
exec(escapeshellcmd($cmd) . ' ' . escapeshellarg($a));  
exec('ls -la ' . escapeshellarg($path));                
exec('kill ' . intval($pid));                           

パストラバーサル 検出パターン

重大度: HIGH
├── file_get_contents($userPath)
├── fopen($userPath, 'r')
├── unlink($userPath)
├── move_uploaded_file($tmp, $userDest)
└── response()->download($userPath)

重大度: MEDIUM
├── Storage::get($userPath)
└── Storage::put($userPath, $content)

パスサニタイザー関数(これらは安全と判定)

basename($path)                                          ディレクトリ除去
realpath($path)                                          パス正規化
pathinfo($path, PATHINFO_BASENAME)                       ファイル名抽出
intval($id)                                              数値ID
Str::random(40), Str::uuid()                             安全なファイル名
$file->hashName()                                        ハッシュファイル名

危険なパストラバーサルパターン

..                                                      ✗ ディレクトリトラバーサル
../  ..\\                                               ✗ Unix/Windows
%2e%2e                                                  ✗ URLエンコード
%252e%252e                                              ✗ ダブルエンコード

パスサニタイザー破壊パターン(危険)

urldecode(basename($var))                                %2e%2e -> ..
base64_decode($var)                                      トラバーサル隠蔽
$file->getClientOriginalName()                           ユーザー制御

安全なパターン

$safePath = basename($userInput);                       
$realPath = realpath($path);                            
if (str_starts_with($realPath, $allowedDir)) { ... }    
'/docs/' . intval($id) . '.txt'                        
$request->file('doc')->hashName()                       

認証 検出パターン

重大度: HIGH
├── md5($password)
├── sha1($password)
├── $password = 'hardcoded'
└── base64_encode($password)

重大度: MEDIUM
├── $token == $userToken          # タイミング攻撃
└── password_hash($pw, ..., ['cost' => 4])

安全なパターン

password_hash($pw, PASSWORD_ARGON2ID);                  
password_verify($input, $hash);                         
hash_equals($expected, $actual);                        
Hash::make($password);                                  

CSRF/セッション 検出パターン

重大度: HIGH
└── <form method="POST"> without @csrf

重大度: MEDIUM
├── session_start() without secure options
├── Cookie without httponly
└── session_regenerate_id() without true

安全なパターン

<form method="POST">
    @csrf                                               ✓
    @method('PUT')                                      ✓
</form>
session_start([
    'cookie_httponly' => true,                          
    'cookie_secure' => true,                            
    'cookie_samesite' => 'Strict',                      
]);
session_regenerate_id(true);                            

設定 検出パターン

重大度: HIGH
├── phpinfo()
└── unserialize($data) without allowed_classes

重大度: MEDIUM
├── dd($var), dump($var)
├── var_dump($var), print_r($var)
├── error_reporting(-1)
├── ini_set('display_errors', '1')
└── Log::info($password)

CLI 使用方法

# 基本
php bin/security-lint <path>

# オプション
-f, --format    出力形式 (text|json|html|sarif|markdown)
-s, --severity  最小重大度 (low|medium|high|critical)
-o, --output    ファイルに出力
-l, --lang      言語 (ja|en)
-e, --exclude   除外パターン
-d, --recursive-depth  再帰深度 (default: 10)
--verbose       詳細表示

# 例
php bin/security-lint app/ -s high -f json -o report.json
php bin/security-lint resources/views/ -l en

終了コード

コード 意味
0 問題なし
1 中/低重大度の問題あり
2 クリティカル/高重大度の問題あり