web-dev-qa-db-ja.com

このPHPフォームのMD5脆弱性を悪用しますか?

私はセキュリティ関連のトピックで練習しており、まったく理解できないこの問題に遭遇しました。 passという名前の1つの入力を持つフォームを受け取ります。これは、バイパスする必要があるコードです。

<?php
error_reporting(0);
session_save_path('/home/mawekl/sessions/');
session_start();
echo '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>';
echo 'This task is as hard to beat as the castle which you can see on the bottom.<br>';
echo '<pre>';
include('./ascii.txt');
echo '</pre><br>';

$_SESSION['admin_level']=1;

if (!isset($_POST['pass']) || md5($_POST['pass'])!='castle')
{
    echo '<b>Wrong or empty password.</b><br>';
    $_SESSION['admin_level']=0;
}

最後のifステートメントに入ると、負けになります($_SESSION['admin_level']1に留まるようにする必要があります)。

助けてくれてありがとう、ありがとう!

説明:

投稿したコードを編集できません。それは挑戦です。私ができることは、名前が「pass」である入力を介してパスワードを送信することだけです。はい、md5は32文字の長い文字列を返すことになっています。それが課題です。

42
Tom

HEADリクエストを送信してみてください。

Ascii.txtが含まれている場合、スクリプトの出力は、4096バイトのようなNiceの数値(一般的なoutput_buffering値)を超えると想定しています。スクリプトがoutput_bufferingバイトを書き込んだら、続行する前に出力バッファーをフラッシュする必要があります。

通常、これは正常に機能し、スクリプトは続行しますが、リクエストタイプがHEADの場合、出力がどこに行っても実行が停止せず、実行が停止します。うまくいけば、「間違ったパスワード」メッセージの途中でadmin_levelが戻されないことを意味します0に。

Ascii.txtが制御可能なファイルである場合は、サイズを微調整して、「間違ったパスワード」メッセージを書き込んでいるときに数値がoutput_bufferingを超えるように調整する必要があります。

これはこのテクニックに関する論文です 。 PHP version/configに基づいて常に適用できるとは限りませんが、論文の最後の例はこの問題に非常に似ているため、意図したソリューションであると期待します。

59
gabedwrds

この場合、MD5にはセキュリティ上の欠陥はありません。そして、その目的は、ハッカーを支持してif (!isset($_POST['pass']) || md5($_POST['pass'])!='castle')を評価させることではありません。この脆弱性は、スクリプトをクラッシュさせたときに発生します。管理者権限は条件付きではありません。 1を$_SESSION['admin_level']に設定することで、ユーザーが何に許可を昇格しても、 PHPは手続き型です。したがって、次のIFステートメントでエラーが発生した場合、権限が設定されるだけでなく、永続的なままになります。これは、セッション。スクリプトがクラッシュしてエラーが発生した場合でも、ログイン中にIFステートメントのみが存在する場合、攻撃者はadmin_levelを1に設定して、他のすべての制限付きスクリプトにアクセスできます。

イベントのタイムライン:

  • 攻撃者が不正なデータまたはデータのオーバーフローをPOSTリクエストに入れる
  • スクリプトの実行
  • スクリプトは、セッションに保存されるadmin_levelを1に設定します
  • 評価時のスクリプト爆弾
  • 攻撃者は、$_SESSION['admin_level']が1かどうかを確認する別のページ/スクリプトに移動します

スクリプトがセッション値をIFステートメントの一部にした場合、これは回避できたはずです。

if (!isset($_POST['pass']) || md5($_POST['pass'])!='castle')
{
    echo '<b>Wrong or empty password.</b><br>';
    $_SESSION['admin_level']=0;
} else {
    $_SESSION['admin_level']=1;
}

ただし、このコードを保護するためにすべきことはまだたくさんあります。

27
Bacon Brad

私はどこかで同様の課題を見てきました。 _'QNKCDZO'_のようなものを入力として送信してみてください。 md5('QNKCDZO')は_'0e830400451993494058024219903391'_(ハッシュの_0e_プレフィックスに数値の科学的表記を示すことに注意)であり、コードは_!=_演算子を使用するため_!==_)PHP(古いバージョンのみ?)は、比較する前に実際に数値にキャストします。当然、両方が_0_に評価され、勝ちます。

