この文章は Salesforce 機械翻訳システムを使用して翻訳されました。詳細はこちらをご参照ください。
英語に切り替える

Apex および Visualforce 開発のセキュリティガイドライン

カスタムアプリケーションを開発する場合のコードの脆弱性を理解し、その対策を講じます。
使用可能なインターフェース: Salesforce Classic (使用できない組織もあります)
使用可能なエディション: Group Edition、Professional Edition、Enterprise Edition、Performance Edition、Unlimited Edition、Developer Edition、および Database.com Edition

Visualforce は、Database.com Edition では利用できません。


セキュリティとは

Apex および Visualforce ページの強力な組み合わせにより、Lightning Platform 開発者は、Salesforce にカスタム機能およびビジネスロジックを提供したり、Lightning Platform 内部で実行する新しいスタンドアロン製品を作成したりできます。ただし、プログラミング言語と同様、開発者はセキュリティ関連の不備について認識する必要があります。

Salesforce は、複数のセキュリティ防御を Lightning Platform に統合しました。ただし、不注意な開発者が組み込み防御をスキップし、アプリケーションと顧客をセキュリティ上のリスクにさらしている場合があります。開発者が Lightning Platform 上で犯す多くのコーディングエラーは、一般的な Web アプリケーションのセキュリティ脆弱性と類似していますが、一部のコーディングエラーは Apex 固有のものです。

AppExchange のアプリケーションを認証するには、説明されているセキュリティ上の弱点について開発者が学習および理解しておくことが重要です。詳細は、Salesforce Developers で Lightning Platform のセキュリティリソースのページを参照してください。https://developer.salesforce.com/page/Security

クロスサイトスクリプト (XSS)

クロスサイトスクリプト (XSS) 攻撃では、悪意のある HTML またはクライアント側スクリプトが Web アプリケーションに提供されます。Web アプリケーションには、意図せずに攻撃の犠牲になっているユーザーに対して、悪意のあるスクリプトが組み込まれます。攻撃者は、Web アプリケーションに対する被害者の信頼を利用し、攻撃の媒体として Web アプリケーションを使用しています。データを適切に検証することなく動的 Web ページを表示する多くのアプリケーションは攻撃されやすいといえます。Web サイトに対する攻撃は、あるユーザーからの入力を別のユーザーに表示する場合は特に単純です。可能性として、掲示板、ユーザーコメントスタイルの Web サイト、ニュース、またはメールアーカイブなどがあります。

たとえば、次のスクリプトがスクリプトコンポーネント、on* 行動、または Visualforce ページを使用する Lightning Platform ページに使用されているとします。
このスクリプトブロックは、ユーザーが入力した userparam の値をページに挿入します。これで攻撃者は userparam に次の値を入力することができます。

この場合、現在のページのすべての Cookie が cookie.cgi スクリプトに対する要求のクエリ文字列として www.attacker.com に送信されます。この時点で、攻撃者は被害者のセッション Cookie を持っており、彼らが被害者になりすまして Web アプリケーションに接続することができます。

攻撃者は、Web サイトまたはメールを使用して、悪意のあるスクリプトを送信できます。Web アプリケーションユーザーにより攻撃者の入力が表示されるだけでなく、ブラウザーによって信頼されたコンテキストで攻撃者のスクリプトを実行することもできます。こうした機能により、攻撃者はさまざまな攻撃を被害者に対して行うことができます。これらの攻撃の範囲はウィンドウを開いたり閉じたりする単純なアクションから、データまたはセッションの Cookie を盗むなど、被害者のセッションに攻撃者が完全にアクセスできるようになる悪意に満ちた攻撃にまで及びます。

この種の攻撃の詳細については、次のサイトを参照してください。

Lightning Platform 内には、複数の対 XSS 防御策が組み込まれています。たとえば、多くの出力メソッドの有害な特性を除外するフィルターが用意されています。標準クラスおよび出力メソッドを使用する開発者に対する XSS の脆弱性の脅威は、大幅に緩和されています。ただし、クリエイティブな開発者によって、デフォルトのコントロールを意図的または偶然に、エスケープする方法がいまだに見つかっています。

既存の保護

<apex> で始まるすべての標準 Visualforce コンポーネントでは、有害な特性を除外する対 XSS フィルターが設定されています。たとえば、ユーザーに直接返されるユーザー指定の入力および出力を採用するため次のコードは通常 XSS の攻撃に対して脆弱ですが、<apex:outputText> タグは XSS に対して安全です。HTML タグとされるすべての文字は、リテラル形式に変換されます。たとえば、< 文字は &lt; に変換され、ユーザーの画面上ではリテラル < が表示されます。

Visualforce タグのエスケープの無効化

デフォルトでは、ほぼすべての Visualforce タグは XSS に対して脆弱な文字をエスケープします。省略可能な属性 escape="false" を設定することによって、この動作を無効化できます。たとえば、次の出力は、XSS の攻撃に対して脆弱です。

