安全なwebアプリケーションの作り方を読んだ
こんにちは。秋ですね。
昨日暖かかったし、今日は半袖で行けるやろって外出して後悔しています。
アラサー男とは思えない軽はずみな判断に我ながら絶句しています。
それでも今日も僕は元気です。
そんなどうでもいいことはともかくとして、
今回は「安全なWebアプリケーションの作り方」を取り上げます。
この本を読もうと思った背景ですが、ズバリ上司からの指摘です。
基本情報は取ったから知識としてはあっても、
それが実際の開発においてどう対策されているかといったことが分かっていない、と。
おっしゃる通り。
そこでよさげな本を調べた結果、この本に行き着いたわけです。
というわけで、この本の全体の構成から入ります。
全体の構成
- 第1章 脆弱性とはそもそも何か
- 第2章 実習環境のセットアップ
- 第3章 HTTP、クッキー、セッション
- 第4章 Webアプリケーションの機能毎の脆弱性
- 第5章 代表的なセキュリティ機能
- 第6章 文字コードとセキュリティ
- 第7章 携帯電話特有の脆弱性
- 第8章 Webアプリケーション以外の側面からの安全性向上施策
- 第9章 開発プロセス
第1章 Webアプリケーションの脆弱性とは
脆弱性とは、悪用できるバグのこと。 セキュリティバグとも言う。
- 悪用の例
- 個人情報などの秘密情報を勝手に閲覧する
- Webサイトの内容を書き換える
- サイトを閲覧した利用者のPCをウイルスに感染させる
経済的損失、法的な問題への発展、利用者への回復不能なダメージ、
ボットネットワークへの構築なんかにつながるからダメ!!
- ボットネットワークとは? ボットとは、PCに感染後、外部からの指令を受けて不正活動を行うマルウェアの事。 ボットネットワークとは、脆弱性のある改ざんされたWebサイトを閲覧した利用者のPCが ボットに感染して、そうしたPC同士がネットーワーク化した状態のこと。 攻撃者はボットネットワークを使ってDDos攻撃や迷惑メール送信を行う。
脆弱性には2種類ある。
- バグによるもの
- セキュリティ意識の不足からチェック機能が不足しているもの
脆弱性はバグだけではなくHTTPSを使っていないなど、セキュリティ機能の不足も含まれる。
第2章 環境設定
mac * vagrant なので、このサイトを参考に環境構築。
第3章 Webセキュリティの基礎
HTTPやセッション管理についての知識がなければ脆弱性を作り込む原因になるためHTTPを学ぶ必要がある。
GETとPOSTの使い分け
- GET
- 参照(リソースの取得にのみ用いる)
- データ更新など副作用を伴うリクエストには用いない
- POST
- 送信データが多い場合
- 秘密情報を送信する場合
- データ更新など副作用を伴う場合
セッションとクッキー
- クッキーセット、クッキーを含めたリクエストの流れ
- アプリケーションデータの保持のためにクッキーは通常利用しない
- クッキーが保持できる値の個数や文字列長には制限があるから
- クッキーの値は利用者本人には参照・変更できるので、秘密情報の格納に向かないから
- クッキーには整理番号としてのセッションIDを格納しておき、実際の値はサーバー側で管理する。
- クッキーの属性
- Domain
- Path
- ブラウザがクッキー値を送信するURLのディレクトリ
- Expires
- クッキー値の有効期限。設定しない場合はブラウザの終了まで
- Secure
- SSLの場合のみクッキーを送信
- HttpOnly
- JavaScriptから送信できないようにする。
- クロスサイトスクリプティング等の脆弱性対策として有用。
受動的攻撃と同一生成元ポリシー
- Webアプリケーションに対する攻撃は2種類ある
- 能動的攻撃
- 攻撃者がWebサーバーに直接攻撃すること
- 受動的攻撃
- Webサイトの利用者に罠を仕掛けることで、罠を閲覧したユーザを通してアプリケーションを攻撃すること。
- 罠サイトへの誘導、正規サイトに罠を仕掛けるなど。
- 同一生成元ポリシー
- JavaScriptで異なるホストからのアクセス(クロスドメインアクセス)を拒否すること
- 同一生成元(同じホスト)である条件
- 第三者のJavaScriptを許可することもある
- JS以外のクロスドメインアクセス
Webアプリケーションの機能別に見るセキュリティバグ
脆弱性の分類
- 脆弱性は大きく分けて2種類
- 出力に起因する脆弱性(=インジェクション系脆弱性)
- HTML、HTTP、SQLなど、Webアプリケーションに関わる技術がテキスト形式のインターフェースであることを利用。
- カンマやタブ、シングルクオートなど、決められた文法を持っていることを利用して攻撃する。
- HTML、HTTP、SQLなど、Webアプリケーションに関わる技術がテキスト形式のインターフェースであることを利用。
- 処理に起因する脆弱性
- ディクトリラバーサル、クロスサイトリクエストフォージェリなど
- 出力に起因する脆弱性(=インジェクション系脆弱性)
入力処理とセキュリティ
- 入力値検証はアプリケーションの仕様に基づいて行う
- 文字エンコーディングの検証
- 制御文字を含む文字種の検証
- バイナリセーフな関数かどうかの確認も必要
- バイナリセーフ - Unixなどで文字列の終端を示す'\0'を示すを正しく扱えるかどうか
- バイナリセーフな関数かどうかの確認も必要
- 各パラメータの文字種や文字数の検証
クロスサイトスクリプティング(XSS)
- 外部からの入力に応じて表示内容が変化する箇所のHTML生成の実装の問題から生じる脆弱性
- (ex)フォームに入力した内容をそのまま次のページで確認するとする。
入力内容が「
<script>alert(document.cookie)</script>
」出会った場合、 クッキーが表示される。 - 上の例のように、サイト内容の書き換えやJSの実行などができる。
- (ex)フォームに入力した内容をそのまま次のページで確認するとする。
入力内容が「
- 3種類の被害
- クッキー値の盗難
- JSによる攻撃
- 画面の書き換え
- 対策
SQLインジェクション
データベースと連動したWebサイトで、データベースへの問い合わせや操作を行うプログラムにパラメータとしてSQL文の断片を与えることにより、 データベースを改ざんしたり不正に情報を入手する攻撃。また、そのような攻撃を許してしまうプログラムの脆弱性のこと。
例
- SQLインジェクションによる認証回避
- 下のように入力フォームの ID と パスワード を変数で直接SQLに入れているとき。
SELECT * FROM users WHERE id = "$user" AND password = "$id";
$user = 'yoshinaga', $password = ' " OR "a" = "a' とすると、下記のようなSQL文になる。
SELECT * FROM users WHERE id = "yoshinaga" AND password = " " OR "a" = "a";
id が存在する場合、ログインできてしまう。 同様の形で、データの消去、改ざん、挿入などが行うことができる。
- 考えられる被害
- データベース内の情報が盗まれる。
- データベースの内容が書き換えられる。
- 認証を回避される。 ( ID と password を用いずにログインされる )
- 対策
my $sql = 'SELECT id, name, weight, muscle FROM users WHERE muscle = ?'; my $sth = $dbh->prepare($sql); $sth->bind_params(1, '; DELETE FROM users;'); $sth->execute();
- 上の例の場合、プレースホルダを用いていなければusersテーブルのデータが全て消去されてしまうが、 プレースホルダを用いることによって、? 箇所に入る文字列が必要に応じてエスケープされるため、データ消去は起こらない。
クロスサイト・リクエストフォージェリ(CSRF)
決済、送金、ユーザー情報の変更など、ログインした利用者のアカウントにより行われる取り消しできない操作の脆弱性。
- 攻撃手順例
- 対策が必要な箇所
- 購入や変更などの実際に処理が行われる箇所
- 確認画面ではないので注意
- 対策方法
- その他の保険的対策
- 処理があったことをメール送信することで不正に早く気づける
セッションハイジャック
Webアプリケーションでは認証結果などの現在の状態を記録するのにセッション管理機構が使われている。 現在主流のセッション管理機構は、クッキーなどにセッションIDという識別子を記憶させて、 セッションIDをキーとしてサーバー側で情報を記憶する方法。 ある利用者のセッションIDが第三者に知られると、その利用者になりすましてアクセスできる。
- 第三者がセッションIDを知る手段
- 対策
- クッキー管理機構は自作せず、Webアプリケーション開発ツールのものを使う
- クッキーにセッションIDを保存する(URLではなく)
- 認証成功時にセッションIDを変更する(固定攻撃対策)
- 認証前にセッション変数に秘密情報を保存しない
リダイレクト処理関連の脆弱性
- オープンリダイレクト脆弱性
- HTTPヘッダインジェクション
- 2つの脆弱性への対策
- リダイレクト処理には極力専用のライブラリ関数を用いる
- リダイレクト先のURLを固定にする
- リダイレクト先のURLを直接指定せず、番号指定などにする
- リダイレクト先のURLのドメインを十分にチェックする
クッキー出力にまつわる脆弱性
- 基本的にはクッキーにはセッションIDのみを用いる
- クッキーは改変されうるため
- クッキーの流出を避けるため、https通信の場合クッキーにセキュア属性をつける
メール送信の問題
ファイルアクセスに関わる問題
OSコマンド呼び出しの際に発生する脆弱性
- シェル呼び出し機能を呼び出す関数(system関数)に外部からのパラメータを渡した場合に発生する
- 「;cat /etc/passwd」といったような変数が渡されると情報漏洩する
- 原則としてOSコマンドを使わない実装方法を使うこと
- シェル呼び出し機能のある関数を避ける
- 使う場合には外部から入力された文字列を渡さない、渡す場合はエスケープする等の処理を行う
ファイルアップロードに関わる問題
不正を働くスクリプトがアップロードされ、 そのスクリプトが公開サーバにあって直接アクセスできる場合には、 不正なスクリプトの実行によって情報が流出する恐れがある
- 対策
- 拡張子をチェックすること
- コンテンツ内容をチェックすること
- 画像として読み込めるかなど
- 公開サーバに置かず、スクリプトでアクセスするようにすること
長かったのでまとめ
- ライブラリが用意されている場合には独自実装せずに素直にライブラリを使うこと
- 外部から入力されるパラメータを処理すること
- 重要な処理がされる前にはサイド認証すること
- クッキーにはパスワードなど重要情報をセットしないこと
- クッキーのセキュア属性、ドメイン属性、HttpOnly属性など正しく設定すること
- ログイン操作がある場合には、ログイン時にセッションIDを変えるとよい
代表的なセキュリティ機能
認証機能
- ログイン機能のセキュリティに必要なこと
- 前章までのSQLインジェクション、XSS、セッションID固定化などの対策
- パスワードの文字種、桁数の要件を検討する
- ログインIDを公開しないこと
- 積極的なパスワードポリシーのチェック
- ユーザーIDと同じパスワードは弾くなど(ジョーアカウントと呼ばれる)
- 総当たり攻撃対策のため、パスワードの保存方法を工夫すること
- 自動ログインに関して
- エラーメッセージを詳細にしない
- IDが間違っています等、だと使用されているIDが判明してしまう
アカウント管理
- ユーザーが入力したメールアドレスは必ず受信確認を行う
- 重要な処理に際しては再認証
- 重要な処理のメール通知
- アカウント管理では以下の脆弱性が発生しやすい
- CSRF
- SQLインジェクション
- メールヘッダインジェクション
認可
- 認可とは認証された利用者に対して権限を与えること
- 認可不備が発生するケース
- URLやhiddenパラメータ、クッキーなどに権限情報を格納して、それが書き換えられる
- ディレクトリやファイル名の直打ちでアクセスできる
- 対策
- データベースでロール毎に管理するのが望ましい
- ユーザー1は、管理者権限。 ユーザーには一般ユーザー権限といった形で登録しておき、
それぞれの権限毎に実行できる処理、表示する情報を変えて、情報の表示・処理実行前に権限を確認する
- ユーザー1は、管理者権限。 ユーザーには一般ユーザー権限といった形で登録しておき、
- データベースでロール毎に管理するのが望ましい
### ログ
- ログの必要性
- 攻撃や事故の予兆をログから把握し、早期に対策する
- 攻撃や事故の予後調査のため
- アプリケーションの運用監査のため
- ログの種類
- 記録すべきログ
- ログイン・ログアウト(失敗も含む)
- アカウントロック
- ユーザ登録・削除
- パスワード変更
- 重要情報の参照
- 重要な操作
- ログ出力の実装はログ用のライブラリが言語毎にたいていは用意されている
文字コードとセキュリティ
Webサイトの安全性を高めるために
開発マネジメント
- 開発ガイドラインの策定
- 脆弱性毎の対処方法
- 認証、セッション管理、ログ出力の実装方式
- 各フェーズでのレビューとテストの方法
- 開発メンバーの教育による体制の整備
- 事件事例の紹介
- 主要な脆弱性の原理と影響
- 遵守すべき事項
- 開発プロセスの整備
おわりに
すみません、度を超えた長さになってしまいやした。
こんだけ色々書いといてなんですが、
一番重要なのは、
Webアプリケーションの機能別に見るセキュリティバグ
の章まとめとして書いた部分数行です。
読みながら自分の会社のアプリケーションのコードに出てくるような対策が出てきて、
うちはセキュリティちゃんとやってんだなぁ、と当たり前のことをしみじみ感じました。
それではみなさん、3連休明けの月曜日を張り切って迎えましょう、、、