다음을 통해 공유


보안 및 경쟁 조건

또 다른 관심사는 경합 조건에 의해 악용되는 보안 구멍의 가능성입니다. 이 문제가 발생할 수 있는 방법에는 여러 가지가 있습니다. 다음 하위 항목은 개발자가 피해야 하는 몇 가지 주요 문제를 간략하게 설명합니다.

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 두 번째 스레드를 null로 설정할 수 있습니다. 이것이 보안 문제인지 여부는 코드가 실행되면 어떻게 되는지에 Cleanup 따라 달라집니다. 동기화되지 않은 Dispose 구현의 주요 문제는 파일과 같은 리소스 핸들의 사용과 관련이 있습니다. 부적절한 폐기로 인해 잘못된 핸들이 사용될 수 있으며, 그 결과 보안 취약성이 자주 발생합니다.

생성자의 경합 조건

일부 애플리케이션에서는 클래스 생성자가 완전히 실행되기 전에 다른 스레드가 클래스 멤버에 액세스할 수 있습니다. 모든 클래스 생성자를 검토하여 이 문제가 발생하는 경우 보안 문제가 없는지 확인하거나 필요한 경우 스레드를 동기화해야 합니다.

캐시된 개체를 사용한 경합 조건

다음 예제와 같이 클래스의 다른 부분이 적절하게 동기화되지 않은 경우 보안 정보를 캐시하거나 코드 액세스 보안 어설션 작업을 사용하는 코드도 경합 조건에 취약할 수 있습니다.

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에 이르는 다른 경로가 있다면, 신뢰할 수 없는 호출자가 검사를 피할 수 있습니다.

코드가 보안 정보를 캐시하는 경우 이 취약성에 대해 검토해야 합니다.

종료자에서 발생하는 경합 상태

경합 조건은 종료자에서 해제하는 정적 또는 비관리 리소스를 참조하는 객체에서도 발생할 수 있습니다. 여러 개체가 클래스의 종료자에서 조작된 리소스를 공유하는 경우 개체는 해당 리소스에 대한 모든 액세스를 동기화해야 합니다.

참고하십시오