進行状況の追跡を始めよう
Trailhead のホーム
Trailhead のホーム

SOQL インジェクションについて

学習の目的

この単元を完了すると、次のことができるようになります。
  • SQL と SOQL の相違点を 5 つ以上挙げる。
  • 基本的な SOQL インジェクションを悪用する方法を学ぶ。

SQL (Structured Query Language) 入門

アプリケーションの最も重要な機能は、データストアにデータを格納し、データストアからデータを取得する機能です。従来の Web アプリケーションでは、SQL (Structured Query Language) と呼ばれるものを使用します。これは、アプリケーション開発者がリレーショナルデータベースと対話するために使用する特別な言語です。SQL には、レコードまたはテーブル全体を INSERT、UPDATE、DELETE するためのさまざまな機能が含まれます。そのうち、最も一般的に実行される操作は、アプリケーションがデータベースからデータを問い合わせるための SELECT クエリです。

このクエリタイプの基本的な形式は次のとおりです。

SELECT TABLE_COLUMN FROM TABLE_NAME WHERE CONDITION

このクエリにより、追加の条件で制限して、特定のテーブルの 1 つまたは複数 (ワイルドカード文字 * を使用する場合) のテーブル列からデータを取得できます。この機能はそのままでも強力ですが、多くの場合、追加の機能によって拡張されます。

  • 結合 - 複数のテーブルをグループにまとめます。
  • サブクエリ - あるクエリの結果を別のクエリで使用します。
  • コマンド実行 - システムレベルのコマンドをクエリから直接実行できます。

データへのアクセス権を得ようとする攻撃者にとって、SQL はエクスプロイトの主要なターゲットです。

SQL はどのように攻撃されるのでしょうか?

ユーザ向けにカスタマイズされた応答性の高いアプリケーションを作成するために、開発者はしばしばユーザが行った入力を利用してデータベースから情報を取得するよう誘導します。

たとえば、ほとんどのアプリケーションに組み込まれている基本的なログイン機能を考えてみます。

  1. ログインページでは、ユーザ名とパスワードの入力が促されます。
  2. ENTER をクリックして、次のようなデータベースクエリをバックグラウンドでトリガします。
    Select * from user where username = ‘CASTLE-Y_USERNAME’ and password = ‘CASTLE_PASSWORD’
    

データベースクエリでデータが返される場合、アプリケーションはユーザをシステムに誘導します。

追加の検証なしで入力を信頼する場合、SQL インジェクションに自らを開放することになり、悪意のあるユーザは SQL にとって特別な意味のある文字を使用して結果を変更できてしまいます。

それでは、攻撃者の視点から改めてこのフローを見てみましょう。

  1. ログインページで攻撃者はユーザ名として「admin」、パスワードとして「password」を入力します。
  2. 攻撃者は ENTER をクリックし、前と同様にデータベースクエリをトリガします。
    Select * from user where username = ‘admin’-- and password = ‘password’
    

SQL では “--” はコメントを示すため、アプリケーションは残りのクエリを無視します。ユーザ名 admin のユーザが存在する場合 (ほとんどのアプリケーションでは合理的な推測)、攻撃者はまんまとログインをバイパスして基盤となるアプリケーションにアクセスできてしまいます!

これは深刻な例ですが、SQL はデータを照会するだけではないことに注意してください。データベースのデータを CREATE、INSERT、DELETE、DROP するより高度なアクションでも使用できます。このため、SQL インジェクションは非常に深刻なものになる可能性があります。アプリケーションのどこかに 1 つの弱点があると、攻撃者はデータベース全体を読み取り、変更、削除できる可能性があります。

Salesforce では SQL ではなく SOQL を使用

Salesforce 開発者は、Lightning プラットフォームで SQL ではなく SOQL (Salesforce Object Query Language) が使用されていることを知っています。これらの言語は多くの点で似ていますが、SOQL は本質的に、Salesforce プラットフォーム専用に記述された SQL の軽量版です。

SOQL と SQL の相違点をいくつか示します。

  • INSERT、UPDATE または DELETE ステートメントはなく、SELECT のみ。
  • コマンド実行がない。
  • 項目用のワイルドカードがない。すべての項目に明示的に入力する必要があります。
  • JOIN ステートメントがない。ただし、Select name、phone、account.name from contact などの親オブジェクトの情報を含めることができます。
  • UNION 演算子がない。
  • クエリをチェーニングできない。

SOQL はインジェクション攻撃に対しても脆弱か?

プラットフォームによって適用されるこれらすべての制限があってもなお、果たしてインジェクション攻撃を実行できるのかと疑問に思われるかもしれません。結論から言うと、「できます!」です。残念なことに、開発者は依然としてユーザ入力を間違って信用する可能性があり、それが SOQL インジェクション攻撃と呼ばれるものを介した情報の漏えいにつながっています。

