La codificación segura es la práctica de desarrollar software de manera que se evite la introducción accidental de vulnerabilidades de seguridad . Los defectos, errores y fallos lógicos son, de forma constante, la causa principal de las vulnerabilidades de software más explotadas. [ 1 ] Mediante el análisis de miles de vulnerabilidades reportadas, los profesionales de la seguridad han descubierto que la mayoría de las vulnerabilidades provienen de un número relativamente pequeño de errores comunes de programación de software. Al identificar las prácticas de codificación inseguras que dan lugar a estos errores y capacitar a los desarrolladores sobre alternativas seguras, las organizaciones pueden tomar medidas proactivas para reducir o eliminar significativamente las vulnerabilidades en el software antes de su implementación. [ 2 ]
Algunos académicos han sugerido que, para afrontar eficazmente las amenazas relacionadas con la ciberseguridad , la seguridad adecuada debe estar codificada o integrada en los sistemas. Al diseñar la seguridad en el software, se garantiza la protección contra ataques internos y se reduce la amenaza a la seguridad de las aplicaciones. [ 3 ] La implementación de prácticas de codificación segura forma parte del enfoque de seguridad por diseño en la ingeniería de seguridad .
Prevención de desbordamiento de búfer
Los desbordamientos de búfer , una vulnerabilidad común de seguridad de software, ocurren cuando un proceso intenta almacenar datos más allá de un búfer de longitud fija. Por ejemplo, si hay 8 ranuras para almacenar elementos, se producirá un problema si se intenta almacenar 9. En la memoria de la computadora, los datos desbordados pueden sobrescribir los datos en la siguiente ubicación, lo que puede resultar en una vulnerabilidad de seguridad ( desbordamiento de pila ) o la terminación del programa (fallo de segmentación). [ 1 ]
Un ejemplo de un programa en C propenso a un desbordamiento de búfer es:
#include <string.h>#define PEQUEÑO 50void vulnerable_function ( char * large_user_input ) { char dst [ SMALL ]; strcpy ( dst , large_user_input ); }Si la entrada del usuario es mayor que el búfer de destino, se producirá un desbordamiento del búfer.
Para corregir este programa inseguro, utilice strncpy para evitar un posible desbordamiento de búfer.
#include <string.h>#define BUF_SIZE 100void secure_function ( char * user_input ) { char dst [ BUF_SIZE ]; // copia un máximo de BUF_SIZE bytes strncpy ( dst , user_input , BUF_SIZE ); // establece el último carácter del búfer a NUL. dst [ BUF_SIZE - 1 ] = '\0' ; }Otra alternativa segura es asignar memoria dinámicamente en el montón usando malloc .
#include <stdlib.h> #include <string.h>char * secure_copy ( char * src ) { size_t len = strlen ( src ); char * dst = ( char * ) malloc ( len + 1 ); if ( dst ) { strncpy ( dst , src , len ); // agregar terminador nulo dst [ len ] = '\0' ; } return dst ; }En el fragmento de código anterior, el programa intenta copiar el contenido de srcen dst, mientras que también verifica el valor de retorno de malloc()para asegurarse de que se pudo asignar suficiente memoria para el búfer de destino.
Prevención de ataques de formato de cadena
Un ataque de formato de cadena ocurre cuando un usuario malintencionado proporciona entradas específicas que eventualmente se ingresarán como argumento a una función que realiza formato, como printf() . El ataque implica que el adversario lea o escriba en la pila .
La función printf de C escribe la salida en la salida estándar (stdout). Si el parámetro de la función printf no tiene el formato adecuado, pueden introducirse varias vulnerabilidades de seguridad. A continuación, se muestra un programa vulnerable a un ataque de formato de cadena.
#include <stdio.h>void vulnerable_print ( char * malicioso_input ) { printf ( malicioso_input ); }Un argumento malicioso que se le pase al programa podría ser "%s%s%s%s%s%s%s", lo que puede provocar que el programa falle debido a lecturas de memoria incorrectas.
Prevención de desbordamiento de enteros
El desbordamiento de enteros se produce cuando una operación aritmética genera un número entero demasiado grande para ser representado en el espacio disponible. Un programa que no comprueba adecuadamente el desbordamiento de enteros introduce posibles errores y vulnerabilidades de software.
A continuación se muestra una función en C++ que intenta confirmar que la suma de x e y es menor o igual a un valor MAX definido:
#define MAX 5000bool sum_is_valid_flawed ( unsigned int x , unsigned int y ) { unsigned int sum = x + y ; return sum <= MAX ; }El problema con el código es que no comprueba si hay desbordamiento de enteros en la operación de suma. Si la suma de x e y es mayor que el valor máximo posible de una variable unsigned int, la operación de suma se desbordará y posiblemente dé como resultado un valor menor o igual a MAX, aunque la suma de x e y sea mayor que MAX.
A continuación se muestra una función que comprueba si hay desbordamiento, verificando que la suma sea mayor o igual que x e y. Si la suma se desborda, será menor que x o menor que y.
#define MAX 5000bool sum_is_valid_secure ( unsigned int x , unsigned int y ) { unsigned int sum = x + y ; return sum >= x && sum >= y && sum <= MAX ; }prevención de recorridos de ruta
El recorrido de rutas es una vulnerabilidad mediante la cual las rutas proporcionadas desde una fuente no confiable se interpretan de tal manera que es posible el acceso no autorizado a archivos.
Por ejemplo, consideremos un script que obtiene un artículo a partir de un nombre de archivo, el cual luego es leído y analizado por el script . Dicho script podría usar la siguiente URL hipotética para recuperar un artículo sobre comida para perros:
https://www.example.net/cgi-bin/article.sh?name=dogfood.htmlSi el script no realiza ninguna comprobación de entrada, confiando en que el nombre del archivo siempre es válido, un usuario malintencionado podría falsificar una URL para recuperar archivos de configuración del servidor web:
https://www.example.net/cgi-bin/article.sh?name=../../../../../etc/passwdDependiendo del script, esto puede exponer el archivo /etc/passwd , que en sistemas tipo Unix contiene (entre otros datos) identificadores de usuario , sus nombres de inicio de sesión , rutas de directorio personal y shells . (Consulte la inyección SQL para ver un ataque similar).
Véase también
Notas
- 1 2 Viega, John; Gary McGraw (2001). Building Secure Software: How to Avoid Security Problems the Right Way . MAddison-Wesley Professional. p. 528. ISBN 978-0201721522.
- ↑ Taylor, Blair; Azadegan, Shiva (22 de septiembre de 2006). «Integración de principios de codificación segura y análisis de riesgos en el currículo de informática y sistemas de información para estudiantes de pregrado» . Actas de la 3.ª conferencia anual sobre desarrollo de currículos de seguridad de la información . InfoSecCD '06. Kennesaw, Georgia: Association for Computing Machinery. págs. 24-29 . doi : 10.1145/1231047.1231053 . ISBN 978-1-59593-437-6. S2CID 2452783 .
- ↑ Russell L, Jones (dic. 2004). "Codificación segura: Incorporando la seguridad en el ciclo de vida del desarrollo de software" . Seguridad de los sistemas de información . ProQuest 229507883 .
Referencias
- Taylor, Art; Brian Buege; Randy Layman (2006). Hacking Exposed J2EE & Java . McGraw-Hill Primis. pág. 426. ISBN 0-390-59975-1.
- Seguridad informática