Partager via


Sécurité et conditions de concurrence

Le risque d’exploitation de failles de sécurité par des conditions de concurrence représente également un sujet de préoccupation. Ceci peut se produire de différentes manières. Les sous-rubriques qui suivent décrivent certains des principaux pièges que le développeur doit éviter.

Conditions de concurrence dans la méthode Dispose

Si la méthode Dispose d’une classe (pour plus d’informations, consultez Garbage collection) n’est pas synchronisée, le code de nettoyage dans Dispose est susceptible d’être exécuté plusieurs fois comme illustré dans l’exemple suivant.

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;  
    }  
}  

Étant donné que cette implémentation Dispose n’est pas synchronisée, Cleanup peut être appelé par un premier thread, puis un deuxième thread avant que _myObj soit défini sur null. La question de savoir s’il s’agit d’un problème de sécurité dépend de ce qui se passe quand le code Cleanup s’exécute. Les implémentations Dispose non synchronisées posent un problème majeur vis-à-vis de l’utilisation de handles de ressources tels que des fichiers. Une suppression incorrecte peut entraîner l’utilisation d’un mauvais handle, ce qui provoque souvent des failles de sécurité.

Conditions de concurrence dans les constructeurs

Dans certaines applications, d’autres threads peuvent parfois accéder aux membres de classe avant que leurs constructeurs de classe n’aient été complètement exécutés. Vous devez passer en revue tous les constructeurs de classe pour prévenir tout problème de sécurité si cela venait à se produire, ou synchroniser les threads si nécessaire.

Conditions de concurrence avec des objets mis en cache

Le code qui met en cache les informations de sécurité ou utilise l’opération de sécurité d’accès du code Assert peut également être vulnérable aux conditions de concurrence si d’autres parties de la classe ne sont pas correctement synchronisées, comme illustré dans l’exemple suivant.

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();  
    }  
}  

S’il existe d’autres chemins à DoOtherWork qui peuvent être appelés à partir d’un autre thread avec le même objet, un appelant non approuvé peut effectuer une demande de manière furtive.

Si votre code met en cache des informations de sécurité, veillez à vérifier sa vulnérabilité à cet égard.

Conditions de concurrence dans les finaliseurs

Des conditions de concurrence peuvent également se produire dans un objet qui référence une ressource statique ou non managée, qu’il libère ensuite dans son finaliseur. Si plusieurs objets partagent une ressource manipulée dans le finaliseur d’une classe, ils doivent synchroniser tous les accès à cette ressource.

Voir aussi