次の方法で共有


セキュリティと競合状態

もう 1 つの懸念事項は、競合状態によって悪用されるセキュリティ ホールの可能性です。 この問題は、いくつかの方法で発生する可能性があります。 次のサブトピックでは、開発者が回避する必要がある主な落とし穴の一部を示します。

Dispose メソッドの競合状態

クラスの Dispose メソッド (詳細については、「 ガベージ コレクション」を参照) が同期されていない場合、次の例に示すように、 Dispose 内のクリーンアップ コードを複数回実行できる可能性があります。

Sub Dispose()  
    If Not (myObj Is Nothing) Then  
       Cleanup(myObj)  
       myObj = Nothing  
    End If  
End Sub  
void Dispose()
{  
    if (myObj != null)
    {  
        Cleanup(myObj);  
        myObj = null;  
    }  
}  

この Dispose 実装は同期されないため、Cleanup_myObj に設定される前に、最初の 1 つのスレッドと 2 番目のスレッドによってを呼び出す可能性があります。 これがセキュリティ上の問題であるかどうかは、 Cleanup コードの実行時に何が起こるかによって異なります。 同期されていない Dispose 実装の主な問題は、ファイルなどのリソース ハンドルの使用です。 不適切な破棄により、間違ったハンドルが使用される可能性があり、多くの場合、セキュリティの脆弱性につながります。

コンストラクターの競合状態

アプリケーションによっては、クラス コンストラクターが完全に実行される前に、他のスレッドがクラス メンバーにアクセスできる場合があります。 これが発生する必要がある場合は、すべてのクラス コンストラクターを確認してセキュリティの問題がないことを確認するか、必要に応じてスレッドを同期する必要があります。

キャッシュされたオブジェクトの競合状態

次の例に示すように、クラスの他の部分が適切に同期されていない場合、セキュリティ情報をキャッシュしたり、コード アクセス セキュリティ Assert 操作を使用したりするコードも競合状態に対して脆弱になる可能性があります。

Sub SomeSecureFunction()  
    If SomeDemandPasses() Then  
        fCallersOk = True  
        DoOtherWork()  
        fCallersOk = False  
    End If  
End Sub  
  
Sub DoOtherWork()  
    If fCallersOK Then  
        DoSomethingTrusted()  
    Else  
        DemandSomething()  
        DoSomethingTrusted()  
    End If  
End Sub  
void SomeSecureFunction()
{  
    if (SomeDemandPasses())
    {  
        fCallersOk = true;  
        DoOtherWork();  
        fCallersOk = false;  
    }  
}  
void DoOtherWork()
{  
    if (fCallersOK)
    {  
        DoSomethingTrusted();  
    }  
    else
    {  
        DemandSomething();  
        DoSomethingTrusted();  
    }  
}  

同じオブジェクトを持つ別のスレッドから呼び出すことができる DoOtherWork への他のパスがある場合、信頼されていない呼び出し元が要求を超える可能性があります。

コードがセキュリティ情報をキャッシュする場合は、この脆弱性を確認してください。

ファイナライザーの競合状態

競合状態は、ファイナライザーで解放される静的リソースまたはアンマネージ リソースを参照するオブジェクトでも発生する可能性があります。 クラスのファイナライザーで操作されるリソースを複数のオブジェクトが共有する場合、オブジェクトはそのリソースへのすべてのアクセスを同期する必要があります。

こちらも参照ください