보안 및 경합 상태

또 다른 우려 사항은 경쟁 조건으로 인해 보안 허점이 악용될 가능성이 있다는 것입니다. 이런 일이 발생할 수 있는 방법에는 여러 가지가 있습니다. 다음 하위 항목에서는 개발자가 피해야 하는 몇 가지 주요 문제에 대해 설명합니다.

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에 대한 다른 경로가 있는 경우 신뢰할 수 없는 호출자가 요구를 무시할 수 있습니다.

코드가 보안 정보를 캐시하는 경우 이 취약성이 있는지 검토합니다.

종료자의 경쟁 조건

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

참고 항목