XSS から保護されていないプログラミング項目

カスタム Javascript コードと <apex:includeScript> コンポーネント内のコードには、組み込み XSS 保護がありません。これらの項目により、開発者はスクリプトコマンドを使用してページをカスタマイズできます。意図的にページに追加されるコマンドに対 XSS フィルターを指定しても意味は��りません。

カスタム JavaScript

独自の JavaScript を作成した場合、Lightning Platform にはユーザーを保護する方法がありません。たとえば JavaScript で使用している場合、次のコードは XSS の攻撃に対して脆弱です。

<apex:includeScript>

<apex:includeScript> Visualforce コンポーネントにより、ページにカスタムスクリプトを追加できます。内容が安全で、ユーザーが入力したデータが含まれていないことを確認してください。たとえば、次のスニペットはスクリプトテキストの値としてユーザー指定の入力が含まれているため脆弱です。タグによって指定された値は、使用する JavaScript への URL です。攻撃者が次の例内のこのパラメーターに任意のデータを入力できる場合、被害者に別の Web サイトの JavaScript ファイルを使用するよう指示できます。

[数式] タグ

これらのタグの一般的なシンタックスは、{!FUNCTION()} または {!$OBJECT.ATTRIBUTE} です。たとえば、開発者がリンクにユーザーのセッション ID を指定したい場合、次のシンタックスを使用してリンクを作成できます。
そして、この出力のようにレンダリングされます。
数式は、関数コールとして使用したり、プラットフォームオブジェクト、ユーザーの環境、システム環境、要求の環境に関する情報を含めたりすることができます。これらの数式の重要な特徴は、表示中にデータがエスケープされないという点です。式はサーバーに表示されるため、JavaScript またはその他のクライアント側の技術を使用してクライアントの表示データをエスケープすることはできません。このため、数式が非システムデータ、つまり悪意のあるデータや編集可能なデータを参照し、式が、表示中に出力をエスケープする関数でラップされていない場合は危険です。一般的な脆弱性は、要求パラメーターにアクセスする {!$Request.*} 式の使用によって引き起こされます。
エスケープされない {!$Request.title} タグによっても、クロスサイトスクリプトの脆弱性が誘発されます。たとえば、次のような要求の場合
出力は次のようになります。
サーバー側でエスケープする標準メカニズムは、SUBSTITUTE() 数式タグを使用します。例で {!$Request.*} 式の投入を指定すると、次のネストされた SUBSTITUTE() コールを使用して、前述の攻撃を回避できます。
タグの投入およびデータの使用に応じて、エスケープが必要な文字と、エスケープされる文字は異なる可能性があります。たとえば、次のようなステートメントの場合
リンクで使用される可能性が高いため、HTML エスケープ文字の " の代わりに同等の URL エンコードの %22 を使用して二重引用符をエスケープする必要があります。そうでない場合、次のような要求
では、次のようになります。

ret 変数は、含まれる HTML 制御文字が解釈される場合、ページの後半で追加のクライアント側エスケープが必要になる場合があります。

また、数式タグを使用して、プラットフォームオブジェクトデータを追加することもできます。データはユーザーの組織から直接取得されますが、ユーザーが、他のユーザー (より高い特権レベルを持つユーザーなど) のコンテキストでコードを実行することを防ぐために、使用前にエスケープする必要があります。このような攻撃を実行できるのは、同じ組織内のユーザーのみです。これらの攻撃により、ユーザーロールが弱体化し、データ監査の完全性が低下します。データを外部ソースからインポートした場合、悪意のあるコンテンツのスキャンが行われない場合があります。

クロスサイトリクエストフォージェリ (CSRF)

クロスサイトリクエストフォージェリ (CSRF) の脆弱性は、プログラムエラーというよりも保護対策の欠如に起因します。攻撃者が www.attacker.com に Web ページを持っているとします。この Web ページは、サイトへの通信量を増大させる重要なサービスや情報を提供するページなどです。攻撃者のページには、次のような HTML タグがあります。

つまり、攻撃者のページには、あなたの Web サイトでアクションを実行する URL が含まれています。ユーザーが攻撃者の Web ページにアクセスしたときに、まだあなたの Web ページにログインしている場合、URL が取得され、アクションが実行されます。ユーザーはあなたの Web ページで認証されているため、この攻撃は成功します。この攻撃は単純な例で、攻撃者の手口はより巧妙になっており、コールバック要求を生成するスクリプトを使用したり、あなたの AJAX メソッドに対して CSRF 攻撃を行うこともあります。

詳細および従来の防御方法については、次を参照してください。

Lightning Platform 内では、このような攻撃を回避する対 CSRF トークンが実装されています。すべてのページにランダムな文字列が非表示形式項目として指定されています。次のページが読み込まれると、アプリケーションはこの文字列の正当性を確認し、値が予測値と一致しない限り、コマンドを実行しません。この機能によって、すべての標準コントローラーおよびメソッドの使用時に攻撃から保護されます。

