Qodana
The code quality platform for teams
Qodanaの汚染解析によるPHPコードのセキュリティ保護
このブログ投稿は、JetBrains のコード品質プラットフォームである Qodana の提供でお送りします。 Qodana はお好みの CI ツールでサーバーサイド静的解析を実現できるように設計されています。 Qodana は PhpStorm やその他の JetBrains IDE と同じコードインスペクションを使用するため、IDE と CI 環境の両方で一貫したコード品質チェックを確保するのに役立ちます。
プロジェクトの脆弱性を悪用してシステムを破壊するにはたった 1 人のユーザーで十分です。 外部ユーザーからの悪意のある入力(「テイント=汚染」とも呼ばれます)からプログラムを保護するため、開発チームは静的解析ルーチンにテイントチェックを追加します。
Qodana チームは今年最初のリリースで EAP での PHP のテイント解析を実現しました。 この機能は PHP 2023.1 (jetbrains/qodana-php:2023.1-eap) 向けの Qodana でのみ使用可能です。 PHP 向け Qodana は当社がリリースした初のリンターであっため、PHP 開発者にも当社の新しいセキュリティ機能を最初にテストしてもらうことにしました。 今後は十分なフィードバックを収集した後に他の言語も追加する予定です。
テイント解析とその Qodana での仕組みに関する詳細を知るには、このまま続きをお読みください。
テイント解析とは
テイントとは外部ユーザーによって変更されるとセキュリティリスクをもたらす可能性がある値のことです。 コード内にテイントがあり、未検証の外部データがプログラム全体に拡散される可能性がある場合、ハッカーはこのようなコード箇所を実行して、SQL インジェクション、演算のオーバーフロー、クロスサイトスクリプティング、パストラバーサルなどを発生させることができます。 通常、ハッカーはこのような脆弱性を悪用してシステムを破壊し、資格情報やその他のデータを強奪してシステムの動作を変更します。
開発チームはプログラムの攻撃対象領域に対してセキュリティ監査を実行する際、テイント解析を悪意のある入力に対する追加の保護レイヤーとして実行します。
テイント解析は、関数またはメソッドの本体全体にわたって信頼されていないユーザーの入力の流れを評価するプロセスです。 予期しない入力がプログラムの実行に悪影響を及ぼさないかどうかを判断することを基本的な目標としています。
テイントソースは、プログラムが汚染されている可能性があるデータにアクセスする場所を指します。 汚染された入力を受け入れやすいプログラムの重要箇所はテイントシンクと呼ばれます。 このデータは、関数呼び出しまたは代入を介してシンクに伝播される可能性があります。
テイント解析を手動で実行する場合、外部ユーザーからデータを受け入れているすべての場所を特定し、システム全体で各データを追跡する必要があります。汚染データは多数のノードで使用される可能性があるためです。 テイントの伝搬を防ぐには、以下にある 2 つの手法のいずれかを取る必要があります。
- データをサニタイズする。つまり、データを安全な状態に変換します。 以下の例では、テイントを解消するためにタグを除去しました。
- データを検証する。つまり、追加されたデータが必要なパターンに適合しているかどうかを確認します。 以下の例では、
$
email
変数の検証を有効にしています。
要するに、テイント解析のインスペクションはユーザーの汚染データをそのソースからシンクまで追跡し、サニタイズまたは検証なしでそのデータを扱っている場合に警告を発します。
Qodana でのテイント解析の仕組み
テイント解析はバージョン 2023.1 EAP 以降の PHP 向け Qodana で実行されます。 この機能には、コードをスキャンしてテイントと潜在的な脆弱性をハイライトするインスペクション、PhpStorm で問題を開いてその場で対応する機能、およびテイントのフローを可視化するデータフローグラフが含まれます。
例 1. SQL インジェクション
SQL インジェクションの例と Qodana によるその検出方法を見てみましょう。
ここでは、Qodana は system_admin() 関数内で次のテイントを示しています。
マーカー 1-2: ユーザーのフォーム入力データがサニタイズまたは検証なしで $
_POST
グローバル配列から取得され、変数 $
edit
に割り当てられています。 これはテイントです。
マーカー 3: 汚染された変数 $
edit
が、適切なサニタイズなしに <0>system_save_settings 関数に引数として渡されます。
マーカー 4: $
edit
変数のデータが $
edit
パラメーターに配置されています。
マーカー 5: $
edit
変数が $
filename
キーと $
status
値を持つ <0>foreach に渡されます。 両方の変数に文字列で連結された $
edit
変数の汚染データが含まれています。 $
filename
キーが汚染された SQL 文字列と連結されたあと、汚染データが <0>db_query に渡される引数に伝播されます。
マーカー 6: $
filename
キーには、文字列で連結された $
edit
変数の汚染データが含まれています。
マーカー 7: $
filename
キーは汚染された SQL 文字列と連結されています。
マーカー 8: 汚染された SQL 文字列は汚染たデータを db_query
に渡される引数に伝播します。
次に db_query
を見てみましょう。
マーカー 9: 汚染された文字列は $
query
パラメーターに配置されます。
マーカー 10: このパラメーターは _db_query
関数の引数になります。
_db_query
関数に移動しましょう。
マーカー 11: _db_query
関数の最初のパラメーター $query
にある汚染データ。
マーカー 12: パラメーターのデータが mysql_query
関数に渡されます。これはシンクです。
上記のデータフロー全体が、サニタイズまたは検証なしにデータが $_POST[“edit”]
から mysql_query
($query
) にどのように移動するのかを示しています。これにより、攻撃者は $_POST[“edit”]
のキーで連結された SQL クエリを操作し、SQL インジェクションをトリガーできます。
Qodanaは汚染されたデータが使用されるすべてのノートと共にコードベース内のこれらのリスクを見つけ出すため、すべての汚染データを時間内にサニタイズすることができます。
例 2. XSS の問題
Qodana UI では、全体のテイントのフローを可視化するグラフを表示できます。 こちらは Qodana が XSS 脆弱性を可視化する方法です。これにはマーカー 5 でマージされる 2 つのソースが含まれています。
ソース 1
マーカー 1-2: searchUpdate.pos ファイルのデータが読み取られ、汚染データが $
start
変数に割り当てられます。
ソース 2
マーカー 3-4: パスが $
posFile
のファイルからのデータが読み取られ、汚染データが $
start
変数に割り当てられます。
マーカー 5: $
start
変数のすべての条件分岐からマージされた汚染状態が <0>doUpdateSearchIndex メソッドに引数として渡されます。
doUpdateSearchIndex()
メソッド内を見てみましょう。
マーカー 6-8: $
start
パラメーターにはこのデータフロースライスでの汚染データが含まれ、output
メソッドへの引数として連結文字列内に渡されます。
output
メソッド内を見てみましょう。
マーカー 9: 送信された文字列内に含まれる汚染データは $
out
パラメーターに配置されます。
マーカー 10: $
out
パラメーターからのデータはサニタイズなしで print
関数に転送されます。 この関数はシンクで XSS の脆弱性を発生させるため、悪用される可能性があります。
脆弱性を悪用するために、攻撃者は例えばマーカー 1 および 2 の必要なファイルの代わりにシェルスクリプトをアップロードして、サニタイズされていない print 関数の結果としてウェブページにどんな情報でも載せることができます。
Qodana はこの脆弱性について警告して優先度を高めることで、早急に脆弱性を解決してハックを予防できるようにします。
まとめ
テイント解析は悪用されうる攻撃対象領域の排除に役立つため、ソフトウェアに対するリスクを軽減するのに効果的な方法です。 テイント解析と Qodana の詳細は、Qodana ドキュメントをご覧ください。
コードを健全に保ちながら、開発をお楽しみください!
オリジナル(英語)ブログ投稿の作者: