セキュリティと競合状態
懸念されるもう 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
が最初の 1 つのスレッドから、その後 _myObj
が null に設定される前に、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
へのパスが他にもある場合は、信頼されていない呼び出し元の要求がすり抜けてしまう可能性があります。
コードでセキュリティ情報がキャッシュされている場合は、この脆弱性について見直しを行うようにしてください。
ファイナライザーの競合状態
競合状態は、静的リソースまたはアンマネージド リソースが参照され、後にファイナライザーで解放されるオブジェクトでも発生します。 クラスのファイナライザーによって操作されているリソースが複数のオブジェクトで共有されている場合、そのオブジェクトでは、そのリソースへのすべてのアクセスを同期する必要があります。
関連項目
.NET