徳丸さんの練習問題を考えてみます。
お題
お題のSQL組立文字列は、このようになっています。
"SELECT * FROM users WHERE userid = '$userid'"
$userid
には好きな文字列を入れることができますので、SQLインジェクションし放題というわけです。
結論から考える
認証処理の部分は次のようになっています(一部書き換え)。
password_verify($_POST['password'], $user['password'])
$user['password']
に任意の文字列を入れることができれば、認証突破できそうです。
# お題はSQLインジェクションですから、PHP固有の問題ではないですよね。きっと。
任意の結果を返すSQLを考える
WHERE 句をいじりまわしても、GROUP BY やら ORDER BY やら使っても、任意の結果は返せません。
なにか使えましたっけ?
・・・
・・・・・
・・・・・・・
そういえば UNION というものがありました。
O/Rマッパー脳は、すっかり忘れていましたよ。
UNION をインジェクションする
どんな列を返せばよいか、あらかじめわかっているホワイトボックスハックですので、さっくりといってみます。
こんなSQLでいけるでしょうか?
SELECT * FROM users WHERE userid = ''
UNION
VALUES (NULL, 'Admin', 'ハッシュ化したパスワード', NULL) --'
パスワードを abc とすると、ソルト付きハッシュは $2y$10$NzNs.erlBALZjj2YZJTtl.9wfZcB7dv00OgwF7Dn6BG6XcpBoeCEq
です。
試してみます。
成功しました。
参考サイト
ひとりごと
それにしても、PHPにはpassword_verify
なんていう、 きな臭そうな(偏見) 便利な関数があるんですね。使ったことなかったです。