Kingdom Management 開発者組織の例を使用して、これがどのように悪用されるかを見ていきましょう。

  1. Kingdom Management 開発者組織にログインします。
  2. [SOQL インジェクション] アプリケーションに移動します。
  3. [SOQL インジェクションデモ] タブをクリックします。

    このアプリケーションで、Kingdom を検索して Kingdom の人員の概要を入手するためのカスタムページを作成しました。検索ボックスに敬称または年齢検索条件を入力して、このリストを絞り込むことができます。

  4. 「Sir」などの敬称検索条件を入力して試してみます。

    ページは予想どおりに動作し、敬称 Sir を持つ人員のリストが返されます。

  5. ページ下部にある [Apex コントローラ] リンクをクリックし、アプリケーションで使用されている SOQL クエリを検索します。
    whereClause += 'Title__c like  \'%'+textualTitle+'%\' ';
    whereclause_records = database.query(query+' where'+whereClause);
    

    アプリケーションはユーザから送信された textualTitle パラメータを取り込んで、SOQL クエリに直接挿入します。これは SOQL インジェクションに対して脆弱である可能性があります! 覚えておいででしょうが、SOQL インジェクションは攻撃者がクエリの構造を変更したときに発生します。今度はもっと複雑な検索条件を試して、クエリの動作を変えられるかどうか見てみましょう。

  6. [SOQL インジェクションデモ] タブに戻って、%' and name like 'Amanda% のような検索条件を入力します。

    うまくいきました! これを誤用して、さらに情報を漏えいさせることができるか見てみましょう。

  7. 敬称検索に次の検索条件を入力して、データベースで成績が低い人員を識別させるようにします: %' and Performance_rating__c<2 and name like '%

これが機能する理由は、ユーザ入力は検証なしで SOQL クエリに連結されるため、攻撃者は敬称パラメータの単一引用符を閉じて、別の条件をクエリに追加できるからです。この結果、構文的には有効なクエリになります。

前:

Title__c like '%'+textualTitle+'%'

後:

Title__c like '% %' and Performance_rating__c<2 and name like '% %'';

別の SOQL インジェクション例

それでは、Kingdom Management 開発者組織で SOQL インジェクションの別の例を試してみましょう!

  1. Kingdom Management 開発者組織にログインします。
  2. [SOQL インジェクション] アプリケーションに移動します。
  3. [SOQL インジェクションデモ] タブをクリックします。
  4. 年令検索条件に「22」と入力します。

    アプリケーションは、年令が 22 の人員のみ表示するように人員リストを絞り込む必要があります。これをもう一度試してみましょう。ただし、今回は最後に有効な SOQL を追加して、アプリケーションで実行されるかどうか見てみましょう。これを簡単に実現するには、LIMIT コマンドを使用してクエリで返される結果の数を制限します。

  5. 年令検索条件に「22 limit 1」と入力します。

    アプリケーションが SOQL インジェクションに対して脆弱である場合、文字列の “limit 1” 部分が SOQL コマンドとして実行され、結果を 1 つのレコードのみに制限します。うまくいきました!

    ページ下部にある Apex コントローラリンクを使用してコードを見てみましょう。

    if(textualAge!=null){
        whereClause+='Age__c >'+textualAge+'';
        whereclause_records = database.query(query+' where'+whereClause);
    }
    

アプリケーションは textualAge という文字列を取り込んで動的クエリに直接挿入し、検証またはエスケープせずにすべてを実行します。このアプリケーションは本当に脆弱なようです!

SOQL インジェクションの影響

Salesforce 開発者にとって幸運なことに、SOQL は SQL よりもユーザができることが限られているため、SOQL によって攻撃面が減少し、攻撃者が脆弱なクエリを利用してできることが制限されます。

  • コマンドが実行されないため、Salesforce サービスを実行する基礎となる OS を悪用することはできません。
  • 削除方法がないため、破壊的に相互作用することはできません。
  • 挿入または更新方法がないため、データ、ユーザアカウント、または権限をシステムに追加することはできません。

それでもまだ、SOQL は脆弱です。SOQL インジェクションをまんまと悪用できる攻撃者は、開発者が公開するつもりのない項目、またはユーザが通常アクセス権を持たない項目にアクセスできます。

リソース

Apex 開発者ガイド - SOQL インジェクション

Open Web Application Security Project (OWASP) - SQL Injection (オープン Web アプリケーションセキュリティプロジェクト (OWASP) - SQL インジェクション)

Flower icon used to indicate that the content is for Salesforce Classic

このモジュールは Salesforce Classic 向けです。ハンズオン組織を起動するときには、Salesforce Classic に切り替えてから、この Challenge を実行してください。

retargeting