Windows Communication Foundation (WCF) でデータを処理する場合は、さまざまな脅威カテゴリを考慮する必要があります。 次の一覧は、データ処理に関連する最も重要な脅威クラスを示しています。 WCF には、これらの脅威を軽減するためのツールが用意されています。
サービス拒否
信頼されていないデータを受信すると、受信側がメモリ、スレッド、使用可能な接続、プロセッサ サイクルなど、さまざまなリソースの不均衡な量にアクセスし、長い計算を行う可能性があります。 サーバーに対するサービス拒否攻撃により、サーバーがクラッシュし、他の正当なクライアントからのメッセージを処理できなくなる可能性があります。
悪意のあるコードの実行
信頼されていないデータが受信されると、受信側は意図していないコードを実行します。
情報の開示
リモート攻撃者は、受信側の要求に対して、意図したよりも多くの情報を開示するように強制します。
ユーザー指定のコードとコード アクセス セキュリティ
Windows Communication Foundation (WCF) インフラストラクチャの多くの場所で、ユーザーによって提供されるコードが実行されます。 たとえば、DataContractSerializerシリアル化エンジンは、ユーザー指定のプロパティset
アクセサーとget
アクセサーを呼び出す場合があります。 WCF チャネル インフラストラクチャは、 Message クラスのユーザー指定の派生クラスを呼び出すこともできます。
セキュリティの脆弱性が存在しないことを確認するのは、コード作成者の責任です。 たとえば、整数型のデータ メンバー プロパティを持つデータ コントラクト型を作成し、 set
アクセサーの実装で、プロパティ値に基づいて配列を割り当てる場合、悪意のあるメッセージにこのデータ メンバーの非常に大きな値が含まれている場合、サービス拒否攻撃の可能性を公開します。 一般に、ユーザーが指定したコードでの受信データまたは長い処理に基づく割り当てを回避します (特に、少量の受信データによって長い処理が発生する可能性がある場合)。 ユーザーが指定したコードのセキュリティ分析を実行する場合は、すべてのエラー ケース (つまり、例外がスローされるすべてのコード 分岐) も考慮してください。
ユーザーが指定したコードの最終的な例は、各操作のサービス実装内のコードです。 サービス実装のセキュリティは、お客様の責任です。 サービス拒否の脆弱性を生じる可能性のある安全でない操作の実装を誤って作成するのは簡単です。 たとえば、文字列を受け取り、その文字列で始まる名前のデータベースから顧客の一覧を返す操作です。 大規模なデータベースを操作していて、渡される文字列が 1 文字のみである場合、コードは使用可能なすべてのメモリより大きいメッセージを作成しようとして、サービス全体が失敗する可能性があります。 ( OutOfMemoryException は .NET Framework では回復できず、常にアプリケーションが終了します)。
悪意のあるコードがさまざまな拡張ポイントに接続されていないことを確認する必要があります。 これは、部分信頼で実行する場合、部分的に信頼されたアセンブリの型を処理する場合、または部分的に信頼されたコードで使用できるコンポーネントを作成する場合に特に関連します。 詳細については、後のセクションの「部分信頼の脅威」を参照してください。
部分信頼で実行する場合、データ コントラクトのシリアル化インフラストラクチャでは、データ コントラクト プログラミング モデルの限られたサブセットのみがサポートされます。たとえば、 SerializableAttribute 属性を使用するプライベート データ メンバーまたは型はサポートされていません。 詳細については、「 部分信頼」を参照してください。
注
コード アクセス セキュリティ (CAS) は、.NET Framework と .NET のすべてのバージョンで非推奨になりました。 最近のバージョンの .NET では、CAS に関連する API が使用されている場合、CAS 注釈は使用されず、エラーが発生します。 開発者は、セキュリティ タスクを実行するための代替手段を求める必要があります。
意図しない情報漏えいの回避
セキュリティを念頭に置いてシリアル化可能な型を設計する場合、情報漏えいが懸念される可能性があります。
次の点を考慮してください。
DataContractSerializer プログラミング モデルを使用すると、シリアル化中に型またはアセンブリの外部でプライベート データと内部データを公開できます。 さらに、スキーマのエクスポート中に型の図形を公開できます。 必ず、型のシリアル化射影について理解してください。 何も公開したくない場合は、シリアル化を無効にします (たとえば、データ コントラクトの場合は DataMemberAttribute 属性を適用しないこと)。
使用中のシリアライザーによっては、同じ型に複数のシリアル化プロジェクションがある場合があることに注意してください。 同じ型は、 DataContractSerializer で使用する場合は 1 つのデータ セットを公開し、 XmlSerializerで使用する場合は別のデータ セットを公開できます。 誤って間違ったシリアライザーを使用すると、情報漏えいにつながる可能性があります。
従来のリモート プロシージャ コール (RPC)/エンコード モードで XmlSerializer を使用すると、送信側のオブジェクト グラフの形状が受信側に誤って公開される可能性があります。
サービス拒否攻撃の防止
Quotas (クォータ)
受信側で大量のメモリを割り当てることは、サービス拒否攻撃の可能性があります。 このセクションでは、大きなメッセージから発生するメモリ消費の問題に焦点を当てながら、他の攻撃が発生する可能性があります。 たとえば、メッセージでは、不釣り合いな処理時間が使用される場合があります。
サービス拒否攻撃は通常、クォータを使用して軽減されます。 クォータを超えると、通常は QuotaExceededException 例外がスローされます。 クォータがないと、悪意のあるメッセージによって使用可能なすべてのメモリにアクセスされ、 OutOfMemoryException 例外が発生したり、使用可能なすべてのスタックにアクセスされたりして、 StackOverflowExceptionが発生する可能性があります。
クォータ超過のシナリオは復旧可能です。実行中のサービスで検出された場合、現在処理中のメッセージは破棄され、サービスは実行を続け、さらにメッセージを処理します。 ただし、メモリ不足とスタック オーバーフローのシナリオは、.NET Framework のどこにも回復できません。このような例外が発生した場合、サービスは終了します。
WCF のクォータには、事前割り当ては含まれません。 たとえば、(さまざまなクラスで見つかった) MaxReceivedMessageSize クォータが 128 KB に設定されている場合、メッセージごとに 128 KB が自動的に割り当てられるという意味ではありません。 割り当てられる実際の量は、実際の受信メッセージサイズによって異なります。
トランスポート層では、多くのクォータを使用できます。 これらは、使用中の特定のトランスポート チャネル (HTTP、TCP など) によって適用されるクォータです。 このトピックでは、これらのクォータの一部について説明しますが、これらのクォータについてはトランスポート クォータで詳しく説明 します。
ハッシュテーブルの脆弱性
データ コントラクトにハッシュテーブルまたはコレクションが含まれている場合、脆弱性が存在します。 この問題は、多数の値が同じハッシュ値を生成するハッシュテーブルに多数の値が挿入された場合に発生します。 これは DOS 攻撃として使用できます。 この脆弱性は、MaxReceivedMessageSize バインディング クォータを設定することで軽減できます。 このような攻撃を防ぐために、このクォータを設定するときは注意が必要です。 このクォータにより、WCF メッセージのサイズに上限が設定されます。 さらに、データ コントラクトでハッシュテーブルまたはコレクションを使用しないようにします。
ストリーミングなしでメモリ消費量を制限する
大きなメッセージに関するセキュリティ モデルは、ストリーミングが使用されているかどうかによって異なります。 基本的なストリーミング以外のケースでは、メッセージはメモリにバッファーされます。 この場合は、MaxReceivedMessageSizeまたはシステムが提供するバインディングでTransportBindingElement クォータを使用して、アクセスする最大メッセージ サイズを制限することで、大きなメッセージから保護します。 サービスが複数のメッセージを同時に処理している可能性があることに注意してください。その場合、それらはすべてメモリ内にあります。 この脅威を軽減するには、スロットリング機能を使用します。
また、 MaxReceivedMessageSize
はメッセージごとのメモリ消費に上限を設定せず、定数係数内に制限されることにも注意してください。 たとえば、 MaxReceivedMessageSize
が 1 MB で、1 MB のメッセージを受信して逆シリアル化する場合、逆シリアル化されたオブジェクト グラフを含めるために追加のメモリが必要になり、合計メモリ消費量が 1 MB を超えることになります。 このため、シリアル化可能な型を作成することは避けてください。これにより、大量の受信データなしで大量のメモリ消費が発生する可能性があります。 たとえば、50 個の省略可能なデータ メンバー フィールドを持つデータ コントラクト "MyContract" と、XML 構築 "<MyContract/>" を使用して、追加の 100 個のプライベート フィールドをインスタンス化できます。 この XML により、150 個のフィールドのメモリにアクセスされます。 既定では、データ メンバーは省略可能であることに注意してください。 このような型が配列の一部である場合、問題は複合化されます。
MaxReceivedMessageSize
は、サービス拒否攻撃をすべて防ぐには不十分です。 たとえば、受信メッセージによって、デシリアライザーが深く入れ子になったオブジェクト グラフ (オブジェクトに別のオブジェクトが格納され、その別のオブジェクトにさらに別のオブジェクトが格納されているということが繰り返されているオブジェクト) を逆シリアル化することを強制される場合があります。
DataContractSerializerとXmlSerializerの両方が入れ子になった方法でメソッドを呼び出して、このようなグラフを逆シリアル化します。 メソッド呼び出しを深く入れ子にすると、回復不能な StackOverflowExceptionが発生する可能性があります。 この脅威は、後の「XML を安全に使用する」セクションで説明するように、XML 入れ子のレベルを制限するように MaxDepth クォータを設定することで軽減されます。
バイナリ XML エンコードを使用する場合は、 MaxReceivedMessageSize
に追加のクォータを設定することが特に重要です。 バイナリ エンコードの使用は圧縮と多少同等です。受信メッセージ内の小さなバイト グループは、大量のデータを表している可能性があります。 したがって、 MaxReceivedMessageSize
制限に適合するメッセージであっても、完全に拡張された形式ではるかに多くのメモリを占有する可能性があります。 このような XML 固有の脅威を軽減するには、このトピックで後述する「XML を安全に使用する」セクションで説明するように、すべての XML リーダー クォータを正しく設定する必要があります。
ストリーミングによるメモリ使用量の制限
ストリーミング時に、サービス拒否攻撃から保護するために小さな MaxReceivedMessageSize
設定を使用できます。 ただし、ストリーミングではより複雑なシナリオが可能です。 たとえば、ファイル アップロード サービスは、使用可能なすべてのメモリより大きいファイルを受け入れます。 この場合、MaxReceivedMessageSize
を非常に大きな値に設定します。これにより、データがメモリにほとんどバッファーされず、メッセージがディスクへ直接ストリームされることを意図しています。 悪意のあるメッセージが、この場合にストリーミングするのではなく、何らかの方法で WCF にデータのバッファーを強制する可能性がある場合、 MaxReceivedMessageSize
は、使用可能なすべてのメモリにアクセスするメッセージから保護されなくなります。
この脅威を軽減するために、バッファリングを制限するさまざまな WCF データ処理コンポーネントに特定のクォータ設定が存在します。 これらの中で最も重要なのは、さまざまなトランスポート バインド要素と標準バインドの MaxBufferSize
プロパティです。 ストリーミング時には、メッセージごとに割り当てるメモリの最大量を考慮して、このクォータを設定する必要があります。
MaxReceivedMessageSize
と同様に、この設定はメモリ消費量に絶対最大値を設定するのではなく、一定の係数内のみに制限します。 また、 MaxReceivedMessageSize
と同様に、複数のメッセージが同時に処理される可能性があることに注意してください。
MaxBufferSize の詳細
MaxBufferSize
プロパティは、WCF が行う一括バッファリングを制限します。 たとえば、WCF は常に SOAP ヘッダーと SOAP エラー、およびメッセージ送信最適化メカニズム (MTOM) メッセージの自然な読み取り順序に含まれていないことが判明した MIME パーツをバッファーします。 この設定により、これらすべての場合のバッファリングの量が制限されます。
WCF は、バッファーに格納できるさまざまなコンポーネントに MaxBufferSize
値を渡すことによってこれを実現します。 たとえば、CreateMessage クラスの一部のMessageオーバーロードは、maxSizeOfHeaders
パラメーターを受け取ります。 WCF は、SOAP ヘッダーバッファリングの量を制限するために、 MaxBufferSize
値をこのパラメーターに渡します。
Message クラスを直接使用する場合は、このパラメーターを設定することが重要です。 一般に、クォータ パラメーターを受け取るコンポーネントを WCF で使用する場合は、これらのパラメーターのセキュリティへの影響を理解し、正しく設定することが重要です。
MTOM メッセージ エンコーダーには、 MaxBufferSize
設定もあります。 標準バインドを使用する場合、これはトランスポート レベルの MaxBufferSize
値に自動的に設定されます。 ただし、MTOM メッセージ エンコーダー バインド要素を使用してカスタム バインドを構築する場合は、ストリーミングを使用するときに、 MaxBufferSize
プロパティを安全な値に設定することが重要です。
XML ベースのストリーミング攻撃
MaxBufferSize
ストリーミングが予想される場合に WCF を強制的にバッファリングできないようにするには、単独では不十分です。 たとえば、WCF XML リーダーは、新しい要素の読み取りを開始するときに、XML 要素の開始タグ全体を常にバッファーします。 これにより、名前空間と属性が適切に処理されます。
MaxReceivedMessageSize
が大きく構成されている場合 (たとえば、ディスクへの直接の大きなファイル ストリーミング シナリオを有効にするために)、メッセージ本文全体が大きな XML 要素の開始タグである悪意のあるメッセージが作成される可能性があります。 読み取ろうとすると、 OutOfMemoryExceptionが発生します。 これは、XML リーダー クォータを使用してすべて軽減できる、XML ベースのサービス拒否攻撃の 1 つであり、このトピックで後述する「XML を安全に使用する」セクションで説明します。 ストリーミングするときは、これらのクォータをすべて設定することが特に重要です。
ストリーミングプログラミングモデルとバッファリングプログラミングモデルの混在
ストリーミング プログラミング モデルと非ストリーミング プログラミング モデルを同じサービスに混在させることが原因で、多くの攻撃が発生する可能性があります。 2 つの操作を含むサービス コントラクトがあるとします。1 つは Stream を受け取り、もう 1 つはカスタム型の配列を受け取ります。 また、 MaxReceivedMessageSize
が大きな値に設定され、最初の操作で大きなストリームを処理できるようになるとします。 残念ながら、これは、大きなメッセージを 2 番目の操作にも送信できるようになったことを意味し、逆シリアライザーは、操作が呼び出される前にメモリ内のデータを配列としてバッファーします。 これはサービス拒否攻撃の可能性があります。 MaxBufferSize
クォータではメッセージ本文のサイズは制限されません。これは、デシリアライザーが動作するものです。
このため、同じコントラクトでストリーム ベースの操作と非ストリーム操作を混在させないようにします。 2 つのプログラミング モデルを絶対に混在する必要がある場合は、次の予防措置を使用します。
IExtensibleDataObjectの IgnoreExtensionDataObject プロパティを ServiceBehaviorAttribute に設定して、
true
機能をオフにします。 これにより、コントラクトの一部であるメンバーのみが逆シリアル化されます。MaxItemsInObjectGraphのDataContractSerializer プロパティを安全な値に設定します。 このクォータは、 ServiceBehaviorAttribute 属性または構成でも使用できます。 このクォータは、1 回の逆シリアル化エピソードで逆シリアル化されるオブジェクトの数を制限します。 通常、メッセージ コントラクト内の各操作パラメーターまたはメッセージ本文部分は、1 つのエピソードで逆シリアル化されます。 配列を逆シリアル化する場合、各配列エントリは個別のオブジェクトとしてカウントされます。
すべての XML リーダー クォータを安全な値に設定します。 MaxDepth、MaxStringContentLength、およびMaxArrayLengthに注意し、ストリーミング以外の操作では文字列を避けてください。
既知の型の一覧を確認します。いずれかの型はいつでもインスタンス化できることに注意してください (このトピックの「意図しない型が読み込まれないようにする」セクションを参照してください)。
大量のデータをバッファーする IXmlSerializable インターフェイスを実装する型は使用しないでください。 このような型を既知の型の一覧に追加しないでください。
XmlElement、XmlNode配列、Byte配列、またはコントラクトにISerializableを実装する型は使用しないでください。
XmlElement、XmlNode配列、Byte配列、または既知の型の一覧にISerializableを実装する型は使用しないでください。
上記の予防措置は、ストリーミングされていない操作で DataContractSerializerを使用する場合に適用されます。 XmlSerializerを使用している場合は、MaxItemsInObjectGraph クォータの保護がないため、ストリーミング プログラミング モデルと非ストリーミング プログラミング モデルを同じサービスで混在させないようにします。
スロー ストリーム攻撃
ストリーミングサービス拒否攻撃のクラスには、メモリ消費は含まれません。 その代わりに、攻撃は元々動作が遅いデータ送信者または受信者を利用します。 データの送受信を待っている間に、スレッドや使用可能な接続などのリソースが使い果たされます。 この状況は、悪意のある攻撃の結果として、または低速のネットワーク接続で正当な送信者/受信者から発生する可能性があります。
これらの攻撃を軽減するには、トランスポートタイムアウトを正しく設定します。 詳細については、「 トランスポート クォータ」を参照してください。 第 2 に、WCF でストリームを操作するときは、同期 Read
操作や Write
操作を使用しないでください。
XML を安全に使用する
注
このセクションでは XML について説明しますが、この情報は JavaScript Object Notation (JSON) ドキュメントにも適用されます。 クォータは、 JSON と XML の間のマッピングを使用して同様に機能します。
セキュリティで保護された XML リーダー
XML 情報セットは、WCF のすべてのメッセージ処理の基礎を形成します。 信頼されていないソースから XML データを受け入れる場合、軽減する必要があるサービス拒否攻撃の可能性が多数存在します。 WCF には、セキュリティで保護された特別な XML リーダーが用意されています。 これらのリーダーは、WCF (テキスト、バイナリ、または MTOM) で標準エンコードのいずれかを使用する場合に自動的に作成されます。
これらのリーダーのセキュリティ機能の一部は常にアクティブです。 たとえば、閲覧者はドキュメント型定義 (DTD) を処理しません。これはサービス拒否攻撃の潜在的な原因であり、正当な SOAP メッセージには表示されません。 その他のセキュリティ機能には、次のセクションで説明する、構成する必要があるリーダー クォータが含まれます。
XML リーダーを直接操作する場合 (独自のカスタム エンコーダーを作成するときや、 Message クラスを直接操作する場合など)、信頼されていないデータを操作する可能性がある場合は、常に WCF セキュリティで保護されたリーダーを使用します。
CreateTextReader クラスのCreateBinaryReader、CreateMtomReader、またはXmlDictionaryReaderのいずれかの静的ファクトリ メソッド オーバーロードを呼び出して、セキュリティで保護されたリーダーを作成します。 リーダーを作成するときは、セキュリティで保護されたクォータ値を渡します。
Create
メソッドのオーバーロードを呼び出さないでください。 これらは WCF リーダーを作成しません。 代わりに、このセクションで説明するセキュリティ機能によって保護されていないリーダーが作成されます。
リーダーのクォータ
セキュリティで保護された XML リーダーには、5 つの構成可能なクォータがあります。 通常、これらはエンコード バインド要素または標準バインドの ReaderQuotas
プロパティを使用するか、リーダーの作成時に渡される XmlDictionaryReaderQuotas オブジェクトを使用して構成されます。
MaxBytesPerRead
このクォータは、要素の開始タグとその属性を読み取るときに、1 つの Read
操作で読み取るバイト数を制限します。 (ストリーミングされない場合、要素名自体はクォータに対してカウントされません)。 MaxBytesPerRead は、次の理由で重要です。
要素名とその属性は、読み取り時に常にメモリにバッファーされます。 そのため、ストリーミングが予想される場合に過剰なバッファリングを防ぐために、ストリーミング モードでこのクォータを正しく設定することが重要です。 実際に行われるバッファリングの量については、「
MaxDepth
クォータ」セクションを参照してください。XML 属性の数が多すぎると、属性名の一意性をチェックする必要があるため、処理に時間がかかる可能性があります。
MaxBytesPerRead
は、この脅威を軽減します。
最大深度
このクォータにより、XML 要素の入れ子の最大深度が制限されます。 たとえば、ドキュメント "<A><B><C/></B></A>" の入れ子の深さは 3 です。 MaxDepth は、次の理由で重要です。
MaxDepth
は、MaxBytesPerRead
と対話します。リーダーは常に、現在の要素とそのすべての先祖のメモリにデータを保持するため、リーダーの最大メモリ消費量は、これら 2 つの設定の積に比例します。深いネストのオブジェクトグラフを逆シリアル化すると、デシリアライザーはスタック全体にアクセスし、回復不能なStackOverflowExceptionを投げることを強制されます。 XML の入れ子とオブジェクトの入れ子の間には、 DataContractSerializer と XmlSerializerの両方に対して直接的な相関関係があります。 この脅威を軽減するには、
MaxDepth
を使用します。
MaxNameTableCharCount
このクォータにより、リーダーの 名前テーブルのサイズが制限されます。 名前テーブルには、XML ドキュメントの処理中に検出される特定の文字列 (名前空間やプレフィックスなど) が含まれています。 これらの文字列はメモリ内にバッファーされるため、ストリーミングが予想される場合に過剰なバッファリングを防ぐために、このクォータを設定します。
最大文字列コンテンツ長
このクォータにより、XML リーダーから返される文字列の最大サイズが制限されます。 このクォータでは、XML リーダー自体ではなく、リーダーを使用しているコンポーネントでのメモリ使用量が制限されます。 たとえば、 DataContractSerializer が MaxStringContentLengthで保護されたリーダーを使用する場合、このクォータより大きい文字列は逆シリアル化されません。 XmlDictionaryReader クラスを直接使用する場合、すべてのメソッドがこのクォータを考慮するわけではありませんが、ReadContentAsString メソッドなど、文字列を読み取るように特別に設計されたメソッドのみが考慮されます。 リーダーの Value プロパティは、このクォータの影響を受けないため、このクォータが提供する保護が必要な場合は使用しないでください。
MaxArrayLength
このクォータは、XML リーダーが返すプリミティブの配列の最大サイズ (バイト配列を含む) を制限します。 このクォータでは、XML リーダー自体のメモリ消費量は制限されず、リーダーを使用しているコンポーネントでは制限されません。 たとえば、 DataContractSerializer が MaxArrayLength で保護されたリーダーを使用する場合、このクォータより大きいバイト配列は逆シリアル化されません。 ストリーミング とバッファープログラミング モデルを 1 つのコントラクトで混在させる場合は、このクォータを設定することが重要です。 XmlDictionaryReader クラスを直接使用する場合、ReadInt32Arrayなど、特定のプリミティブ型の任意のサイズの配列を読み取るように特別に設計されたメソッドのみが、このクォータを考慮に入れている点に注意してください。
バイナリ エンコードに固有の脅威
WCF でサポートされているバイナリ XML エンコードには、 ディクショナリ文字列 機能が含まれています。 大きな文字列は、数バイトのみを使用してエンコードできます。 これにより、パフォーマンスが大幅に向上しますが、軽減する必要がある新しいサービス拒否の脅威が発生します。
ディクショナリには、 静的 と 動的の 2 種類があります。 静的ディクショナリは、バイナリ エンコードの短いコードを使用して表される長い文字列の組み込みリストです。 この文字列の一覧は、リーダーの作成時に修正され、変更できません。 WCF が既定で使用する静的ディクショナリ内の文字列は、ディクショナリ拡張攻撃で引き続き使用される可能性がありますが、サービス拒否の深刻な脅威を引き起こすのに十分な大きさはありません。 独自の静的ディクショナリを指定する高度なシナリオでは、大きなディクショナリ文字列を導入するときは注意してください。
動的ディクショナリ機能を使用すると、メッセージで独自の文字列を定義し、短いコードに関連付けることができます。 これらの文字列からコードへのマッピングは、通信セッション全体でメモリに保持されるため、後続のメッセージで文字列を再送信する必要がなく、既に定義されているコードを利用できます。 これらの文字列は任意の長さである可能性があるため、静的ディクショナリの文字列よりも深刻な脅威が発生します。
軽減する必要がある最初の脅威は、動的ディクショナリ (文字列からコードへのマッピング テーブル) が大きくなりすぎる可能性です。 このディクショナリは複数のメッセージの過程で拡張される可能性があるため、 MaxReceivedMessageSize
クォータは各メッセージにのみ個別に適用されるため、保護を提供しません。 したがって、ディクショナリのサイズを制限する個別の MaxSessionSize プロパティが BinaryMessageEncodingBindingElement に存在します。
他のほとんどのクォータとは異なり、このクォータはメッセージの書き込み時にも適用されます。 メッセージの読み取り時にこのクォータを超えた場合は、 QuotaExceededException
が通常どおりスローされます。 メッセージの書き込み時に超過した場合、クォータを超える原因となる文字列は、動的ディクショナリ機能を使用せずに as-is書き込まれます。
辞書拡張の脅威
バイナリ固有の攻撃の重要なクラスは、辞書の拡張から発生します。 バイナリ形式の小さなメッセージは、文字列辞書機能を広範に使用する場合、完全に拡張されたテキスト形式で非常に大きなメッセージに変わる可能性があります。 動的ディクショナリ文字列の拡張係数は、ディクショナリ全体の最大サイズを超える動的ディクショナリ文字列がないため、 MaxSessionSize クォータによって制限されます。
MaxNameTableCharCount、MaxStringContentLength
、およびMaxArrayLength
のプロパティでは、メモリ使用量のみが制限されます。 メモリ使用量は既に MaxReceivedMessageSize
によって制限されているため、通常、ストリーミングされない使用量の脅威を軽減する必要はありません。 ただし、 MaxReceivedMessageSize
は拡張前のバイト数をカウントします。 バイナリ エンコードが使用されている場合、メモリ消費量は MaxReceivedMessageSize
を超える可能性があり、 MaxSessionSizeの要因によってのみ制限される可能性があります。 このため、バイナリ エンコードを使用するときは、常にすべてのリーダー クォータ (特に MaxStringContentLength) を設定することが重要です。
バイナリ エンコードを DataContractSerializerと共に使用する場合、 IExtensibleDataObject
インターフェイスを誤ってディクショナリ拡張攻撃をマウントする可能性があります。 このインターフェイスは基本的に、コントラクトの一部ではない任意のデータに無制限のストレージを提供します。
MaxSessionSize
にMaxReceivedMessageSize
を掛けて問題が発生しないようにクォータを十分に低く設定できない場合は、バイナリ エンコードを使用するときにIExtensibleDataObject
機能を無効にします。
IgnoreExtensionDataObject
プロパティを true
属性にServiceBehaviorAttribute
するように設定します。 または、 IExtensibleDataObject
インターフェイスを実装しないでください。 詳細については、「 Forward-Compatible データ コントラクト」を参照してください。
クォータの概要
次の表は、クォータに関するガイダンスをまとめたものです。
条件 | 設定が重要なクォータ |
---|---|
ストリーミングや小さなメッセージ、テキスト、または MTOM エンコードの使用は禁止されています。 |
MaxReceivedMessageSize 、MaxBytesPerRead 、MaxDepth |
ストリーミングなし、または小さなメッセージのストリーミングにバイナリ エンコードを使用する |
MaxReceivedMessageSize 、 MaxSessionSize 、およびすべて ReaderQuotas |
大きなメッセージ、テキスト、または MTOM エンコードのストリーミング |
MaxBufferSize およびすべての ReaderQuotas |
大きなメッセージのストリーミング、バイナリ エンコード |
MaxBufferSize 、 MaxSessionSize 、およびすべて ReaderQuotas |
トランスポート レベルのタイムアウトは常に設定する必要があります。また、大きいメッセージと小さいメッセージをストリーミングするかどうかにかかわらず、ストリーミングが使用中の場合は同期読み取り/書き込みを使用しないでください。
クォータが不明な場合は、クォータを開いたままにするのではなく、安全な値に設定します。
悪意のあるコード実行の防止
次の脅威の一般的なクラスは、コードを実行し、意図しない影響を及ぼす可能性があります。
デシリアライザーが、悪質、安全でない、またはセキュリティに注意する必要がある型を読み込んでしまう。
受信メッセージにより、デシリアライザーは、通常は安全だとされる型のインスタンスを、意図しない結果を招くような方法で生成します。
以降のセクションでは、これらの脅威のクラスについてさらに説明します。
DataContractSerializer
( XmlSerializerのセキュリティ情報については、関連するドキュメントを参照してください)。 XmlSerializer のセキュリティ モデルは DataContractSerializerのセキュリティ モデルに似ていますが、主に詳細が異なります。 たとえば、 XmlIncludeAttribute 属性は、 KnownTypeAttribute 属性ではなく型包含に使用されます。 ただし、 XmlSerializer 固有の脅威については、このトピックの後半で説明します。
意図しない型の読み込み防止
意図しない型を読み込むと、型が悪意のある場合でも、セキュリティに影響を受けやすい副作用がある場合でも、大きな影響を及ぼす可能性があります。 型には、悪用可能なセキュリティの脆弱性が含まれている可能性があります。また、コンストラクターまたはクラス コンストラクターでセキュリティに依存するアクションを実行したり、サービス拒否攻撃を容易にする大きなメモリ占有領域を持ったり、回復不可能な例外をスローしたりする可能性があります。 型には、型が読み込まれるとすぐに、インスタンスが作成される前に実行されるクラス コンストラクターがある場合があります。 このような理由から、デシリアライザーが読み込む可能性がある型のセットを制御することが重要です。
DataContractSerializerは疎結合な方法でデシリアライズされます。 受信データから共通言語ランタイム (CLR) 型とアセンブリ名を読み取ることはありません。 これは XmlSerializerの動作に似ていますが、 NetDataContractSerializer、 BinaryFormatter、および SoapFormatterの動作とは異なります。 疎結合では安全性が高くなります。リモート攻撃者は、メッセージ内でその型に名前を付けるだけでは、読み込む任意の型を示すことができないためです。
DataContractSerializerは、コントラクトに従って現在想定されている型を常に読み込むことができます。 たとえば、データ コントラクトに Customer
型のデータ メンバーがある場合、 DataContractSerializer はこのデータ メンバーを逆シリアル化するときに Customer
型を読み込むことができます。
さらに、 DataContractSerializer はポリモーフィズムをサポートします。 データ メンバーは Objectとして宣言できますが、受信データには Customer
インスタンスが含まれている場合があります。 これは、 Customer
型が次のいずれかのメカニズムを介してデシリアライザーに "既知" になっている場合にのみ可能です。
KnownTypeAttribute 属性が型に適用されます。
KnownTypeAttribute
型のリストを返すメソッドを指定する属性。ServiceKnownTypeAttribute
属性を使用する。KnownTypes
構成セクション。シリアライザーを直接使用する場合、構築中に DataContractSerializer に明示的に渡される既知の型の一覧。
これらの各メカニズムは、デシリアライザーが読み込むことができる型を増やすことで、サーフェス領域を増やします。 既知の型の一覧に悪意のある型や意図しない型が追加されないように、これらの各メカニズムを制御します。
既知の型がスコープ内にあれば、いつでも読み込むことができます。また、コントラクトが実際に使用を禁止している場合でも、型のインスタンスを作成できます。 たとえば、上記のいずれかのメカニズムを使用して、型 "MyDangerousType" が既知の型リストに追加されるとします。 これは、次のことを意味します。
MyDangerousType
が読み込まれ、そのクラス コンストラクターが実行されます。文字列データ メンバーを使用してデータ コントラクトを逆シリアル化しても、悪意のあるメッセージによって
MyDangerousType
のインスタンスが作成される可能性があります。 プロパティ セッターなどのMyDangerousType
内のコードが実行される場合があります。 これが完了すると、デシリアライザーはこのインスタンスを文字列データ メンバーに割り当てようとし、例外で失敗します。
既知の型のリストを返すメソッドを記述する場合、またはリストを DataContractSerializer コンストラクターに直接渡す場合は、リストを準備するコードがセキュリティで保護され、信頼されたデータでのみ動作することを確認します。
構成で既知の種類を指定する場合は、構成ファイルがセキュリティで保護されていることを確認します。 (型が存在する署名付きアセンブリの公開キーを指定して) 構成では常に厳密な名前を使用しますが、読み込む型のバージョンは指定しないでください。 タイプ ローダーは、可能であれば、最新バージョンを自動的に選択します。 構成で特定のバージョンを指定した場合は、次のリスクが発生します。種類には、将来のバージョンで修正される可能性があるセキュリティの脆弱性がある可能性がありますが、脆弱なバージョンは、構成で明示的に指定されているため、引き続き読み込まれます。
既知の型が多すぎると、別の結果が発生します。 DataContractSerializer は、シリアル化/逆シリアル化コードのキャッシュをアプリケーション ドメインに作成し、シリアル化および逆シリアル化する必要がある各型のエントリを使用します。 アプリケーション ドメインが実行されている限り、このキャッシュはクリアされません。 そのため、アプリケーションが多くの既知の型を使用していることを認識している攻撃者は、これらすべての型の逆シリアル化を引き起こす可能性があり、キャッシュは非常に大量のメモリを消費する可能性があります。
型の意図しない状態の防止
型には、適用する必要がある内部整合性制約がある場合があります。 逆シリアル化中にこれらの制約が壊れないように注意する必要があります。
次の型の例は、宇宙船のエアロックの状態を表し、内側と外側の両方のドアを同時に開くことができないという制約を適用します。
[DataContract]
public class SpaceStationAirlock
{
[DataMember]
private bool innerDoorOpenValue = false;
[DataMember]
private bool outerDoorOpenValue = false;
public bool InnerDoorOpen
{
get { return innerDoorOpenValue; }
set
{
if (value & outerDoorOpenValue)
throw new Exception("Cannot open both doors!");
else innerDoorOpenValue = value;
}
}
public bool OuterDoorOpen
{
get { return outerDoorOpenValue; }
set
{
if (value & innerDoorOpenValue)
throw new Exception("Cannot open both doors!");
else outerDoorOpenValue = value;
}
}
}
<DataContract()> _
Public Class SpaceStationAirlock
<DataMember()> Private innerDoorOpenValue As Boolean = False
<DataMember()> Private outerDoorOpenValue As Boolean = False
Public Property InnerDoorOpen() As Boolean
Get
Return innerDoorOpenValue
End Get
Set(ByVal value As Boolean)
If (value & outerDoorOpenValue) Then
Throw New Exception("Cannot open both doors!")
Else
innerDoorOpenValue = value
End If
End Set
End Property
Public Property OuterDoorOpen() As Boolean
Get
Return outerDoorOpenValue
End Get
Set(ByVal value As Boolean)
If (value & innerDoorOpenValue) Then
Throw New Exception("Cannot open both doors!")
Else
outerDoorOpenValue = value
End If
End Set
End Property
End Class
攻撃者はこのような悪意のあるメッセージを送信し、制約を回避し、オブジェクトを無効な状態にして、意図しない予期しない結果を招く可能性があります。
<SpaceStationAirlock>
<innerDoorOpen>true</innerDoorOpen>
<outerDoorOpen>true</outerDoorOpen>
</SpaceStationAirlock>
この状況は、次の点に注意することで回避できます。
DataContractSerializerがほとんどのクラスを逆シリアル化する場合、コンストラクターは実行されません。 したがって、コンストラクターで実行される状態管理に依存しないでください。
コールバックを使用して、オブジェクトが有効な状態であることを確認します。 OnDeserializedAttribute属性でマークされたコールバックは、逆シリアル化が完了した後に実行され、全体的な状態を調べて修正できるため、特に便利です。 詳細については、Version-Tolerant シリアル化コールバックを参照してください。
プロパティ セッターを呼び出す必要がある特定の順序に依存するようにデータ コントラクト型を設計しないでください。
SerializableAttribute属性でマークされたレガシ型を使用する場合は注意してください。 それらの多くは、信頼されたデータでのみ使用するために .NET Framework リモート処理を使用するように設計されています。 この属性でマークされた既存の型は、状態の安全性を念頭に置いて設計されていない可能性があります。
状態の安全性に関する限り、データの存在を保証するために、IsRequired属性のDataMemberAttributeプロパティに依存しないでください。 データは常に
null
、zero
、またはinvalid
にすることができます。信頼されていないデータ ソースから逆シリアル化されたオブジェクト グラフを、最初に検証せずに信頼しないでください。 個々のオブジェクトは一貫した状態にある場合がありますが、オブジェクト グラフ全体が一致しない可能性があります。 さらに、オブジェクト グラフの保持モードが無効になっている場合でも、逆シリアル化されたグラフは、同じオブジェクトへの複数の参照を持っているか、循環参照を持つことができます。 詳細については、「 シリアル化と逆シリアル化」を参照してください。
NetDataContractSerializer を安全に使用する
NetDataContractSerializerは、型との緊密な結合を使用するシリアル化エンジンです。 これは、 BinaryFormatter と SoapFormatterに似ています。 つまり、受信データから .NET Framework アセンブリと型名を読み取って、インスタンス化する型を決定します。 WCF の一部ですが、このシリアル化エンジンに接続する方法は提供されていません。カスタム コードを記述する必要があります。
NetDataContractSerializer
は、主に .NET Framework リモート処理から WCF への移行を容易にするために提供されます。 詳細については、「 シリアル化と逆シリアル化」の関連セクションを参照してください。
メッセージ自体は任意の型を読み込むことができる可能性があるため、 NetDataContractSerializer メカニズムは本質的に安全でないため、信頼できるデータでのみ使用する必要があります。 詳細については、「BinaryFormatter セキュリティ ガイド」を参照してください。
信頼できるデータと共に使用した場合でも、特に AssemblyFormat プロパティが Simple に設定されている場合、受信データで読み込む型が十分に指定されないことがあります。 アプリケーションのディレクトリまたはグローバル アセンブリ キャッシュにアクセスできるユーザーは、読み込むはずのディレクトリの代わりに悪意のある種類を置き換えることができます。 アクセス許可を正しく設定して、アプリケーションのディレクトリとグローバル アセンブリ キャッシュのセキュリティを常に確保してください。
一般に、 NetDataContractSerializer
インスタンスへの部分的に信頼されたコード アクセスを許可する場合、または代理セレクター (ISurrogateSelector) またはシリアル化バインダー (SerializationBinder) を制御する場合、コードはシリアル化/逆シリアル化プロセスを大幅に制御できます。 たとえば、任意の型を挿入したり、情報漏えいを引き起こし、結果のオブジェクト グラフやシリアル化されたデータを改ざんしたり、生成されたシリアル化されたストリームをオーバーフローさせたりすることがあります。
NetDataContractSerializer
に関するもう 1 つのセキュリティ上の懸念は、悪意のあるコード実行の脅威ではなく、サービス拒否です。
NetDataContractSerializer
を使用する場合は、常にMaxItemsInObjectGraphクォータを安全な値に設定します。 このクォータによってのみサイズが制限されているオブジェクトの配列を割り当てる小さな悪意のあるメッセージを簡単に作成できます。
XmlSerializer 固有の脅威
XmlSerializer セキュリティ モデルは、DataContractSerializerのセキュリティ モデルと似ています。 ただし、いくつかの脅威は、 XmlSerializerに固有です。
XmlSerializerは、実際にシリアル化および逆シリアル化するコードを含むシリアル化アセンブリを実行時に生成します。これらのアセンブリは、一時ファイル ディレクトリに作成されます。 他のプロセスまたはユーザーがそのディレクトリへのアクセス権を持っている場合、シリアル化/逆シリアル化コードを任意のコードで上書きする可能性があります。 その後、 XmlSerializer は、シリアル化/逆シリアル化コードではなく、セキュリティ コンテキストを使用してこのコードを実行します。 一時ファイル ディレクトリでアクセス許可が正しく設定されていることを確認して、この問題が発生しないようにします。
XmlSerializerには、実行時に生成するのではなく、事前に生成されたシリアル化アセンブリを使用するモードもあります。 このモードは、 XmlSerializer が適切なシリアル化アセンブリを見つけるたびにトリガーされます。 XmlSerializerは、シリアル化される型を含むアセンブリの署名に使用されたのと同じキーによってシリアル化アセンブリが署名されたかどうかを確認します。 これにより、シリアル化アセンブリとして偽装されている悪意のあるアセンブリからの保護が提供されます。 ただし、シリアル化可能な型を含むアセンブリが署名されていない場合、 XmlSerializer はこのチェックを実行できず、正しい名前のアセンブリを使用します。 これにより、悪意のあるコードが実行される可能性があります。 悪意のあるアセンブリの導入を防ぐために、シリアル化可能な型を含むアセンブリに常に署名するか、アプリケーションのディレクトリとグローバル アセンブリ キャッシュへのアクセスを厳密に制御します。
XmlSerializerは、サービス拒否攻撃の対象となる可能性があります。
XmlSerializerにはMaxItemsInObjectGraph
クォータがありません (DataContractSerializerで使用できます)。 したがって、メッセージ サイズによってのみ制限される任意の量のオブジェクトを逆シリアル化します。
部分信頼の脅威
部分信頼で実行されているコードに関連する脅威に関する次の懸念事項に注意してください。 これらの脅威には、悪意のある部分的に信頼されたコードと、悪意のある部分的に信頼されたコードが他の攻撃シナリオと組み合わせて含まれます (たとえば、特定の文字列を構築して逆シリアル化する部分信頼コード)。
シリアル化コンポーネントを使用する場合は、シリアル化シナリオ全体がアサートのスコープ内にあり、信頼されていないデータまたはオブジェクトを処理していない場合でも、このような使用前にアクセス許可をアサートしないでください。 このような使用は、セキュリティの脆弱性につながる可能性があります。
部分的に信頼されたコードが、拡張ポイント (サロゲート)、シリアル化される型、またはその他の手段を使用してシリアル化プロセスを制御している場合、部分的に信頼されたコードによって、シリアライザーがシリアル化ストリームに大量のデータを出力する可能性があり、このストリームの受信側にサービス拒否 (DoS) が発生する可能性があります。 DoS の脅威の影響を受けやすいターゲットを対象にデータをシリアル化する場合は、部分的に信頼された型をシリアル化しないか、部分的に信頼されたコードがシリアル化を制御できるようにします。
DataContractSerializer インスタンスへの部分的に信頼されたコード アクセスを許可する場合、またはデータ コントラクト サロゲートを制御する場合は、シリアル化/逆シリアル化プロセスを大幅に制御できます。 たとえば、任意の型を挿入したり、情報漏えいを引き起こし、結果のオブジェクト グラフやシリアル化されたデータを改ざんしたり、生成されたシリアル化されたストリームをオーバーフローさせたりすることがあります。 同等の NetDataContractSerializer 脅威については、「NetDataContractSerializer を安全に使用する」セクションで説明されています。
DataContractAttribute属性が型 (またはSerializableAttributeとしてマークされているがISerializableされていない型) に適用される場合、デシリアライザーは、すべてのコンストラクターが非パブリックであるか、要求によって保護されている場合でも、このような型のインスタンスを作成できます。
逆シリアル化するデータが信頼され、すべての既知の型が信頼できる型であることが確実でない限り、逆シリアル化の結果を信頼しないでください。 既知の型はアプリケーション構成ファイルから読み込まれず、部分信頼で実行されている場合は (ただし、コンピューター構成ファイルから読み込まれます) ことに注意してください。
部分的に信頼されたコードにサロゲートが追加された DataContractSerializer インスタンスを渡すと、そのサロゲートの変更可能な設定を変更できます。
逆シリアル化されたオブジェクトの場合、XML リーダー (またはその中のデータ) が部分的に信頼されたコードから取得される場合は、結果の逆シリアル化されたオブジェクトを信頼されていないデータとして扱います。
ExtensionDataObject型にパブリック メンバーが存在しないという事実は、その中のデータがセキュリティで保護されていることを意味するものではありません。 たとえば、特権データ ソースから一部のデータが存在するオブジェクトに逆シリアル化し、そのオブジェクトを部分的に信頼されたコードに渡す場合、部分的に信頼されたコードは、オブジェクトをシリアル化することで、
ExtensionDataObject
内のデータを読み取ることができます。 特権データ ソースから、後で部分的に信頼されたコードに渡されるオブジェクトに逆シリアル化する場合は、 IgnoreExtensionDataObject をtrue
に設定することを検討してください。DataContractSerializer と DataContractJsonSerializer は、完全な信頼でプライベート、保護、内部、およびパブリック メンバーのシリアル化をサポートします。 ただし、部分信頼では、パブリック メンバーのみをシリアル化できます。 アプリケーションがパブリック メンバー以外のメンバーのシリアル化を試みると、 SecurityException がスローされます。
内部メンバーまたは保護された内部メンバーを部分信頼でシリアル化できるようにするには、 InternalsVisibleToAttribute アセンブリ属性を使用します。 この属性を使用すると、アセンブリは、その内部メンバーが他のアセンブリから参照可能であることを宣言できます。 この場合、内部メンバーをシリアル化するアセンブリは、その内部メンバーが System.Runtime.Serialization.dllに表示されることを宣言します。
この方法の利点は、昇格されたコード生成パスを必要としないことです。
同時に、2 つの大きな欠点があります。
1 つ目の欠点は、 InternalsVisibleToAttribute 属性のオプトイン プロパティがアセンブリ全体に及ぶことです。 つまり、特定のクラスだけが内部メンバーをシリアル化できるように指定することはできません。 もちろん、 DataMemberAttribute 属性をそのメンバーに追加しないだけで、特定の内部メンバーをシリアル化しないことを選択することもできます。 同様に、メンバーをプライベート メンバーまたはプロテクト メンバーではなく内部メンバーにすることもできますが、参照可能範囲の問題が残ります。
2 つ目の欠点は、プライベート メンバーまたは保護されたメンバーがまだサポートされていないことです。
部分信頼での InternalsVisibleToAttribute 属性の使用を説明するには、次のプログラムを検討してください。
public class Program { public static void Main(string[] args) { try { // PermissionsHelper.InternetZone corresponds to the PermissionSet for partial trust. // PermissionsHelper.InternetZone.PermitOnly(); MemoryStream memoryStream = new MemoryStream(); new DataContractSerializer(typeof(DataNode)). WriteObject(memoryStream, new DataNode()); } finally { CodeAccessPermission.RevertPermitOnly(); } } [DataContract] public class DataNode { [DataMember] internal string Value = "Default"; } }
上記の例では、
PermissionsHelper.InternetZone
は部分信頼の PermissionSet に対応しています。 ここで、InternalsVisibleToAttribute属性がないと、パブリック メンバー以外のメンバーは部分信頼でシリアル化できないことを示す SecurityException がスローされてアプリケーションは失敗します。ただし、ソース ファイルに次の行を追加すると、プログラムは正常に実行されます。
[assembly:System.Runtime.CompilerServices.InternalsVisibleTo("System.Runtime.Serialization, PublicKey = 00000000000000000400000000000000")]
その他の状態管理に関する懸念事項
オブジェクト状態管理に関するその他のいくつかの懸念事項については、次の点に言及する必要があります。
ストリーミング トランスポートでストリーム ベースのプログラミング モデルを使用する場合、メッセージの受信時にメッセージの処理が行われます。 メッセージの送信者は、ストリームの途中で送信操作を中止する可能性があり、より多くのコンテンツが予想される場合、コードは予測不可能な状態になります。 一般に、ストリームの完了に依存せず、ストリームが中止された場合にロールバックできないストリーム ベースの操作では何も実行しないでください。 これは、ストリーミング本文の後にメッセージの形式が正しくない可能性がある状況にも当てはまります (たとえば、SOAP エンベロープの終了タグが見つからない場合や、2 つ目のメッセージ本文がある場合など)。
IExtensibleDataObject
機能を使用すると、機密データが出力される可能性があります。 信頼されていないソースからのデータを、IExtensibleObjectData
を使用してデータ コントラクトに受け入れ、後でメッセージが署名されているセキュリティで保護されたチャネルで再出力する場合は、何も知らないデータを保証している可能性があります。 さらに、既知のデータと不明なデータの両方を考慮に入れた場合、送信している全体的な状態が無効になる可能性があります。 拡張機能データ プロパティをnull
に選択的に設定するか、IExtensibleObjectData
機能を選択的に無効にすることで、このような状況を回避します。
スキーマのインポート
通常、スキーマをインポートして型を生成するプロセスは、デザイン時にのみ行われます。たとえば、Web サービスで ServiceModel メタデータ ユーティリティ ツール (Svcutil.exe) を使用してクライアント クラスを生成する場合です。 ただし、より高度なシナリオでは、実行時にスキーマを処理できます。 そうすると、サービス拒否リスクが発生する可能性があることに注意してください。 スキーマによっては、インポートに時間がかかる場合があります。 このようなシナリオでは、スキーマが信頼されていないソースから取得される可能性がある場合は、 XmlSerializer スキーマ インポート コンポーネントを使用しないでください。
ASP.NET AJAX 統合に固有の脅威
ユーザーが WebScriptEnablingBehavior または WebHttpBehaviorを実装すると、WCF は XML メッセージと JSON メッセージの両方を受け入れることができるエンドポイントを公開します。 ただし、XML リーダーと JSON リーダーの両方で使用されるリーダー クォータのセットは 1 つだけです。 特定のクォータ設定は、あるリーダーには適していても、別のリーダーにとっては大きすぎる場合があります。
WebScriptEnablingBehavior
を実装する場合、ユーザーにはエンドポイントで JavaScript プロキシを公開するオプションがあります。 次のセキュリティの問題を考慮する必要があります。
サービスに関する情報 (操作名、パラメーター名など) は、JavaScript プロキシを調べることで取得できます。
JavaScript エンドポイントを使用する場合、機密性の高い情報と個人情報がクライアント Web ブラウザー キャッシュに保持される場合があります。
コンポーネントに関する注意事項
WCF は、柔軟でカスタマイズ可能なシステムです。 このトピックの内容のほとんどは、最も一般的な WCF の使用シナリオに焦点を当てています。 ただし、WCF が提供するコンポーネントは、さまざまな方法で作成できます。 各コンポーネントを使用する場合のセキュリティへの影響を理解することが重要です。 具体的には次のとおりです。
XML リーダーを使用する必要がある場合は、他のリーダーではなく、 XmlDictionaryReader クラスが提供するリーダーを使用します。 安全なリーダーは、 CreateTextReader、 CreateBinaryReader、または CreateMtomReader メソッドを使用して作成されます。 Create メソッドは使用しないでください。 安全なクォータを使用してリーダーを常に構成します。 WCF のシリアル化エンジンは、WCF のセキュリティで保護された XML リーダーと共に使用される場合にのみセキュリティで保護されます。
DataContractSerializerを使用して信頼されていない可能性のあるデータを逆シリアル化する場合は、常に MaxItemsInObjectGraph プロパティを設定します。
メッセージを作成するときに、
maxSizeOfHeaders
で十分な保護が提供されない場合は、MaxReceivedMessageSize
パラメーターを設定します。エンコーダーを作成するときは、常に関連するクォータ (
MaxSessionSize
やMaxBufferSize
など) を構成します。XPath メッセージ フィルターを使用する場合は、フィルターがアクセスする XML ノードの量を制限するように NodeQuota を設定します。 多くのノードにアクセスせずに計算に時間がかかる可能性がある XPath 式は使用しないでください。
一般に、クォータを受け入れるコンポーネントを使用する場合は、そのセキュリティへの影響を理解し、安全な値に設定します。