SOQL インジェクション

概要

SOQLインジェクションは、SalesforceのApex言語で使用されるSOQL(Salesforce Object Query Language)クエリにおいて、ユーザーが提供する悪意のある文字列がデータベースクエリの一部として実行され、不正なデータアクセスやデータ変更を引き起こす攻撃です。この脆弱性は、ユーザー入力を適切に検証やサニタイズせずに動的SOQLクエリに組み込むことで生じます。

Apex での SOQL インジェクションの脆弱性

SOQLインジェクションは主に、ユーザーからの入力を検証せずに動的クエリに組み込むことで発生します。例えば以下のApexコードを見てみましょう。

public class SOQLController {
    public String name { get; set; }
    
    public PageReference query() {
        // 危険: ユーザーの入力がエスケープされずにクエリに組み込まれている
        String qryString = 'SELECT Id FROM Contact WHERE (IsDeleted = false and Name like \'%' + name + '%\')';
        List<Contact> queryResult = Database.query(qryString);
        System.debug('query result is ' + queryResult);
        return null;
    }
}

このコードはユーザーが提供するnameを使って取引先責任者の名前を検索しますが、SOQLインジェクションに対して脆弱です。

例えば、ユーザーがtest%') OR (Name LIKE 'という値をnameに入力した場合、結果のクエリは以下のようになり、すべての取引先責任者を返します。これは、悪意のあるユーザーがクエリのロジックを変更して、意図しないデータにアクセスすることを可能にする例です。

SELECT Id FROM Contact WHERE (IsDeleted = false AND Name LIKE '%test%') OR (Name LIKE '%')

SOQL インジェクションの防御策

1.変数バインディングを使用する

Apexにおいては、クエリ内で変数を直接利用することが可能です。これはSOQLインジェクションを防ぐ効果的な手法です。

String queryName = 'John Doe';
List<Contact> queryResult = [SELECT Id FROM Contact WHERE Name = :queryName];

上記のコード例において、:queryName の部分が変数バインディングを使用しています。この : プレフィックスは、Apex変数 queryName の値をSOQLクエリに直接組み込むためのものです。この方法で変数の値をクエリに組み込むことで、動的に文字列を組み立てることなく、安全にクエリを実行することができます。

2.escapeSingleQuotes メソッドを使用する

このメソッドは、文字列内の単一引用符にエスケープシーケンスを追加し、文字列リテラルの一部として扱われるようにします。

String userInput = "O'Reilly";
String safeInput = String.escapeSingleQuotes(userInput);

これにより、ユーザーの入力を安全にクエリに組み込むことができます。

public class SOQLController {
    public String name { get; set; }
    
    public PageReference query() {
        // ユーザー入力をエスケープして安全性を高める
        String queryName = '%' + String.escapeSingleQuotes(name) + '%';
        // 安全な変数バインディングを使用してクエリを実行
        List<Contact> queryResult = [SELECT Id FROM Contact WHERE (IsDeleted = false and Name like :queryName)];
        System.debug('query result is ' + queryResult);
        return null;
    }
}

防御策を適用すべきシチュエーション

  • ユーザーの入力を基に動的SOQLクエリを構築する際: フォームや検索バーからの入力をクエリに組み込む際には、特に注意が必要です。
  • レポートやダッシュボードのフィルタとしてユーザー入力を利用する際: Salesforceのレポートやダッシュボード機能にユーザーがフィルタ条件を入力する際にも、インジェクション攻撃のリスクがあります。
  • システム外部からのデータを使用してクエリを実行する際: API経由や他のシステムからインポートされるデータは、信頼性が検証されていない可能性があるため、クエリに組み込む前に適切な検証が必要です。
  • URLパラメータやフォームの入力から直接SOQLクエリを組み立てる際: WebアプリケーションでURLパラメータを利用してデータベースクエリを構築する場合にも、SOQLインジェクションの可能性があります。
  • アプリケーション間の統合時: 他のアプリケーションやシステムからのデータを受け取る際は、受け取ったデータを信頼する前に適切にサニタイズすることが不可欠です。

まとめ

SOQLインジェクションは、Salesforce開発者が常に意識すべき重要なセキュリティリスクです。このリスクを効果的に管理するためには、安全なコーディング慣行を理解し、適切に実施することが不可欠です。上記の方法でユーザー入力を適切に処理することで、アプリケーションのセキュリティを強化し、不正なデータアクセスを防ぐことができます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

雇われのシステムエンジニアです。
普段は車載ECUのセキュリティー分野に従事しております。

■保有資格
Salesforce 認定 アドミニストレーター
Salesforce 認定 Platform アプリケーションビルダー
Salesforce 認定 Platform デベロッパー

コメント

コメントする

目次