連日投稿25日目。今回はCSRFを悪用して不正なパスワード改ざんを再現。そしてブラウザの防御機能がどう働いてるのかについて理解。
今回の目的
昨日のXSS、一昨日のSQLiに続き、手動診断シリーズ第三弾。今回はCSRF(クロスサイトリクエストフォージェリ)に挑戦する。
- CSRFという言葉は知っているが、どういう仕組みで攻撃が成立するのか、いまいちピンと来ていない。
- XSSと何が違うのか、攻撃者の視点で具体的に理解したい。
- 最近のブラウザでは対策されていると聞くが、それがどういうものなのか実際に体験したい。
目標は、DVWAのCSRFページにて脆弱性を発見し、パスワードを強制的に変更させる攻撃を成功させること。そして、その過程でブラウザの防御機能について(SameSite Cookie)も学ぶ。
このチャレンジについて
目的: セキュリティエンジニアとしての技術力向上
手段: 手動での脆弱性診断を通じて学習
実施する事: CSRFの発見、悪用、そして現代のブラウザによる防御機能の理解
目次
実行結果
最終的に、被害者がリンクをクリックすることで、意図せずパスワードをhackedに変更させてしまう攻撃に成功した。
攻撃用HTML (attack.html):
<h1>Visit my page!</h1>
<a href="http://<DVWAのIP>/vulnerabilities/csrf/?password_new=hacked&password_conf=hacked&Change=Change">Click here to claim!</a>
ユーザーがこのページのリンクをクリックすると、DVWAにログイン済みのブラウザが認証情報(Cookie)を付与してリクエストを送信。結果としてパスワードが変更され、元のパスワードではログインできなくなる。

実行環境
- テスト対象: DVWA (Docker上で稼働)
- セキュリティレベル: Low
- 使用ツール: Webブラウザ, ブラウザのDeveloper Tools (F12)
開発ステップ
-
正常な動作の確認: まずは正規のフォームでパスワードを変更し、URLにパスワード情報が平文で含まれる
GETリクエストが使われていることを確認。これが脆弱性の最初の兆候。 -
攻撃用URLの作成: 確認したURLを元に、パスワードを
hackedに変更するためのURLを組み立てる。# こういう事ね `http://<IP>/vulnerabilities/csrf/?password_new=hacked&password_conf=hacked&Change=Change` -
第一の攻撃(失敗):
<img>タグのsrcに攻撃用URLを埋め込み、被害者がページを開くだけで攻撃が発動する、ステルス性の高い攻撃を試みる。しかし、攻撃は失敗。
srcのタグは普通画像の挿入とかに使われるタグ。だからこの行が実行されるとサーバーに画像読み込み処理が走る。その時にパスワード改ざんをねじ込む想定だった。<h1>Visit my page!</h1> <img src="http://<IP>/vulnerabilities/csrf/?password_new=hacked&password_conf=hacked&Change=Change" width="1" height="1"> -
原因調査: ブラウザのDeveloper Toolsを使い、Cookieの
SameSite属性に値が入っていない事を確認。これにより、ブラウザがデフォルトのSameSite=Laxポリシーを適用し、<img>タグのようなクロスサイトリクエストにCookieを送信しないように防いでいることを突き止める。 -
第二の攻撃(成功):
SameSite=Laxの制約を回避するため、ユーザー自身にリンクをクリックさせる方法に切り替える。<a>タグで攻撃用URLへのリンクを作成し、ユーザーを誘導することで攻撃を成功させた。
開発中の気づき
SameSite Cookieってなんや
検証開始当初、<img>タグを使った静かな攻撃を試みたが、全く機能しなかった。
attack.htmlのコードは問題なさそう...何が気に食わんねん
調べてみると、SameSiteっていう Cookieの属性が関係してそう。
ブラウザのDeveloper Tools(F12おしてね)で調べてみる。ApplicationタブでCookieを調べると、PHPSESSIDのSameSite属性が空欄になっている。
え、空なんすけど...
なんやかんや調べてみると、これが空欄の場合、最近のブラウザはSameSite=Laxとして扱うらしい。
で、Laxは、「リンクのクリックやURLの直接入力のようなトップレベルのナビゲーション(なにをもってトップなのかはよく理解できてない)」でなければ、別サイトからのリクエストにCookieを乗せない、という設定。つまり、<img>タグによるリクエストは、ブラウザによってブロックされてる。っぽい。
なんとなく、自分が普段ブラウザの標準的なセキュリティ機能に助けられてたのかな~と妄想。
で、どうすんのか
SameSite=Laxが標準で備わってるならもう回避するしかない。<a>タグでユーザーにリンクをクリックさせる方法に切り替えた。
<a href="...">Click here to claim!</a>
これをクリックすると、見事にパスワードが変更された。しかし、攻撃後、被害者の画面は「Password changed」と表示されたDVWAのページに遷移してしまう。攻撃がバレバレ。
回避はできたけど、攻撃の「ステルス性(静かさ)」と「成功率」がトレードオフになるのね~。
<img>タグは静かだけど防がれて、<a>タグは成功するがばれる。
コードの詳細な解説
CSRF攻撃用URL
http://<IP>/vulnerabilities/csrf/?password_new=hacked&password_conf=hacked&Change=Change
このURLのポイントは、パスワード変更に必要な全ての情報(新しいパスワード、確認用パスワード、そして実行のトリガーであるChangeボタン)が、一つのURLに全て含まれていること。認証済みのユーザーがこのURLにアクセスするだけで、意図しない操作が実行されてしまう。
まとめ
CSRFは、単にリクエストを偽造するだけの単純な攻撃だと思っていたが、実際にはブラウザのセキュリティ機能が貢献していて奥が深いと感じた。SameSite Cookieという具体的な防御策に直面し、それをどうやって回避するのかを考える過程は、まさに実践的なトラブルシューティングだった。机上の知識だったものが、手を動かすことで、生きた経験として身についてきた。
