Files
php-security-linter/docs/QUICK_REFERENCE.md

291 lines
8.6 KiB
Markdown
Raw Permalink Normal View 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 ディレクティブ
```
### 安全なパターン(検出されない)
```blade
{!! 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サニタイザー関数これらは安全と判定
```php
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サニタイザー破壊パターン危険
```php
stripslashes(mysqli_real_escape_string(...)) ✗
urldecode(addslashes($var)) ✗
html_entity_decode($pdo->quote($var)) ✗
```
### 安全なパターン
```php
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)
```
### コマンドサニタイザー関数(これらは安全と判定)
```php
escapeshellarg($arg) ✓ 引数エスケープ
escapeshellcmd($cmd) ✓ コマンドエスケープ
basename($path) ✓ ファイル名のみ
intval($var) ✓ 型キャスト
```
### コマンドサニタイザー破壊パターン(危険)
```php
urldecode(escapeshellarg($var)) ✗
str_replace("'", "", escapeshellarg($var)) ✗
stripslashes(escapeshellcmd($var)) ✗
```
### 安全なパターン
```php
$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)
```
### パスサニタイザー関数(これらは安全と判定)
```php
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 ✗ ダブルエンコード
```
### パスサニタイザー破壊パターン(危険)
```php
urldecode(basename($var)) ✗ %2e%2e -> ..
base64_decode($var) ✗ トラバーサル隠蔽
$file->getClientOriginalName() ✗ ユーザー制御
```
### 安全なパターン
```php
$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])
```
### 安全なパターン
```php
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
```
### 安全なパターン
```blade
<form method="POST">
@csrf
@method('PUT') ✓
</form>
```
```php
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 使用方法
```bash
# 基本
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 | クリティカル/高重大度の問題あり |