この記事は「パスワードがハッシュ値で保存されているサイトのSQLインジェクションによる認証回避の練習問題 - Qiita」の続編です。
前回までのあらすじ
SQLインジェクションによる影響として、認証回避の例がよく紹介されます。よくある「'OR'a'='a」を入力するパターンはよく見かけるところですが、パスワードがハッシュ値で保存されているケースについても認証回避が可能なケースがあることを示しました(参考:解答編)。
パスワードがペッパー付きハッシュ値で保存されているとどうなる?
今どきはパスワードはソルト付きハッシュ値で保存することが常識になっていますが、加えて「ペッパー(pepper)」というものを付加した方がよいという流れになってきています。ソルトがユーザー毎に異なる文字列であるためにハッシュ値とセットで保存するのに対して、ペッパーは固定値であるもののデータベースとは別の安全な場所に保存できる点が異なります。以下を参考にしてください。
ペッパー(シークレットソルトと呼ぶ場合もある)の実装は様々で、Dropboxのようにソルト付きハッシュをさらにAES等で暗号化する場合(参考)もあれば、Rubyのdevise gem(ライブラリ)のように、ハッシュ計算の前にペッパーをパスワード前後に連結するだけの場合もあります。下記はdeviseのハッシュ値計算の部分ですが、ペッパーがあれば、それをパスワードの後ろに連結しています(GitHUbリポジトリ)。
def self.digest(klass, password)
if klass.pepper.present?
password = "#{password}#{klass.pepper}"
end
::BCrypt::Password.create(password, cost: klass.stretches).to_s
end
練習問題を作ってみた
と言う前提で、今回の練習問題はdevise方式を採用しました。下記はログイン処理のペッパーを使う箇所です。
$pepper = file_get_contents('../pepper.txt');
$password = $_POST['password'] . $pepper;
ペッパーは、上記のように外部から閲覧できないディレクトリに保存されており、SQLインジェクションでは取得できません。
この条件でSQLインジェクションによる認証回避の練習問題を作ってみました。
ソースコードは、GitHubのリポジトリからダウンロードして、Dokcerコンテナとして実行できます。
$ git clone https://github.com/ockeghem/SQLi-to-bypass-auth2.git
$ cd SQLi-to-bypass-auth2
$ docker compose up -d
http://localhost:8901/ にアクセスすると以下のログインフォームが表示されます。
前回の問題とは異なり、利用者がユーザー登録できます。ログイン後に「マイページ」に遷移して、adminの情報が表示できれば攻撃成功です。
ペッパーはコンテナにアタッチすれば参照できますが、それはルール違反とします。ソースコードやテーブル定義は見てもよいことにしますが、「見なくても攻撃できる」方が良い解答とします。 なお、想定攻撃経路は2種類あります。2種類とも解答できれば完答とします。後述のように、sqlmap等のツールは使用可とします。
sqlmapをバンドルしました
この練習問題ではsqlmap等のSQLインジェクション診断ツールを使ってよいレギュレーションとします(明言してなかったものの前回もだめだったわけではありません)。インターネット世界のサイバー攻撃ではsqlmapが使われる可能性はあるので、sqlmapを使って良いというのは現実的なシナリオです。
sqlmapに親しんでいない参加者の便宜のため、sqlmapコンテナを用意しました。以下でsqlmapを利用することができます。Linux風のプロンプトとなっていますが、Windowsでも同じコマンドで実行可能です。
$ docker compose exec sqlmap /bin/bash
...さまざまな表示
# python sqlmap.py -u http://php/
上記のように、コンテナ内からターゲットサイトには http://php/ でアクセスできます。sqlmapの詳細についての解説は割愛しますので適当な解説記事を参照ください。
脆弱性診断用ツールは、自身が管理するサイトあるいは許可を得たサイトにのみ使用ください。これはsqlmapに限らないことですが、sqlmapは許可なく使用すると違法行為になる可能性が特に高いツールですのでご注意ください。
想定正解については、数日後に公開したいと思います。
※ これから解かれる人もいるので、X(Twitter)やブックマーク、この記事のコメント欄などに解答やヒントは書かないでください。ご自身のブログやQiita等に書くのはかまいません。
追記(2023年9月26日)
解答編を投稿しました