こんにちは。GMOインターネットグループ株式会社 セキュリティエンジニアの赤瀬です。私は2021年に新卒入社し、現在はセキュリティチームでWebアプリケーションの脆弱性診断を行っています。まだ脆弱性診断を始めて2年目のひよっこエンジニアです。脆弱性の勉強+知識の定着を兼ねて今回記事を執筆することになりましたので書いていきます。
はじめに
開発経験がある人でもない人でもエンジニアをやっている人が一度は聞いたことがあるであろうクロスサイトスクリプティング(以下、XSS)には大きくわけて反射型、蓄積型、DOM-Based XSSの3種類があります。簡単に上記3種類の説明を(ほんとにさらっとだけ)
反射型XSSユーザからのリクエストに含まれるスクリプトをそのままレスポンスに出力してしまい発動するXSS蓄積型XSSユーザが入力したスクリプトがWebアプリケーションに保存され、別のユーザがその保存箇所を読み込んだ際に保存されたスクリプトが発動するXSSDOM-Based XSSJavaScriptを使ってブラウザに表示しているHTMLを操作する場合に、攻撃者の用意した意図しないスクリプトが発動するXSS
その中でも今回は、蓄積型XSSについて実際にWeb画面で挙動を紹介できればと思います!
1.注意事項
検査により、意図せずにシステムの停止や不具合を引き起こしてしまう可能性があるため、紹介する手順を試してみたい場合は本番に影響を及ぼさない検証環境か、それ専用に作られたテストサイトでの作業をお勧めします。自組織が管理しないWebアプリケーションへの検査は、場合によっては不正アクセスとして違法となる可能性があります。
2.蓄積型XSS
XSSとは、Webサイトに攻撃者がスクリプトを登録しておくことで、一般のユーザにそのコードを実行させること。攻撃例をあげると、Cookieの情報を抜き取ったりするなどがあります。今回紹介する蓄積型XSSというものは、攻撃者がWebサイトに直接スクリプトを登録し、そのWebサイトの一般利用者が該当のページを読み込むたびにそのスクリプトが実行されてしまうものです。
百聞は一見にしかずということで、実際にどういうのか見てみましょう。※今回は自分のローカル環境にECサイトっぽいものを作成して利用しています。※CSSなど凝ったものを作っていないのでサイトの見た目はご容赦ください。
ということで早速画像のような商品登録画面があるとします。今回は、商品登録を管理者ページでしかできないようなサイト仕様にしました。
普通の利用者が見る商品一覧ページはこんな感じです。最低限の実装って感じですね(自分で作ったんですけど)。
ということで、先程の管理者ページに何らかの方法で攻撃者がアクセスし商品登録できると仮定してスクリプトを仕込んでいきたいと思います。わかりやすいように下記のデータを商品として登録していきます。
商品名:スクリプト商品説明:’任意’ <script>alert(1);</script>価格:500円
無事登録することができました。本来、ここで<>のような記号が入力値にあった場合にそもそも登録できないようにしたり、特殊な意味を持つ記号をサニタイジングして登録する必要があります。
スクリプトを登録することができたので、一般利用者がサイトを利用する際にどういう挙動になるか見てみましょう。利用者は普通のECサイトだと思い商品一覧ページにアクセスします。すると先程登録したスクリプトが読み込まれ処理が実行されるので画像のようにJavascriptのホップアップがあがりました。
3.Cookie拾ってみる
上記を応用してJavascript内にCookieを表示させセッションIDなど取得してみようと思います。といってもやり方は先程同じで登録するデータの値を下記に変更するだけでCookieを取得することができます。
商品名:クッキー商品説明:’任意’ <script>alert(document.cookie);</script>価格:500円
登録できたので商品一覧ページにアクセスしてみます。 すると画像のようにPHPSESSIDをまるっと取得することができました。
少し見辛いですが、商品一覧ページのレスポンスを見てみるとスクリプトがそのまま登録されています。これにより利用者がサイトを読み込むたびにスクリプトが実行されてしまい、Cookieの情報を窃取されてしまいます。Cookieを窃取されてしまうとアプリケーションをのっとられたり、クレジットカード番号などの個人情報を不正に閲覧される可能性があります。
4.対策
3.の中でも少し触れましたが対策方法はいくつかあります。
今回はこんな対応方法があるよ!というのを一部紹介するので、その他の対策方法や、実装方法について詳細気になる方は是非調べてみてください。
対策方法
そもそも<>などの特殊な意味を持つ記号を登録しようとした際にエラーとして登録できないようにする。例)電話番号の入力欄は数字のみ許可。ふりがなは半角カタカナのみ許可。など入力データをそのまま登録せず、登録する際にサニタイジング処理を行う。サニタイジングとは「無害化」という意味で<>、&などの記号を「<」「>」などに置換することでスクリプトとして処理が実行されないようにすることです。
5.おわりに
いかがでしたでしょうか。文章だけだとわかりづらい脆弱性の挙動も、Webサイトの画面を見ながらだと意外とわかりやすい気がしてきませんか?この記事を読んでくださった方が自分の作成したサイトや今後開発を行う際に、入力値のサニタイズなど気にかけるようになってくれれば幸いです。