開発者は、リスクを意識せずに組み込み防御策をスキップしてしまう場合があります。たとえば、カスタムコントローラーがオブジェクト ID を入力パラメーターとして取得し、SOQL コールで使用するとします。

開発者は独自の action メソッドを作成して、意識せずに CSRF 対策コントロールをスキップしています。id パラメーターはコードで読み込まれ、使用されます。CSRF 対策トークンが読み込まれたり、検証されたりすることはありません。攻撃側の Web ページでは、CSRF 攻撃を使用してユーザーをこのページに移動させ、id パラメーターに値を指定する可能性があります。

このような状況に対する組み込みの防御策がないため、開発者は前例の id 変数のように、ユーザー指定のパラメーターに基づいてアクションを実行するページの書き込みに注意する必要があります。回避策の 1 つは、中間の確認ページを挿入して、ユーザーが本当にそのページをコールしようとしているのかどうかを確認することです。その他の対策として、アイドルセッションのタイムアウトを短くすることや、あるサイトで認証されたまま、そのブラウザーを使用して別のサイトに移動しないように、アクティブなセッションからログアウトすることをユーザーに推奨することなどが考えられます。

複数の Salesforce ログインページが開かれている場合、CSRF に対する Salesforce の組み込み防御策によってエラーが表示される場合があります。ユーザーが 1 つのタブで Salesforce にログインし、その後、別のタブでログインを試みると、「送信したページは、セッションに対して無効でした。」というエラーが表示されます。正常にログインするには、ログインページを更新するか、ログインをもう一度試みます。

SOQL インジェクション

他のプログラミング言語では、上記の弱点を SQL インジェクションといいます。Apex では SQL を使用しませんが、独自のデータベースクエリ言語 SOQL を使用します。SOQL は、SQL より単純で、機能が制限されています。SOQL インジェクションのリスクは SQL と比較して低くなりますが、攻撃は従来の SQL インジェクションとほぼ同じです。SQL/SOQL インジェクションではユーザーの入力を取得し、これらの��を動的 SOQL クエリで使用します。入力が検証されない場合、SOQL ステートメントを事実上変更する SOQL コマンドを指定し、アプリケーションにトリックを仕掛けて意図しないコマンドを実行するようにします。

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

次に SOQL に対して脆弱な Apex コードおよび Visualforce の単純な例を示します。
この単純な例は、ロジックについて説明しています。このコードは、削除されていない取引先責任者を検索するためのものです。ユーザーは name という入力値を指定します。値はユーザーが指定する任意の値で、検証されません。SOQL クエリは動的に構築され、Database.query メソッドで実行されます。ユーザーが正当な値を指定すると、ステートメントは次のように期待どおり実行されます。
ただし、次のようにユーザーが予期しない値を入力した場合にはどうなるでしょう。
この場合、クエリ文字列は次のようになります。

結果には削除されていない取引先責任者だけでなく、すべての取引先責任者が表示されます。SOQL インジェクションにより、脆弱なクエリの対象となるロジックを変更することができます。

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

SOQL インジェクションの攻撃を回避するには、動的 SOQL クエリを使用しないようにします。代わりに、静的クエリとバインド変数を使用します。上記の脆弱な例は、静的 SOQL を使用して書き直すことができます。

動的 SOQL を使用する必要がある場合、escapeSingleQuotes メソッドを使用して、ユーザー指定の入力を削除します��このメソッドは、ユーザーから渡される文字列のすべての単一引用符にエスケープ文字 (\) を追加します。このメソッドにより、すべての単一引用符を、データベースコマンドではなく、囲まれた文字列として処理します。

データアクセスコントロール

Lightning Platform は、データ共有ルールを広範囲に使用します。各オブジェクトには権限があり、ユーザーが読み取り、作成、編集、削除できる共有設定がある場合があります。これらの設定は、すべての標準コントローラーを使用する場合に強制されます。

Apex クラスを使用する場合、組み込みユーザー権限、および項目レベルのセキュリティ制限は実行時に重視されません。デフォルトの動作として、Apex クラスはすべてのデータを読み込み、更新できます。これらのルールは強制されないため、Apex を使用する開発者は、ユーザー権限、項目レベルのセキュリティ、デフォルト設定などによって通常は非表示となる機密データが不用意に公開されないようにする必要があります。たとえば、次の Apex 擬似コードについて考えます。
この場合、現在ログインしているユーザーにこれらのレコードを表示する権限がない場合でも、すべての取引先責任者レコードが検索されます。解決策として、クラスを宣言する場合、次のように修飾キーワードの with sharing を使用します。

with sharing キーワードを使用すると、プラットフォームはすべてのレコードに完全アクセス権限を付与するのではなく、現在ログインしているユーザーのセキュリティ共有権限を使用します。