Evitar saturaciones de búfer

Una saturación del búfer es uno de los orígenes más comunes de riesgo de seguridad. Básicamente, un desbordamiento de búfer se produce al tratar una entrada externa no validada como si fueran datos fiables. El acto de copiar estos datos, mediante operaciones como CopyMemory, strcat, strcpy o wcscpy, puede crear resultados imprevistos, lo que permite daños en el sistema. En el mejor de los casos, la aplicación se abortará con un volcado de memoria, un error de segmentación o una infracción de acceso. En el peor de los casos, un atacante puede aprovechar la saturación del búfer introduciendo y ejecutando otro código malintencionado en el proceso. Copiar datos de entrada sin comprobar en un búfer basado en pila es la causa más común de errores explotables.

Warning

Nunca use funciones de cadena no acotadas (strcpy, strcat, sprintf, gets) en código sensible a la seguridad. Sustitúyalos por sus equivalentes acotados (StringCbCopy, StringCbCat, StringCbPrintf) de la biblioteca de cadenas seguras o utilice las variantes con el sufijo C11 _s (strcpy_s, strcat_s).

Los desbordamientos de búfer pueden producirse de varias maneras. En la lista siguiente se proporciona una breve introducción a algunos tipos de situaciones de saturación de búfer y se ofrecen algunas ideas y recursos que le ayudarán a evitar la creación de nuevos riesgos y mitigar los existentes:

Desbordamientos de búfer estático

Se produce un desbordamiento de búfer estático cuando un búfer, que se ha declarado en la pila, se escribe con más datos de los que puede contener. Las versiones menos aparentes de este error se producen cuando los datos de entrada de usuario no comprobados se copian directamente en una variable estática, lo que provoca posibles daños en la pila.

Desbordamientos de montón

Los desbordamientos de montón, al igual que los desbordamientos de búfer estático, pueden provocar daños en la memoria y la pila. Dado que los desbordamientos de montón ocurren en la memoria del montón en lugar de en la pila, algunas personas los consideran menos capaces de causar problemas graves; sin embargo, los desbordamientos de montón requieren una atención cuidadosa en la programación y son igualmente capaces de permitir riesgos en el sistema como los desbordamientos de búfer estático.

Errores de indexación de matriz

Los errores de indexación de matriz también son un origen de saturaciones de memoria. La comprobación cuidadosa de límites y la administración de índices ayudarán a evitar la saturación de este tipo de memoria.

La prevención de saturaciones de búfer consiste principalmente en escribir código correcto. Valide siempre todos los datos de entrada y maneje los errores de manera adecuada cuando sea necesario. Para obtener más información sobre cómo escribir código seguro, consulte los siguientes recursos:

  • Maguire, Steve [1993], Escribir código sólido, ISBN 1-55615-551-4, Microsoft Press, Redmond, Washington.
  • Howard, Michael y LeBlanc, David [2003], Escribir código seguro, 2d ed., ISBN 0-7356-1722-8, Microsoft Press, Redmond, Washington.

Note

Es posible que estos recursos no estén disponibles en algunos idiomas y países.

 

El control seguro de cadenas es un problema de larga duración que sigue siendo solucionado mediante procedimientos de programación recomendados y, a menudo, mediante el uso y la retroajustación de sistemas existentes con funciones seguras y de control de cadenas. Un ejemplo de este conjunto de funciones para el shell de Windows comienza con StringCbCat.

Mitigaciones del compilador y del vinculador

Las versiones modernas del compilador y vinculador de C/C++ de Microsoft proporcionan varias capas de defensa contra saturaciones de búfer. Habilite siempre estas protecciones en las versiones de producción:

Flag propósito
/GS Detección de desbordamiento del búfer de pila (activada por defecto). Inserta cookies de seguridad antes de las direcciones de retorno.
/sdl Habilita comprobaciones de seguridad adicionales, incluido el comportamiento más /GS estricto y la inicialización de variables.
/DYNAMICBASE Aleatorización de la disposición del espacio de direcciones (ASLR). Aleatoriza las direcciones de carga para que la explotación sea más difícil.
/NXCOMPAT Prevención de ejecución de datos (DEP). Marca páginas de memoria como no ejecutables.
/CETCOMPAT Tecnología de aplicación del flujo de control de Intel (CET) para pilas sombra aplicadas por hardware.
/guard:cf Protección de flujo de control (CFG). Valida los destinos de llamadas indirectas en tiempo de ejecución.

Importante

Compile con /sdl y /GS como mínimo para todo el código nuevo. En el caso de las aplicaciones críticas para la seguridad, habilite y vincule /guard:cf con /CETCOMPAT cuando tenga como destino hardware que admita CET.

Herramientas de análisis en tiempo de ejecución

Use estas herramientas durante el desarrollo y las pruebas para detectar problemas de seguridad de memoria antes de llegar a producción:

  • AddressSanitizer (ASan): Compila con /fsanitize=address para detectar desbordamientos de búfer, uso después de la liberación y otros errores de memoria en tiempo de ejecución. Disponible en Visual Studio 2019 16.9 y versiones posteriores.
  • Application Verifier: Detecta la corrupción del montón, el uso indebido de identificadores y otros errores comunes de programación.
  • Análisis estático (/analyze): el analizador estático integrado detecta saturaciones de búfer, variables sin inicializar y otros problemas en tiempo de compilación.