侵入テストをしているとき、HTTP GETパラメータを使用して1次元または多次元の配列を挿入すると、PHPスクリプトの望ましくない動作が発生することがあります。
これは、特にPHPスクリプトが(深い)多次元配列を再帰的にループしていて、実行時間に上限がないか高い場合に、多次元配列の注入が発生する場合に、可用性リスクを引き起こす可能性があります。これはリソースの枯渇を引き起こす可能性があるためです実際には、全体が$_GET
配列はループされ、ある種のフィルタリングまたは検証が適用されます。
入力:(パラメータとして文字列を期待)
/search.php?query=test
結果:(PHPの$_GET
)
[query] => test
入力:(挿入された配列)
/search.php?query[]=test
結果:(PHPの$_GET
)
[query] => Array
(
[0] => test
)
入力:(注入された多次元配列)
/search.php?query[][][][]=test
結果:(PHPの$_GET
)
[query] => Array
(
[0] => Array
(
[0] => Array
(
[0] => Array
(
[0] => test
)
)
)
)
そのような脆弱性の適切な用語は何ですか? 「アレイ注入」?
これはどの脆弱性カテゴリに属しますか(OWASPトップ> 10またはCWEリストなど)?
これは " parameter tampering "と呼ばれ、 PHP開発者 、OWASPによってそのように呼ばれており、親は CWE-371 である、例えばパラメータがインジェクションSQLステートメントを含む場合、SQLインジェクションになります。あなたがしていることは、悪影響を生み出すために入力を操作(改ざん)することだけです。
これは、可用性リスク以外に、脆弱性と見なされますか?
脆弱性は、サーバーが 入力のサニタイズに失敗することです
これが悪用される可能性のある良いシナリオは何ですか?
これはアプリケーション自体に依存します。さまざまな状況で何が起こるか、または何が起こるかを確認するために、入力の操作を続ける必要があります。たとえば、改ざん内にネストされたコマンドを挿入してみましたか?例えば。:
/search.php?query[() { example;};echo \"Content-type: text/plain\"; echo; echo; /bin/cat /etc/shadow"]=test
基盤となるアプリケーションを理解しないと、何が脆弱かを判別するのは困難です。入力が検証されないという事実は、改ざんされたデータにサーバーが応答できるようにするために、注入するあらゆる種類の事柄をテストできるはずです。大量のデータを挿入して、スタック/バッファ/ヒープオーバーフローをトリガーできるかどうかを確認できます。いくつか試してみることができますが、最初のアプリケーションの機能を知らなくても、これは推測ゲームになります
HTTPパラメータ汚染 という用語が最適だと思います。このタイプの汚染は通常、同じリクエストで異なる値を使用して同じパラメータを複数回送信します。これにより、パラメーターは値の配列として扱われ、パラメーター名は配列名として この記事 で説明されています。 Webサーバーとプログラミング言語が単一の値と比較してこれらの配列を処理する方法は、このバグクラスが利用する方法です。
例では、パラメーターを繰り返す方法が異なりますが、同じ名前の配列が同様に発生しますが、fault injection
やtype confusion
などの他の用語と比較すると、より適切に思えます。
このタイプの汚染は通常、未定義の動作を悪用しますが、あなたが提供した例はそうではありません。それらは、配列を処理するための定義された動作を引き起こします。これにより、アプリケーションのフローを変更するために使用される可能性のある例外がトリガーされる場合があります。たとえば、承認チェックでセッションが変更される前にエラーが発生し、特権の昇格が発生します。
このように_$_GET
_で配列を使用できること自体は、セキュリティ上の脆弱性ではありません。 DoSベクトルは私には無視できるようですが、これを使用するコードによって実際に増幅される可能性があります。
ただし、あなたが提供した例はこの機能の最も重要な部分を逃しました(攻撃者の観点から):この方法でGET
およびPOST
パラメータで通常の配列を渡すことだけが可能ではありませんだけでなく、連想配列。実際、PHPは2つを区別しません。
PHP配列は、整数キーと文字列キーを同時に含むことができます。PHPは、インデックス付き配列と連想配列を区別しません。 – PHP:配列-マニュアル
これは、クライアントが次のようなPOST
パラメータを提供する場合を意味します。
_<input type="text" name="pass[pass1]" value="Password 1">
<input type="text" name="pass[pass2]" value="Password 2">
_
_$_POST
_/_$_GET
_は次のようになります。
_$_POST = array(
...
'pass' => array(
'pass1' => 'Password 1',
'pass2' => 'Password 2',
),
...
);
_
しかし、サーバーが連想配列ではなく通常の配列であることをサーバーが期待していた場合、セキュリティの脆弱性につながる可能性があります。
_//Simplified example, bug is possible with parameterized queries as well
//Expects ?pass[]=password1&pass[]=password2
$query = 'INSERT INTO users (index, password) ';
$parts = array();
foreach($_GET['user'] AS $index=>$value){
parts[]=" VALUES ({$index}, ".$pdo->real_escape_string($value).')';
}
$query .= implode(", ", $parts);
$pdo->exec($query);//
_
_$query
_と予想される入力:
_INSERT INTO USERS (index, password) VALUES(0, 'password1'), VALUES(1, 'password2')
_
_$query
_と?pass[0,'');DROP DATABASE DATABASE();--]=foo
:
_INSERT INTO USERS (index, password) VALUES(0,'');DROP DATABASE DATABASE();--, 'foo')
_
事実、これは「Drupalgeddon」と呼ばれるセキュリティ上の欠陥につながるまったく同じ間違いです–および正当な理由でその名前を受け取りました。
このAPIの脆弱性により、攻撃者は特別に細工したリクエストを送信して、任意のSQL実行を引き起こす可能性があります。リクエストの内容によっては、特権の昇格、任意のPHP実行、またはその他の攻撃につながる可能性があります。 – SA-CORE-2014-005-Drupalコア-SQLインジェクション
SA-CORE-2014-005の発表から数時間以内にDrupal 7.32にパッチまたは更新されていないDrupal 7 Webサイトが侵害され、自動攻撃が開始されました-Drupalコア-SQLインジェクション。発表から7時間後の10月15日午後11時(UTC)より前に更新またはパッチを適用しない限り、すべてのDrupal 7 Webサイトが危険にさらされていると想定して続行する必要があります。 – Drupal Core-非常に重要-公共サービスの発表-PSA-2014-0
それも パナマペーパーの開示につながる可能性が最も高い脆弱性 (おそらくそれらのセキュリティ更新プログラムをインストールする必要があったはずです...)。
Drupalの脆弱性は、受信した配列を array_values()
に渡すようにコードを更新することで修正され、値のみを含むインデックス付き配列を返します受け取った配列のを使用して、悪意のあるキーを取り除きます。
サンプルコードは同じ方法で修正できます:
_foreach($_GET['user'] AS $index=>$value){
_
_foreach(array_values($_GET['user']) AS $index=>$value){
_
実用的なエクスプロイトを含むDrupalgeddonの詳細: Drupal 7:Drupalgeddon Exploit
_$_GET
_と_$_POST
_のどちらを使用していても、この方法は同じように機能することに注意してください。 _$_REQUEST
_と_$_COOKIE
_についてはわかりません。
MongoDB
などの他の攻撃の可能性があります。
$ _GET(または$ _POST)パラメータをクエリに渡す場合は、最初に文字列にキャストされていることを確認してください。ユーザーは、GETおよびPOSTリクエストに連想配列を挿入できます。これにより、不要な$クエリになることがあります。
かなり無害な例:リクエスト http://www.example.com?username=bob でユーザーの情報を検索するとします。アプリケーションはクエリ$ collection-> find(array( "username" => $ _GET ['username']))を実行します。
誰かが http://www.example.com?username [ $ ne] = fooを取得することでこれを覆すことができますPHPは魔法のように連想配列になります、クエリを$ collection-> find(array( "username" => array( '$ ne' => "foo")))に変換すると、 "foo"という名前のないすべてのユーザー(おそらくすべてのユーザー)が返されます。