「攻撃者がどうやって脆弱性を見つけ攻撃するのか」これは比較的よくセキュリティ対策で解説されていることだと思います。本質を理解し、対策を考えます。
攻撃者がどうやって脆弱性を見つけ攻撃するのか
基本的にソフトウェア脆弱性はバグです。今回は攻撃者が内部構造を知らないブラックボックス型の攻撃を行う際に、ソフトウェアの内部に潜むバグをいかに利用して攻撃するのか考えます。
攻撃者がソフトウェアを攻撃する場合、ソフトウェアが不正な入力に対して本来あるべき動作をするか、しないかチェックします。攻撃者が自分で考えなくてもJavaScriptインジェクション用ならOWASPに文書としてまとめられています。
XSS Filter Evasion Cheat Sheet – OWASP
';alert(String.fromCharCode(88,83,83))//';alert(String.fromCharCode(88,83,83))//"; alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//-- ></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>
'';!--"<XSS>=&{()}
攻撃用の文書でなくても、防御用の文書からもどのような入力を行なえば、ソフトウェアが誤作動するか分かります。
SQL Injection Prevention Cheat Sheet – OWASP
以下はMySQLが特殊な文字(意味を持つ文字/エスケープが必要な文字)として扱う文字の一覧です。
NUL (0x00) --> \0 [This is a zero, not the letter O] BS (0x08) --> \b TAB (0x09) --> \t LF (0x0a) --> \n CR (0x0d) --> \r SUB (0x1a) --> \Z " (0x22) --> \" % (0x25) --> \% ' (0x27) --> \' \ (0x5c) --> \\ _ (0x5f) --> \_ all other non-alphanumeric characters with ASCII values less than 256 --> \c where 'c' is the original non-alphanumeric character.
この他にみセキュリティフィルタ回避の為、JavaScriptと同様にchr()関数などが利用されます。
OWASP Testing Guide Appendix C: Fuzz Vectors
攻撃者はエンジニアリング化された攻撃を行います。Fuzzing(ファジング)はその良い例です。ブラックボックス型で攻撃してくる攻撃者はどこに含まれているか分らない脆弱性を一々手動で試行錯誤しません。Fuzzingと呼ばれるテクニックを利用して機械的に攻撃を行い、レスポンスの違いによって脆弱性がありそうな(攻撃できそうな)入力に着目して更なる攻撃を行います。
攻撃者は意味を持つ文字をインジェクションする
攻撃者の目的はブラウザ、SQLデータベース、LDAP、XPath、コマンド、SMTPなどに開発者が意図しない「意味を持つ文字」をインジェクションし、不正な操作(プログラムの実行、不正なデータ取得/改竄)をおこなう事です。
OWASP Secure Coding Practices – Quick Reference Guide
では以下の文字がリスクが高いとしています。
- < > ” ‘ % ( ) & + \ \’ \”
この他にも、改行文字や制御コード、壊れた文字エンコーディング、大きすぎるデータ(量および数値)などもリスクが高い入力です。※
※ ブラックリスト型の入力バリデーションは行わないように!セキュリティ対策の基本はホワイトリスト型の対策です。
攻撃者が送ってくる「意味を持つ文字」を含む入力の多くは、アプリケーションにとっては「不正な入力値」です。
参考:
意味を持つ文字のインジェクションに対する対策
ソフトウェア開発者が知っておくべきセキュリティの定義/標準/ガイドでは入力バリデーションと出力の安全対策を確実に行いなさい、と解説しています。意味を持つ文字のインジェクション対策は
- 確実な入力バリデーション
- 確実な出力制御
が対策になります。このためCWE/SANS TOP 25では入力制御を一番目のセキュリティ対策、出力制御を二番目のセキュリティ対策としています。
リスクが高い意味を持つ文字を受け入れる必要がないのに受け入れるコードは危険である、という事実に議論の余地はありません。まずセキュリティ対策として確実に入力バリデーションします。
次に大切なのは確実な出力制御です。
7. 他のシステムに送信するデータを無害化する
コマンドシェル、リレーショナルデータベースや商用製品コンポーネントなどの複雑なシステムへの渡すデータは全て無害化する。攻撃者はこれらのコンポーネントに対してSQL、コマンドやその他のインジェクション攻撃を用い、本来利用してない機能を実行できることがある。これらは入力バリデーションの問題であるとは限らない。これは複雑なシステム機能の呼び出しがどのコンテクストで呼び出されたか入力バリデーションでは判別できないからである。これらの複雑なシステムを呼び出す側は出力コンテクストを判別できるので、データの無害化はサブシステムを呼び出す前の処理が責任を持つ。
CERT Top 10 Secure Coding Standardでは明示的に入力バリデーションは出力の安全性に責任を持たないとしています。セキュリティ確保の為に必要な確実な出力制御は入力バリデーションと独立して行わなければなりません。例えば、同じ入力パラメーターがHTML、SQL、LDAP、XPath/XQueryやOSコマンドの一部として送られる事はよくあります。出力制御と入力制御が独立した制御であることにも議論の余地はありません。
まとめ
ソフトウェアセキュリティを論理的に考えると、入力処理時に無用なリスクを許容しない、出力時に安全な出力を行う、が最も重要な対策になます。つまり
- 確実な入力バリデーション
- 確実な出力制御
がソフトウェアがまず最初に行うべきセキュリティ対策となります。現実的にも、バッファーオーバーフロー、JavaScriptインジェクションなどのインジェクション攻撃がソフトウェア脆弱性の大多数を占めています。インジェクションできる出力先はメモリ、ブラウザ、データベース、メールシステム、Webシステムなど多岐に渡ります。これの出力先への安全対策を知ることも重要ですが、まずセキュアなアーキテクチャの概念を理解していないと、木を見て森を見ない対策になってしまいます。
一部のセキュリティ専門家や開発者が入力バリデーションはセキュリティ対策ではない、といった理解し難い主張をすることを散見します。これはITセキュリティの定義を理解していない、根本的に誤っている主張と言えます。
入力バリデーションを行わないソフトウェアで利益を得るのは攻撃者と一部のセキュリティ業者だけです。開発者やソフトウェアの利用者の利益にはなりません。論理的にも、現実的にも正しいセキュリティ対策を実践してください。
参考:
OWASP TOP 10はここで記述している考え方でのセキュリティ対策をTOP 10の脆弱性にいれました。
論理的にセキュアな構造を考えるとバリデーションの種類は3つに大別できます。
バリデーションはホワイトリスト型でするものですが、ホワイトリストでもリスクがある入力を許可する必要があります。その際にどういった入力データがリスクを持っているのか、理解していると役立ちます。
実はOWASPも入力バリデーションがセキュアな構造のソフトウェアには必須中の必須と考えています。これはOWASPの別のガイドや初版のTOP 10から明らかです。
セキュアなソフトウェアには正しい”ロジック”と正しい”データ”の両方が欠かせません。問題が発生した”コード”に着目しても、根本的対策にはなりません。
ブラックリスト型でダメな物を定義する対策は雑なセキュリティ対策です。ブラックリストは構造的に脆弱だからです。
リスク分析はそれほど難しい物ではありません。コツさえつかめば誰でもできるようになる物です。単純に体系的にリスク分析をしよう、と思っていなかったことが不十分なリスク分析をしてしまう原因だと思います。
Leave a Comment