PHP 自動ホワイトボックス監査技術と実装
中国では公開されている PHP 自動監査技術資料が少ないのに比べ、海外では比較的優れたものが登場しています。 RIPS などの自動監査実装は、トークン フローに基づいて一連のコード分析を実行します。データフロー分析や汚染伝播分析などの従来の静的分析手法は、PHPなどの動的スクリプト言語分析に適用されることは比較的まれですが、ホワイトボックス自動化技術を実現する上で重要な技術ポイントです。本日は、国内のセキュリティ研究者がより多くのPHP自動監査技術の有意義な分野に力を注いでくれることを願って、最近の研究と実装の成果を中心に紹介します。
自動監査を実装するには、位置一致に正規表現ルール ベースを直接使用するなど、さまざまな方法があります。この方法は最も単純ですが、最もコストがかかります。の精度。最も信頼できるアイデアは、静的解析技術の分野の知識に基づいて設計することです。一般に、静的解析セキュリティ ツールのプロセスは、主に次の図の形式になります。静的分析で行うことは、平たく言えば、ソース コードのモデリングとは、文字列のソース コードを、その後の脆弱性分析に便利な中間表現、つまり、このコードを表す一連のデータ構造に変換することを意味します。コンパイル テクノロジの分野のメソッドは、一般に、トークン、抽象構文ツリー、制御フローチャートを生成するための字句解析などのモデリング作業に使用されます。モデリング作業の品質は、その後の汚染伝播分析とデータ フロー分析の結果に直接影響します。
実行分析は、セキュリティの知識を組み合わせて、読み込まれたコードの脆弱性を分析および処理することです。最後に、静的分析ツールは判断結果を生成して、この作業フェーズを終了する必要があります。
0x02 実装アイデア
- まず、ユーザーが入力したスキャン対象のプロジェクト ディレクトリ内のすべての PHP ファイルを読み込み、スキャンされた PHP ファイルが Main ファイルの場合、実際に処理する PHP を特定します。ユーザーの要求ファイルを作成し、このタイプのファイルに対して脆弱性分析を実行します。 PHP プロジェクトのクラス定義ファイルやツール関数定義ファイルなど、メイン ファイル タイプではない場合は、解析されずにスキップされます。
- 次に、スキャン対象のプロジェクト内のクラス情報の定義 (クラスが配置されているファイル パス、クラスの属性、クラスのメソッドとパラメーターなど) に焦点を当てて、グローバル データを収集します。 、その他の情報。同時に、ファイルごとにファイル概要が生成されます。このファイル概要は、各代入ステートメントの情報と、代入ステートメント内の関連する変数の精製情報およびエンコード情報の収集に重点を置いています。
- グローバル初期化後、フロントエンド モジュールをコンパイルし、オープン ソース ツール PHP-Parser を使用して、分析する PHP コードの抽象構文ツリー (AST) を構築します。 AST に基づいて、CFG 構築アルゴリズムを使用して制御フロー グラフを構築し、基本ブロックの概要情報をリアルタイムで生成します。
- フロントエンドのコンパイル中に、機密関数への呼び出しが見つかった場合は、停止して汚染伝播分析を実行し、プロセス間分析とプロセス内分析を実行して、対応する汚染されたデータを見つけます。そして、データフロー解析処理で収集した情報をもとに、精製された情報と暗号化された情報を判定し、脆弱なコードであるかどうかを判定します。
前のステップが脆弱なコードである場合は、脆弱性レポート モジュールに移動して、脆弱なコード セグメントを収集します。その実装の基本は、システム環境内で単一モードの結果セット コンテキスト オブジェクトを維持することです。脆弱性レコードが生成されると、それが結果セットに追加されます。スキャン プロジェクト全体の結果が得られた後、Smarty を使用して結果セットをフロント エンドに出力し、フロント エンドでスキャン結果を視覚化します。
実際の PHP 監査では、mysql_query
などの機密関数の呼び出しに遭遇すると、思わず手動で実行してしまいます。最初のパラメータを分析して、それが制御可能かどうかを確認します。実際、多くの CMS は、呼び出すのに便利なようにいくつかのデータベース クエリ メソッドをカプセル化しており、MysqldB クラスにカプセル化するなど、プログラム ロジックが明確です。現時点では、監査中に mysql_query
キーワードは検索されませんが、db->getOne
などの呼び出しが検索されます。
そこで問題は、自動プログラムが分析を実行するときに、db->getOne 関数がデータベース アクセス クラス メソッドであることをどのようにして知るかということです。
これには、自動分析の初期段階でプロジェクト全体のすべてのクラスと定義されたメソッドを収集し、プログラムが分析中にフォローアップする必要があるメソッド本体を見つけられるようにする必要があります。
クラス情報とメソッド情報の収集は、フレームワークの初期化の一部として完了し、シングルトン コンテキストに保存する必要があります。
同時に、分析された PHP がファイルは実際にユーザー要求ファイルを処理します。これは、一部の CMS では、カプセル化されたクラスが通常、データベース操作クラスやファイルにカプセル化されたファイル操作クラスなどの別のファイルに書き込まれるためです。これらのファイルについては汚染伝播解析を行っても意味がないため、フレームワークの初期化時に識別する必要があり、呼び出し型文と定義型文の割合を解析し、閾値に基づいて判定するだけです。エラー率は非常に小さいです。
最後に、各ファイルに対して要約操作を実行します。このステップの目的は、後続の分析中に require、include などのステートメントが見つかったときにファイル間分析を実行することです。主に変数の代入、変数のエンコード、変数の精製に関する情報を収集します。
一般的な Web 脆弱性は、一般にユーザーが制御可能な危険なパラメーターによって引き起こされます。このタイプの脆弱性は、共通 SQLI などの汚染タイプの脆弱性と呼ばれます。 、XSSなど
PHP の組み込み関数の一部は、反射 XSS を引き起こす可能性があるエコーなど、本質的に危険です。ただし、実際のコードでは、一部の組み込み関数を直接呼び出すことはなく、それらを次のようなカスタム関数として再度カプセル化します。
<code class=" hljs php"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">myexec</span><span class="hljs-params">(<span class="hljs-variable">$cmd</span>)</span>{</span> exec(<span class="hljs-variable">$cmd</span>) ;}</code>
実装では、処理フローは次のとおりです。
- 利用初始化中获取的上下文信息,定位到相应的方法代码段
- 分析这个代码片段,查找到危险函数(这里是exec)
- 定位危险函数中的危险参数(这里是cmd)
- 如果在分析期间没有遇到净化信息,说明该参数可以进行传染,则映射到用户函数myexec的第一个参数cmd,并将这个用户自定义函数当做危险函数存放至上下文结构中
- 递归返回,启动污点分析过程
总结为一句话,我们就是跟入到相应的类方法、静态方法、函数中,从这些代码段中查询是否有危险函数和危险参数的调用,这些PHP内置的危险函数和参数位置都是放在配置文件中的进行配置完成的,如果这些函数和参数一旦被发现,且判断危险参数并没有被过滤,则将该用户自定义函数作为用户自定义危险函数。一旦后续的分析中发现调用这些函数,则立即启动污点分析。
在真实的审计过程中,一旦发现危险参数是可控的,我们就会迫不及待地去寻找看程序员有没有对该变量进行有效的过滤或者编码,由此判断是否存在漏洞。
自动化审计中,也是遵循这个思路。在实现中,首先要对每一个PHP中的安全函数进行统计和配置,在程序分析时,对每一条数据流信息,都应该进行回溯收集必要的净化和编码信息,比如:
<code class=" hljs bash"><span class="hljs-variable">$a</span> = <span class="hljs-variable">$_GET</span>[<span class="hljs-string">'a'</span>] ;<span class="hljs-variable">$a</span> = intval(<span class="hljs-variable">$a</span>) ;<span class="hljs-built_in">echo</span> <span class="hljs-variable">$a</span> ;<span class="hljs-variable">$a</span> = htmlspecialchars(<span class="hljs-variable">$a</span>) ;mysql_query(<span class="hljs-variable">$a</span>) ;</code>
上面的代码片段看起来有些怪异,但只是作为演示使用。从代码片段可以看出,变量a经过了intval和htmlspecialchars两个净化处理,根据配置文件,我们顺利的收集到了这些信息。这时,要进行一次回溯,目的是将当前代码行向上的净化和编码信息进行归并。
比如在第三行时,变量a的净化信息只有一条intval,但是第五行时,要求将变量a的净化信息归并,收集为一个list集合intval和htmlspecialchars,方法就是收集到前驱代码中的所有数据流的信息,并进行回溯。
细节部分是,当用户同时对同一个变量调用了如base64_encode和base64_decode两个函数,那么这个变量的base64编码会被消除。同样,如果同时进行转义和反转义也要进行消除。但是如果调用顺序不对或者只进行了decode,那么你懂的,相当危险。
为了寻找出所有的危险sink点的参数(traceSymbol),将向前回溯与当前Block相连的所有的基本块,具体过程如下:
- 循环当前基本块的所有入口边,查找没有经过净化的traceSymbol并且查找基本块DataFlow属性中,traceSymbol的名字。
- 如果一旦找到,那么就替换成映射的symbol,并且将该符号的所有净化信息和编码信息都复制过来。然后,追踪会在所有的入口边上进行。
- 最后,CFG上不同路径上的结果会返回。
当traceSymbol映射到了一个静态字符串、数字等类型的静态对象或者当前的基本块没有入口边时,算法就停止。如果traceSymbol是变量或者数组,就要检查是否在超全局数组中。
污点分析在过程间分析处理内置和用户定义函数过程中开始,如果程序分析时遇到了敏感的函数调用,则使用回溯或者从上下文中获取到危险参数节点,并开始进行污点分析。通俗讲,就是进行危险参数是否可能导致漏洞的判别。污点分析工作在代码TaintAnalyser
中进行实现,获取到危险参数后,具体步骤如下:
0x07 現在の効果
- まず、現在の基本ブロックで危険なパラメーターの割り当てを探し、DataFlow の右側のノードでユーザー入力ソース (
現在の基本ブロック内にソースが見つからない場合は、このファイルのマルチ基本ブロック解析プロセスに入ります。まず、現在の基本ブロックのすべての先行基本ブロックを取得します。先行基本ブロックには、並列構造 (if-else if-else) または非並列構造 (通常のステートメント) が含まれています。そして、危険変数解析を実行します。現在のサイクルの基本ブロックに先行ノードが存在しない場合、解析アルゴリズムは終了します。G ET _POST などのスーパーグローバル配列。また、さまざまな種類の脆弱性を特定するためのプラグイン クラスを使用して、これらのノードが安全かどうかを判断します。- 基本ブロック間分析で脆弱性が見つからなかった場合、最終的なファイル間分析が実行されます。現在の基本ブロックの前に含まれるファイル概要をロードし、これらのファイル概要を走査して判断を行います。
- 上記の手順中に脆弱性が発生した場合は、脆弱性報告モジュールに入ります。それ以外の場合、システムはコード分析を続行します。
のテスト スキャンを実施しました。結果は次のとおりです: simple-log_v1.3.12
Total : 76 XSS : 3 SQLI : 62 INCLUDE : 5 FILE : 3 FILEAFFECT : 1
テスト コードにはすべて明らかな抜け穴があり、MVC フレームワークを使用していません。どのような種類の文字切り捨てがエスケープ文字を消費するかは、現在のテクノロジーでは実際にはサポートできません。一部をスキャンすることもできます。テストプロセスから判断すると、バグが無限にあります。その主な理由は、初期の実装時に多くの文法構造とテストケースが考慮されていなかったためです。また、アルゴリズムがほぼすべて再帰的であるため、無限再帰が発生しやすいです。 Apache を崩壊させます。
したがって、現在のコードは実際にはテスト製品としか考えられません。コードの堅牢性を確保するには、数え切れないほどのリファクタリングと多くのテストが必要です。作成者には、コードを保守する時間があまりありません。
話に戻りますが、著者と私の友人の実装には、MVC フレームワークをサポートしていないという大きな問題があります。 CI フレームワークなどの MVC では、フレームワークが高度にカプセル化されているため、データ フローを均一にキャプチャすることが困難です。したがって、フレームワークの推定値が異なれば、異なる分析方法が必要になります。
現状では、簡単な脆弱性はいくつか確認できていますが、コードの堅牢性が十分ではなく、バグも多くあります。
最後に、
実装コードは github にあります。 talk is cheap, show me the code
コードを共有する目的は、この分野に興味がある、またはすでに取り組んでいるセキュリティ研究者が調査と議論を行うことです。現時点では、CMS を取り出して実行するだけの効果は得られません。幻想を抱いてはいけません。