ja:rule:out:外部へ出力するデータはデフォルトで全て無害化する
Differences
This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| ja:rule:out:外部へ出力するデータはデフォルトで全て無害化する [2016/03/20 03:02] – created yohgaki | ja:rule:out:外部へ出力するデータはデフォルトで全て無害化する [2017/10/25 00:20] (current) – コンテクストの解説追加 yohgaki | ||
|---|---|---|---|
| Line 18: | Line 18: | ||
| 文字エンコーディングのバリデーションは出力時にも行えますが、入力を受け付けた時点でバリデーションしないと問題を生む場合も少なくありません。入力バリデーションと出力時に出力を無害化する処理は独立したセキュリティ対策です。セキュアなコードを書く場合には、入力と出力の両方でセキュリティを意識したコードが必要です。 | 文字エンコーディングのバリデーションは出力時にも行えますが、入力を受け付けた時点でバリデーションしないと問題を生む場合も少なくありません。入力バリデーションと出力時に出力を無害化する処理は独立したセキュリティ対策です。セキュアなコードを書く場合には、入力と出力の両方でセキュリティを意識したコードが必要です。 | ||
| - | 固定長/可変長のデータ(文字やデータ位置に意味があるデータ)、文字エンコーディングを持つデータは全て出力する前に無害化(エスケープするかエスケープが必要ないAPIを利用、またはバリデーション)しなければなりません。 | + | 固定長/可変長のデータ(文字やデータ位置に意味があるデータ)、文字エンコーディングを持つデータは全て出力する前に無害化しなければなりません。 |
| - | データ形式がスカラーであるかどうか、で振るまいが変る出力先もあります。このようなAPIを持つ出力先にはデータ型のバリデーションも欠かせません。 | + | 無害化の手段 |
| + | |||
| + | * エスケープするか | ||
| + | * エスケープが必要ないAPIを利用 | ||
| + | * バリデーション | ||
| + | |||
| + | これらの何れかの手段を出力するデータ**全て**に適用する。 | ||
| + | |||
| + | 出力先の無害化は”コンテクスト”によって異る。必ず適切な無害化方法を使用する。 | ||
| + | |||
| + | 例:SQLの出力先コンテクスト | ||
| + | |||
| + | * パラメーター (パラメーター用エスケープまたはパラメーター用プレイスホルダ) | ||
| + | * 識別子 (テーブル名、カラム名など。識別子用エスケープ) | ||
| + | * SQL語句 (DESC、ASCなど。バリデーション) | ||
| + | パラメーターには更にコンテクストがある。全てのコンテクストに対して適切な無害化が必要 | ||
| + | * LIKEクエリ (LIKE用エスケープ) | ||
| + | * 正規表現 (正規表現用エスケープ) | ||
| + | * バイナリ型 (バイナリ型用エスケープ) | ||
| + | * 配列型 (パラメーター用またはバイナリ型用のエスケープ) | ||
| + | * JSON型 (JSON用エスケープ) | ||
| + | * その他、全てのコンテクストに対して適切な無害化処理 | ||
| + | |||
| + | エスケープはコンテクストに合わせて行わなければならない。例えば、SQLインジェクション対策としてエスケープ/エスケープが必要ないAPIを利用しても、LIKEクエリや正規表現をサポートするDBMSの場合、LIKEクエリのエスケープ、正規表現のエスケープが必要となる。 | ||
| + | |||
| + | |||
| + | データ形式がスカラーであるかどうか、で振るまいが変る出力先もあります。このようなAPIを持つ出力先にはデータ型のバリデーションも欠かせません。例:MongoDBインジェクション | ||
| データ形式をバリデーションしたり、出力データをエスケープするだけでは不十分な場合も少くありません。例えば、データベースクエリで取得するレコード数は最大値を制限(LIMIT句で取得可能なレコード数の値を制限)していないと、システムが応答不能になる問題が発生する場合があります。 | データ形式をバリデーションしたり、出力データをエスケープするだけでは不十分な場合も少くありません。例えば、データベースクエリで取得するレコード数は最大値を制限(LIMIT句で取得可能なレコード数の値を制限)していないと、システムが応答不能になる問題が発生する場合があります。 | ||
| Line 31: | Line 57: | ||
| ===== 非適合コード例(Output depends on input validation) ===== | ===== 非適合コード例(Output depends on input validation) ===== | ||
| + | |||
| + | 入力対策と出力対策は独立した対策である。出力時に無害化できるものは全て無害化する。 | ||
| <code php> | <code php> | ||
| Line 54: | Line 82: | ||
| // $id is used without escape/ | // $id is used without escape/ | ||
| - | $sql = ' | + | $sql = ' |
| $ret = pg_query($sql); | $ret = pg_query($sql); | ||
| if ($ret === FALSE) { | if ($ret === FALSE) { | ||
| Line 61: | Line 89: | ||
| ?> | ?> | ||
| </ | </ | ||
| + | |||
| + | この非適合コードの場合、$idが整数値としてバリデーションされていることに依存したコードになっている。出力対策は入力対策とは独立して行う。 | ||
| + | |||
| ===== 適合コード例 ===== | ===== 適合コード例 ===== | ||
| - | [ルール/推奨事項に適合するコードおよびその解説。複数あって構わない。その場合、セクション名の後に" | + | 一部のデータベースは整数などに文字リテラルをサポートしていない場合もあるが、ほとんどのデータベースはサポートしている。全てのパラメータに文字リテラルをサポートするデータベースの場合、すべて文字列としてエスケープする。 |
| + | |||
| + | <code php> | ||
| + | <?php | ||
| + | $db = pg_connect(' | ||
| + | if (!$db) { | ||
| + | throw new Exception(' | ||
| + | } | ||
| + | |||
| + | // There should be arbitrary length limit validation | ||
| + | if (strspn(strlen($_GET[' | ||
| + | throw new Exception(' | ||
| + | } | ||
| + | // Validate $_GET[' | ||
| + | if (strspn($_GET[' | ||
| + | throw new Exception(' | ||
| + | } | ||
| + | |||
| + | $id = $_GET[' | ||
| + | |||
| + | // Usually there are many lines of codes and/or input/ | ||
| + | // codes are stored in different files. | ||
| + | |||
| + | // $id should be escaped/ | ||
| + | $sql = ' | ||
| + | $ret = pg_query($sql); | ||
| + | if ($ret === FALSE) { | ||
| + | throw new Exception(' | ||
| + | } | ||
| + | ?> | ||
| + | </ | ||
| + | |||
| + | PostgreSQLの場合、pg_query_params()などのプリペアードクエリを利用しても良い。 | ||
| + | |||
| + | 識別子(テーブル名やカラム名)がパラメータの場合、PostgreSQLではpg_escape_identifier()が利用できる。識別子のエスケープ関数がないAPIを利用している場合、データベースの識別子エスケープ仕様に合わせて関数を作成し適用しなければななあい。LIKEクエリや正規表現を利用したクエリは、SQLコンテクストとは異る。必要な場合はLIKEクエリ、正規表現用のエスケープ関数を使ってエスケープしなければならない。 | ||
| Line 72: | Line 137: | ||
| <code php> | <code php> | ||
| + | <?php | ||
| + | $db = new PDO(' | ||
| + | // Test table | ||
| + | $db-> | ||
| + | // Test data | ||
| + | $str = ' | ||
| + | |||
| + | $db-> | ||
| + | ?> | ||
| </ | </ | ||
| + | sqlite3コマンドでmydbの内容を確認すると以下のような出力となる。 | ||
| - | ===== 適合コード例 ===== | + | < |
| + | sqlite> select * from test; | ||
| - | [ルール/推奨事項に適合するコードおよびその解説。複数あって構わない。その場合、セクション名の後に" | + | aaaaaaaaaaaaaaaaaaaaa |
| + | </ | ||
| + | SQLite3のカラムは整数型のプライマリーキーを除き、全て可変長テキスト型である。このため、この非適合コードはカラムデータ型定義の制限を越えた文字列を保存する。 | ||
| + | |||
| + | |||
| + | ===== 適合コード例(Validation) ===== | ||
| + | |||
| + | <code php> | ||
| + | <?php | ||
| + | $db = new PDO(' | ||
| + | // Test table | ||
| + | $db-> | ||
| + | // Test data | ||
| + | $str = ' | ||
| + | |||
| + | // PHP 5.5 or less requires encoding setting. | ||
| + | if (!is_scalar($str) || !mb_check_encoding($str) || strlen($str) > 8) { | ||
| + | throw new Exception(' | ||
| + | } | ||
| + | $db-> | ||
| + | ?> | ||
| + | </ | ||
| + | |||
| + | この適合コードは適切なバリデーションを行う。CHECK制約やデータ型が利用できるデータベースの場合、データベース側のバリデーション機能を利用し、クエリエラーを検出する方法も選択できる。 | ||
| + | |||
| + | |||
| + | ===== 非適合コード例(HTML) ===== | ||
| + | |||
| + | <code php> | ||
| + | <?php | ||
| + | $id = $_GET[' | ||
| + | if (!is_scalar($id) || strlen($id) > 8 || strspn($id, ' | ||
| + | throw new Exception(' | ||
| + | } | ||
| + | |||
| + | |||
| + | echo 'ID: '. $id . '< | ||
| + | ?> | ||
| + | </ | ||
| + | |||
| + | HTMLコンテクストへの出力に対しHTML用のエスケープを行っていない。 | ||
| + | |||
| + | ===== 適合コード例(HTML) ===== | ||
| + | |||
| + | <code php> | ||
| + | <?php | ||
| + | $id = $_GET[' | ||
| + | if (!is_scalar($id) || strlen($id) > 8 || strspn($id, ' | ||
| + | throw new Exception(' | ||
| + | } | ||
| + | |||
| + | // PHP 5.6以降のデフォルトの場合 | ||
| + | echo 'ID: '. htmlspecialchars($id) . '< | ||
| + | ?> | ||
| + | </ | ||
| + | |||
| + | 適合コードはコンテクストに対してエスケープ可能な全ての変数をコンテクスト用のエスケープを行う。エスケープしない変数は「エスケープできない変数」のみとする。HTMLコンテクストの場合、関数などで既に作られたHTML部品がエスケープできない変数である。 | ||
| + | |||
| + | エスケープできない変数はプログラムによって自動処理できるようにするか、変数名によってエスケープができない変数であることが判るようにする。 | ||
| + | |||
| + | エスケープできない変数を作成する場合、確実に安全な変数となるようにする。 | ||
| ===== 例外 ===== | ===== 例外 ===== | ||
| - | [ルール/推奨事項の例外] | + | 文字エンコーディングのチェックは入力受付時に行う方が効率的である。全ての入力がバリデーションされている場合、出力時の文字エンコーディングバリデーションは省略しても構わない。 |
| + | |||
| + | 出力パラメータには無害化ができない物(HTML構文交じりのパラメータなど)もある。この場合、無害化できないパラメータを生成する場合に、全てのパラメータを無害化する。 | ||
| ===== リスク評価 ===== | ===== リスク評価 ===== | ||
| - | [ルール/推奨事項のリスク評価] | + | 出力対策と入力対策は独立した対策だが、入力対策だけで十分とするコードは間違いを起こしやすい。複雑なソフトウェアでは全てのパラメータが十分に安全なバリデーションを適用されているかを保証することも困難である。非常に単純なコード以外では出力時に全て無害化する。 |
| - | + | ||
| - | [評価例 - 英語表記に統一] | + | |
| ^ Rule ^ Severity ^ Likelihood ^ Remediation Cost ^ Priority ^ Level ^ | ^ Rule ^ Severity ^ Likelihood ^ Remediation Cost ^ Priority ^ Level ^ | ||
| - | | IDS05-J | medium | + | | IDS05-J | critical |
| ===== 関連ガイドライン ===== | ===== 関連ガイドライン ===== | ||
| ===== 参考文献 ===== | ===== 参考文献 ===== | ||
| + | |||
| + | |||
ja/rule/out/外部へ出力するデータはデフォルトで全て無害化する.1458442965.txt.gz · Last modified: 2016/03/20 03:02 by yohgaki
