安全なWebアプリケーションの作り方[1-4.4章]
ハッカー(イメージ MR.ROBOT より)
安全なWebアプリケーションの作り方の「4.4 SQLインジェクション」までを読んだので備忘録として整理。
体系的に学ぶ 安全なWebアプリケーションの作り方 第2版[固定版] 脆弱性が生まれる原理と対策の実践 | 徳丸 浩 | コンピュータ・IT | Kindleストア | Amazon
どんな本?
- Webサイトのセキュリティに関する情報を網羅的に紹介している。最低限のフロントエンドとしての知識があれば理解できるような丁寧な説明がある。
- また全ての項に対応するよう実習用の環境が用意されており、ページとサーバーのやりとりを見ながらどのような脆弱性があるのか学習でき、非常にわかりやすい。 実際に文章で言われるより遥かに説得力もある。
- 多くの脆弱性はは最近のフレームワークでは標準で対策されている。安心だね!
- しかし、実際にどのような基本攻撃があるのかを知っておかなければさらに発展的な攻撃にも対応できないと考える。しっかりと読みたい。
この記事について
1-4.4章までを読み、自分が特に気になった箇所を整理した。
HTTPとセッション
HTTP認証
ステートレス認証ともよばれ、Basic,NTLM、Digest認証などがある。
特徴 例:Basic認証
Basic認証では401を返した後フォームを入力するとBase64エンコードされたIDとPassがAuthorizationヘッダーとして送られる.
以降のやりとりでは自動的に付与されるAuthヘッダーにより「毎回認証」を行なっている。
メリット
やりとりのどのタイミングから始まっても認証が切れない
デメリット
一度離れたら再度認証が必要。IDとPASSしか記録できない上、ヘッダーに保存することしかできない
クッキー
- 初回時にセッションID名のクッキーを保存するよう,ブラウザにレスポンスで指示する.(実際の挙動をWASPで確認する)
- 以降はこのセッションID名のクッキーをサーバに送信する
セッションIDに求められるもの
- 第三者がセッションIDを推測できないこと
- 第三者からセッションIDを強制されないこと →セッションID固定攻撃を防ぐため.不正なセッションIDを強制的に付与され,その後保存した値を抜き取られる. →認証完了時点でセッションIDを変更することで防げる
第三者にセッションIDが漏洩しないこと →ネットワーク上で盗まれる可能性
クッキーにはセキュア属性を付与することができる.
- HttpOnly属性を設定するとJavascriptによるXSSでは盗むことが難しくなる.
- つけておくと良い。
- SameSite属性.
php SameSite = Lax
を指定すると他サイトからのPOSTで遷移した際にクッキーが送信されなくなる.CSRF対策になる.
- HttpOnly属性を設定するとJavascriptによるXSSでは盗むことが難しくなる.
クッキーの脆弱性をついた攻撃例
XSS
iframeに脆弱なサイトURLとともにscriptを埋め込んで読み出す。
検索キーワードに脆弱性があるサイト利用者の攻撃を想定
脆弱性のあるサイトからセッションIDを盗み、攻撃者のサイトに遷移させ送信する。
クッキーの属性にhttpOnlyをつけ、JSによる呼び出しを防ぐことで対策
4章 Webアプリケーションの機能別に見るセキュリティバグ
表示の脆弱性による攻撃-画面書き換えによるもの-
入力フォームに脆弱性がある場合、
(OWASPのresを見せながら実演) 今回は
<input type=text name=mail value=<?php echo $_GET['p']; ?>>>
のように属性値をダブルクオーテーションで囲わなかったことが脆弱性に繋がっていた。 このようなメタ文字の持つ特殊意味を利用して行われるのがXSS。回避するためにはHTMLの「エスケープ」を行い、意味を打ち消す
ただしダブルクオーテーションで囲っていてもダブルクオーテーションをエスケープしないと
"script = ... "
のような攻撃から守れない。
エスケープ方法
htmlspecialcharsを使ってPHPではエスケープする。
Vueのセキュリティ
- HTMLエスケープは自動。安全なHTMLであれば明示して描画できる(
v-html
) - URLの挿入対策にはsanitize-urlというライブラリがある
v-htmlの値にユーザーからのinputを渡さないこと(このような攻撃が可能 https://qiita.com/tnemotox/items/b4b8f0f627e23dd62447)
表示の脆弱性による攻撃-XSS-
上述済
入力による脆弱性
ヌルバイト攻撃
バイナリセーフ:どのようなバイト列であっても扱えることを意味する。値ゼロ\0が来ても続けて読み取る。Cなどではヌルバイトは末端記号と扱うため「バイナリセーフ」ではない。
そのため 2 \00 <script>...
のような文字列を入力として受け取ると、チェックを素通りし\00 以降のスクリプトが実行されてしまう(実演)
入力値の検証には正規表現で指定した形式にマッチしているか判定するのがよい。
SQL呼び出しに伴う脆弱性 -SQLインジェクション-
攻撃する側としてまず何をするのが効率いいのか?
IMFORMATIONS_SCHEMA
というSQL標準規格のテーブルを表示させよう。
これによりtable/rowの定義を表示させらられる。 得られた情報から欲しい情報が入っていそうなtable/rowを優先して攻撃する。
UNION SELECT
を使う。
- 二つのSQL文の結果を結合して求められ得る
- 一度の攻撃で大量のデータを取得できる。
対策:プレースホルダーを使おう
- 特にユーザーが指定できる値については変数でJSの変数で代入させるのではなく、placeholderを使うべき
ここまでのまとめ
ほとんどの攻撃は最新のフレームワークでは標準で対策されているが、実装者も気をつけなければ知らずに「対策の例外処理」を実装してしまいかねないと感じた。 CTFにも役立ちそう。 後半はさらに複雑な攻撃も登場するので楽しみ。