Compartir a través de


Proteger control de excepciones

En C++ y Visual Basic, se ejecuta una expresión de filtro más arriba de la pila antes de cualquier instrucción finally. El bloque catch asociado con ese filtro se ejecuta después de la instrucción finally. Para obtener más información, vea Utilizar excepciones filtradas por el usuario. En esta sección se analizan las repercusiones de seguir este orden en la seguridad. Observe el siguiente ejemplo de pseudocódigo que ilustra el orden en que se ejecutan las expresiones de filtro y las instrucciones finally.

void Main() 
{
    try 
    {
        Sub();
    } 
    except (Filter()) 
    {
        Console.WriteLine("catch");
    }
}
bool Filter () {
    Console.WriteLine("filter");
    return true;
}
void Sub() 
{
    try 
    {
        Console.WriteLine("throw");
        throw new Exception();
    } 
    finally 
    {
        Console.WriteLine("finally");
    }
}                      

Este código imprime lo siguiente.

Throw
Filter
Finally
Catch

El filtro se ejecuta antes de la instrucción finally, así que es posible introducir problemas de seguridad en todo aquello que produce un cambio de estado y permite aprovechar la ejecución de otro código. Por ejemplo:

try 
{
    Alter_Security_State();
    // This means changing anything (state variables,
    // switching unmanaged context, impersonation, and 
    // so on) that could be exploited if malicious 
    // code ran before state is restored.
    Do_some_work();
} 
finally 
{
    Restore_Security_State();
    // This simply restores the state change above.
}

Este pseudocódigo permite que un filtro situado más arriba de la pila ejecute un código arbitrario. Entre los ejemplos de operaciones que pueden tener un efecto similar está la suplantación provisional de otra identidad mediante un marcador interno que omita alguna comprobación de seguridad o cambiando la referencia cultural asociada con el subproceso. La solución más recomendable es introducir un controlador de excepciones para aislar los cambios del código en el estado de subproceso de los bloques de filtro de los llamadores. Sin embargo, es importante introducir correctamente el controlador de excepciones o no se solucionará este problema. En el ejemplo siguiente se cambia la referencia cultural de la interfaz de usuario, aunque se puede exponer de forma similar cualquier clase de cambio de estado de subproceso.

YourObject.YourMethod()
{
   CultureInfo saveCulture = Thread.CurrentThread.CurrentUICulture;
   try {
      Thread.CurrentThread.CurrentUICulture = new CultureInfo("de-DE");
      // Do something that throws an exception.
}
   finally {
      Thread.CurrentThread.CurrentUICulture = saveCulture;
   }
}
Public Class UserCode
   Public Shared Sub Main()
      Try
         Dim obj As YourObject = new YourObject
         obj.YourMethod()
      Catch e As Exception When FilterFunc
         Console.WriteLine("An error occurred: '{0}'", e)
         Console.WriteLine("Current Culture: {0}", 
Thread.CurrentThread.CurrentUICulture)
      End Try
   End Sub

   Public Function FilterFunc As Boolean
      Console.WriteLine("Current Culture: {0}", Thread.CurrentThread.CurrentUICulture)
      Return True
   End Sub

End Class

La solución adecuada para este caso es incluir el bloque try/finally existente en un bloque try/catch. El problema no se soluciona si únicamente se introduce una cláusula catch-throw en el bloque try/finally existente, como se muestra en el ejemplo siguiente.

YourObject.YourMethod()
{
    CultureInfo saveCulture = Thread.CurrentThread.CurrentUICulture;

    try 
    {
        Thread.CurrentThread.CurrentUICulture = new CultureInfo("de-DE");
        // Do something that throws an exception.
    }
    catch { throw; }
    finally 
    {
        Thread.CurrentThread.CurrentUICulture = saveCulture;
    }
}

Esto no soluciona el problema debido a que la instrucción finally no se ha ejecutado antes de que FilterFunc obtenga el control.

En el siguiente ejemplo el problema se soluciona si se garantiza que la cláusula finally se ha ejecutado antes de generar una excepción arriba de los bloques de filtro de la excepción los llamadores.

YourObject.YourMethod()
{
    CultureInfo saveCulture = Thread.CurrentThread.CurrentUICulture;
    try  
    {
        try 
        {
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("de-DE");
            // Do something that throws an exception.
        }
        finally 
        {
            Thread.CurrentThread.CurrentUICulture = saveCulture;
        }
    }
    catch { throw; }
}

Vea también

Conceptos

Instrucciones de codificación segura