インジェクション脆弱性の発生原理は簡単です。エンジニアではないマネージャー向けに作った資料を基に原理を紹介します。
インジェクション脆弱性は、その種類に関わらず原理は同じです。原理が同じということは、対策も同じです。一つ一つのインジェクション脆弱性がどのように作られ、攻撃されるのか?は少しずつ異なりますが、基本的な部分は同じです。別々に考えるより、一まとめに考えて理解した方が応用もでき、新しい仕組みなどが生まれた場合にも対応できます。
インジェクション脆弱性の原理
SQLインジェクションを例に説明します。
SQL以外でも同じ構造を持っています。
OSコマンド: ファイルの先頭から指定行数を取得するheadコマンドの例。
head -n $line $myfile
- head : 命令
- -n : 命令
- $lines : データ
- $myfile : 識別子
メールヘッダー: メール送信時に設定するヘッダーの例。直接SMTPサーバーなどに出力することを想定。
Subject: ${subject}\r\n To: ${mail_to}\r\n
- Subject : 命令(または識別子)
- $subject : データ
- \r\n : 命令
- To : 命令
- $mail_to : データ
- \r\n : 命令
※ メールヘッダーにインジェクションできるとメッセージの改ざんや送信先の追加が可能になる
インジェクション攻撃は”命令”、”識別子”、”データ”のどれかが変数で、攻撃者がその変数の内容を制御できる場合に発生します。制御できる変数に攻撃者の”命令”、”識別子”、”データ”を入れて不正な操作を行います。
基本的にはこれだけを知っていれば、ほぼ全てのインジェクション脆弱性を理解したことになります。
SQLインジェクション脆弱性の場合は以下のように攻撃者の命令が実行されます。
つまり、全てのインジェクション脆弱性はこういうことです。”命令”、”識別子”、”データ”、なんでも構わないので攻撃者の送ったデータが出力されてしまうことが問題となります。
これを理解するとセキュアと言われているAPIに不足している部分があることを簡単に自分で見つけられます。
原理を理解すれば、自分でいくらでもインジェクション脆弱性に対応できるようになります。利用する外部システムやライブラリが変わっても、どこが”命令”、”識別子”、”データ”なのか理解し、それらの安全性を保障すればOKです。インジェクション脆弱性は全ての脆弱性の大半を占めます。自分で対応できるメリットはとても大きいです。
インジェクション脆弱性に対する対策
攻撃者にはインジェクション脆弱性はすべて攻撃対象です。種類などは問いません。インジェクション脆弱性の原因は”攻撃者の入力を出力する”ことにあるので、
- 入力をバリデーションする (CERT TOP 10 Secure Coding Practices #1、CWE/SANS Monster Mitigations #1)
- 他のシステムに送信するデータを無害化する (CERT TOP 10 Secure Coding Practices #7、CWE/SANS Monster Mitigations #2)
を実践すれば対策は完了です。”他のシステムに送信するデータを無害化する”は
- エスケープ・エンコーディングの実行
- 余計な命令などが入らないAPIの利用
- バリデーションによる安全の確保
の3つの対策を知っていれば脆弱性を生まない必要十分条件を満たします。
セキュアプログラミングの本家と言えばCERT/カーネギーメロン大学ですが、日本では多少注意が必要です。
現在のISO 27002ではセキュアプログラミングは体系化されているので「セキュアプログラミング」とだけ記載しています。スライドに書いたようにIPAの「セキュアプログラミング講座Web編」はISOのいう「セキュアプログラミング」とは大きく異なり※ます。 ご注意ください。
※ IPAに問い合わせところ、この講座は削除されるとのことです。ISOの意図するセキュアプログラミングの一部は古いISO標準(ISO/IEC 27002:2005)を参照すると分かります。
まとめ
そもそもソフトウェアセキュリティ対策は”インジェクション脆弱性対策だけ”ではありません。機密性/完全性/可用性/信頼性/責任追跡性(否認防止)/真正性を保証しなければなりません。”妥当な入力データ”以外ではコンピュータープログラムは正しく動作できません。”妥当な入力データ”であること保証する入力バリデーションは全ての脆弱性対策の基本中の基本です。
セキュアなアプリケーションアーキテクチャーは簡単かつ分かりやすいです。
ISO27002でもセキュアなアプリケーションアーキテクチャーを採用するようにと記載されています。
入力バリデーションが「セキュリティ対策かどうか?」「セキュリティ対策としてどうでもよい!」という議論はナンセンスです。
基本を押さえて正しいセキュリティ対策を行いましょう!このスライドはこちらから参照できます。
P.S. メモリ管理の問題を利用してインジェクションする攻撃はここで紹介したインジェクション攻撃とは多少異なります。MongoDBインジェクションのように少し変わったインジェクション攻撃もあります。テキストベースインターフェースの場合は基本的には全てここで紹介したパターンに当てはまります。
インジェクション対策で最初に書かなかったことを追記します。インジェクション対策としての入力バリデーションで必要十分条件を満たすには、文字エンコーディングのことを考慮する必要があります。文字エンコーディングは入出力システムに合わせて正しく使い、尚かつ入力バリデーションで文字エンコーディングをバリデーションする必要があります。出力対策として出力時にも文字エンコーディングをバリデーションすると更に良いです。また、入力バリデーションは”全ての変換”(正規化含む)が終わってからバリデーションしないとならない事に注意してください。
参考
- セキュアプログラミング(防御的プログラミング)の歴史をざっと振り返る
- CERT Top 10 Secure Coding Practices
- エンジニア必須の概念 – 契約による設計と信頼境界線
- ISO 27000とセキュアプログラミング