OWASP TOP10の1位のセキュリティ脅威はインジェクションです。
https://www.owasp.org/index.php/Top_10_2013-A1-Injection
SQLインジェクション、コマンドインジェクションはリファレンスとして掲載されていますが、何故かLDAPインジェクションは掲載されていません。しかし、OWASPの別の文書では簡単に解説されています。
https://www.owasp.org/index.php/Testing_for_LDAP_Injection_(OWASP-DV-006)
LDAPサーバの設定が脆弱な場合、LDAPインジェクションでLDAPデータベースの中身を大量に盗む事が可能になります。
LDAPライブラリの問題はエスケープ方法が定義されているにも関わらず、LDAPクエリ文字列用のエスケープ関数が定義されていない事です。出力(クエリ)に利用する文字に一文字でも特殊な意味を持つ物がある場合、エスケープが必要か確認し、必要であれば定義されたエスケープ方法でエスケープしなければなりません。
PHPもLDAPをサポートしていますが、ライブラリ(OpenLDAP)がエスケープ関数を提供していない為、エスケープ関数が提供されていませんでした。PHP5.6からはLDAP用のエスケープ関数であるldap_escape関数が追加されます。
LDAPを利用する場合、filterとDNで異なる文字をエスケープしなければならないですが、文字列とフラグを使用して指定できるようになっています。
- LDAP_ESCAPE_FILTER
- LDAP_ESCAPE_DN
実際にエスケープされる文字は、以下の部分で指定されています。
+ if (flags & PHP_LDAP_ESCAPE_FILTER) { + havecharlist = 1; + php_ldap_escape_map_set_chars(map, "\\*()\0", sizeof("\\*()\0") - 1, 1); + } + + if (flags & PHP_LDAP_ESCAPE_DN) { + havecharlist = 1; + php_ldap_escape_map_set_chars(map, "\\,=+<>;\"#", sizeof("\\,=+<>;\"#") - 1, 1); + }
具体的なエスケープ方法はRFCで定義されています。
FilterのエスケープはRFC 4515
http://tools.ietf.org/html/rfc4515
DNのエスケープはRFC 2253のセクション2.4
http://tools.ietf.org/html/rfc2253
で定義されています。要約するとエスケープが必要な文字は\でエスケープし16進数のアスキー値を書きます。
\XX – XXは16進数のアスキー値
とエスケープするように、ということです。LDAPサーバの設定が甘い場合はエスケープ漏れで丸ごと中身を抜かれる可能性もあります。
エスケープ方法が定義されているにも関わらず、エスケープ関数・メソッドが定義されていないケースはよくあります。LDAP以外の代表例はSQLの識別子(テーブル名、フィールド名など)、 XPath1.0です。忘れるところでしたがもう一つ、OSコマンドイもOSでエスケープ関数を定義していません。更にXSSもJavaScriptをインジェクションする攻撃なので、XSSも含めてインジェクション攻撃と考えると分り易いと思います。
LDAP、SQL、XPath、OSコマンドインジェクションが可能な場合の影響は非常に大きいので注意が必要です。
LDAPクエリの例を検索してみましたが、SQLインジェクションがあまり知られていなかった時のような牧歌的な例が沢山ありました。出力先への正しい出力知らない・正しい出力方法を知ろうとしないプログラマ、つまりエスケープ処理を知らないプログラマはセキュアなコードは書けない、という証明です。
追記:書いている人達もプロなので一応
They are often found in SQL, LDAP, Xpath, or NoSQL queries; OS commands; XML parsers, SMTP Headers, program arguments, etc.
と代表例としては挙げていますが、LDAPもXPathインジェクションもドキュメントがあるので参考リンクに追加して欲しい所です。
PHPのセキュリティ入門書に記載するコンテンツのレビューも兼ねてブログを書いています。コメント、感想などを歓迎します。