編集:ruakhは正しいです。キャストが発生するためには、ハッシュと文字列_'castle'_の両方がPHP)のように見える必要があるため、これはうまくいきません。

17
Younis Bensalah

私はPHP 5.5.9でテストできませんでした。提案しようとしていることが私のPHP 5.6.22 (しかし、私はいくつかの愚かな間違いをしたかもしれません)。

私が理解できる唯一の回避策は、MD5が数値として処理されるものを返す場合です。私はGoogledを見つけて 関連性のあるもの を見つけました。

9
LSerni

Gabedwrdsソリューションを受け入れたようです(ちなみにこれは優れています)が、興味深いペンテストを行うときに過去に使用した可能性のあるソリューションを1つ投稿したいと思います。 (私は決してその分野の専門家ではありませんが、私は時々ホビストです。

気が付くと、スクリプトはユーザーの中止を処理するためのポリシーを設定しません。デフォルトでは(PHP ini)で他に構成されていない限り)、ページのロード中にユーザーが接続を中止すると、PHPスクリプトはすぐに終了し、すべてを停止しますこのため、接続を適切なタイミングで実行すると、$_SESSION['admin_level']=1;と条件付きの評価の間の接続を中止し、サーバーに強制的に条件付きの評価を終了せずにスクリプトをすぐに終了させることができます。原因admin_levelがゼロにリセットされます。

もちろん、これはignore_user_abort=1がないPHP構成に完全に依存しています。そのため、ユーザーが中止しても続行するように設定されている場合、権限はリセットされます。

このエクスプロイトを使用する機会を増やすために、passペイロード/変数データのサイズを増やすことができます。 md5はチャンク単位でハッシュする必要があるため、passデータのサイズを増やすことで、md5関数がハッシュの計算により多くの時間を費やすようになり、大きなギャップが生じます。接続を中止する必要がある時間。

4
Spencer D

./ascii.txtを変更できると想定して、このテキストを中に入れます。

<?php

override_function('md5', '$a', 'return "castle";');

そして、それはうまくいくはずです。

2
peterpeterson

他の人が言ったのと同様に、PHPには最大メモリサイズがあります。POSTを入れた場合、ALMOSTのすべてのメモリを使用するのに十分な大きさのデータがアップすると、メモリ不足になった場合、この行に正確に到達するとクラッシュする可能性があります。

echo '間違ったまたは空のパスワードです。'

これは次の3つの原則に基づいています。

1)セッションが有効になっている場合、PHPは出力をフラッシュせず、代わりに、ページがレンダリングされるまで、すべてをRAMに保存します。

2)PHPには、各リクエストに割り当てられた最大サイズRAMサイズがあり、到達するとスクリプトがクラッシュします。

3)新しい行が書き込まれると、より多くのRAMを使用し、残りのRAMを使い果たします。

上記の事実を踏まえると、HTTP POST data in your HTTP request(ex:$ _POST ["data"] = "largestring")を追加すると、メモリ不足エラーがトリガーされる可能性があります$ _SESSION ["admin_level"] = 0が実行される前。

実際のシナリオでは、PHPにも最大のPOST本体サイズ、最大ヘッダーサイズ、およびそれをホストしているサーバーコンテナーがあるため、これはほとんどありません。 (nginx、Apacheなど)にも通常、最大制限があります。これらの最大制限のすべてに達する可能性がありますが、適切に構成されていない場合、$ _ SESSION ["admin_level"] = 1になると、実質的にいずれかの管理者になります。この方法を使用するウェブサイトの他のページ。

pdate:別の同様の方法は、大きなパスワードを入力して、md5()関数が何かまたは何かを処理しているときに失敗し、メモリ不足のために再度クラッシュするようにすることです。 md5()が内部でどのように動作するかによって異なります。 $ _POST ["pass"]フィールドのコピーを作成している可能性があるため、$ _ POST ["pass"]が巨大な場合、このコピーがすべてのRAMそしてそれをクラッシュさせます。

2
Jacob Beasley