はじめに
Injectionはしばしば発生する問題で、その形態も様々です。例えば、SQLデータベースではSQLインジェクション、LDAP、XML、OSコマンドなどでも同様の脆弱性が存在します。つまり、様々なInjection脆弱性が発生する可能性があり、本記事ではそれらについて解説します。
A1:インジェクション
脅威の要因/攻撃ベクトル | セキュリティの弱点 | 影響 |
---|---|---|
アプリがユーザ入力を受け取り処理に渡す箇所では、悪意あるコードが挿入される可能性があります。基本パラメータだけでなく、環境変数、各種パラメータ、外部・内部のウェブサービス、インポート機能など、ユーザが操作可能な全要素に注意が必要です。 | この問題は他プロジェクトや他の開発者から引き継がれたコードに起因することが多く、ドキュメント不足のため新しいチームで適切なセキュリティ対策が取られない場合があります。また、SQL、XPath、LDAP、SMTPヘッダーなど、ユーザ入力を利用する処理においても未検証のデータを渡さないよう注意が必要です。ファザや自動スキャナの使用は有用ですが、依存しすぎないことが求められます。 | 影響はアプリの機能や利用されるInjectionの種類により大きく異なり、データ損失、不正な操作、データ破損など多岐にわたる可能性があります。 |
しばしば開発者は、ウェブアプリをより動的にするために様々な手法を用います。例えば、データベースでの CRUDアクション、LDAPやOSコマンドを利用したログインなどが挙げられます。これらはウェブアプリに動きを与える一例ですが、ユーザ入力を十分に検証せずに処理すると、脆弱性が発生する可能性があります。悪意ある利用者が自らの入力を仕込むことで、SQLインジェクションやOSコマンドインジェクションによりリモートでコードが実行されるといった深刻な被害に繋がる恐れがあります。この種類の問題は、OWASP Top 10に挙げられており、見逃せない課題です。
SQLi は、SQLクエリ作成時にユーザ入力を利用する際、入力が十分に検証されないと発生する脆弱性です。入力の検証が不十分な場合、ユーザがクエリを途中で終了させ独自のコードを挿入するリスクが伴います。
LDAPはウェブアプリで認証に用いられるシステムですが、注意すべき落とし穴が存在します。適切に検証されない場合、悪意ある利用者がLDAPクエリに介入し、独自のLDAP文を挿入する可能性があります。安全かつ簡便なパラメータ設定が統一されていない点が、この問題を複雑にしています。
場合によっては、開発者がXML入力を生成する必要があります。ファイルのアップロード機能に限らず、SOAPリクエストなど、ユーザ提供の入力をもとにXMLファイルを作成することがあります。攻撃者は生成されたXMLの構造を乱し、独自の値を挿入しようと試みます。
OSコマンドはコードから直接実行される場合があります。利便性がある一方、ユーザ入力をもとにコマンドを実行する場合、攻撃者がコマンド文字列を終了させ独自のコマンドを挿入する可能性があります。その結果、リモートでコードが実行されるなど重大な影響が生じる恐れがあります。
ウェブアプリがデータをXMLファイルに格納する際、SQLがデータベース検索に用いられるのと同様に、XPATHでXMLを検索することがあります。ユーザ入力がXPATHクエリに利用され、十分な検証がされなければ、攻撃者が独自のクエリを挿入するリスクがあります。これにより、機密情報の漏えいや、XML内のログイン情報を用いた認証回避といった技術的な問題が発生する可能性があります。
CRLFとはキャリッジリターンとラインフィードを指し、行の終了を示す記号です。アプリの設定によっては、攻撃者が自身の改行や場合によってはコードを挿入することで、ログへの不正記録やHTTPレスポンス分割などの深刻な問題が発生する可能性があります。
アプリが内部でメール送信機能を提供する場合、送信先アドレスや内容といった入力が必要です。これらがメールのヘッダーに組み込まれ、十分に検証されない場合、攻撃者が独自のSMTPヘッダーを挿入する恐れがあります。通常、スパマーがフィッシングメールの送信やウイルス添付などの不正行為を試みる際に利用されます。
一部のアプリでは、ユーザ入力がHTTPヘッダーに渡されることがあり、これが適切に検証されない場合、攻撃者が独自のHTTPヘッダーを挿入する可能性があります。これにより、ヘッダーが反映されたページでXSS攻撃などが発生する恐れがあります。
この脆弱性がビジネスに与える影響は、攻撃されるInjectionの種類や該当機能により予測が難しい面があります。しかし、一般的にはデータ損失、リモートコードの実行、認証の回避といった影響が懸念されます。
Injection脆弱性を検出するには、ユーザ入力に対してファズテストを実施する必要があります。隠れたパラメータも含め、全ての入力に適切な攻撃ベクトルを用いてテストし、万が一の脆弱性を見逃さないようにしなければなりません。また、WAFやAPIセキュリティなどの機能を実環境に実装し、万全の対策を講じる必要があります:
一例として、開発者が以下のようなクエリを書く場合が考えられます:
“Select * from users where username =’" . $_POST['user'] . "’ and password = ‘" . $_POST['password'] . "’
もしユーザ入力を十分に検証しなければ、攻撃者はパスワード欄に「'; or 1=1--」のようなコードを挿入でき、クエリを終了させた後に自らのコードを挿入することが可能となります。これにより、パスワード入力を省略できるため、SQLインジェクションの一例となりますが、この技法はさらに多くの攻撃に応用可能です。
もう一つの例は、アプリがユーザ入力をもとにXMLファイルを生成するケースです。利用者が「<action>deleteUsersTable</action>」のようなXMLを入力し、サーバがそのXMLを処理すると、例として全ユーザを削除するといった望ましくない動作が引き起こされる恐れがあります。
また、Injectionに関する攻撃事例も見てみましょう。特に高い影響があるCVE-2021-32590では、複数箇所でのユーザ入力の検証不足により、攻撃者が任意のSQLコードを挿入できる状況が示されています。これにより、ユーザ入力の全経路を洗い出し、必ず検証する重要性を再認識させられます。
https://www.cvedetails.com/cve/CVE-2021-32590/
さらに、正規表現インジェクションに関する攻撃事例も取り上げます。本事例は高額の報奨金が提示されたこと、また正規表現インジェクションという珍しい手法であったため注目されました。報奨金は4,500ドルに達しており、この脆弱性を利用することで、アプリの動作変更やDoS攻撃が引き起こされました。
https://hackerone.com/reports/1196124
データを保存する層とクエリを処理する層を分離することで、ユーザ入力を含むデータをクエリに渡す前に十分な検証を行う体制が必要です。
また、開発者はObject Relational Mapping (ORM)ツールなどへ移行することで、実際のデータベースと隔離された「仮想オブジェクトデータベース」を構築し、安全性を高めることが可能です。
入力データの検証およびサニタイズには、ホワイトリスト方式を用いることが望ましいですが、必ずしもそれだけで対応できるとは限りません。
これらの対策を講じた後でも、動的なクエリがユーザ入力を処理する場合には、該当する技術スタックが使用する特殊文字をエスケープする必要があります。
それでもSQLインジェクションが発生する場合には、SQLのLIMIT文を活用して、一度のクエリでデータベース全体がダンプされないよう対策するのが効果的です。
Injectionの脆弱性は、一見単純に思えるが故に見落とされがちです。「全ての動的クエリや処理に対してユーザ入力をサニタイズする」というのは容易に聞こえますが、実際にはアプリ内に入る全経路を特定するのは難しいものです。OWASP A1:Injectionに沿った厳密なテストと適切なファズテストを実施し、バックエンドでしっかりと守る必要がある脆弱性です。
最新情報を購読