7.4 KiB
Desbordamiento de enteros
Aprende hacking en AWS de cero a héroe con htARTE (Experto en Red Team de AWS de HackTricks)!
Otras formas de apoyar a HackTricks:
- Si deseas ver tu empresa anunciada en HackTricks o descargar HackTricks en PDF, consulta los PLANES DE SUSCRIPCIÓN!
- Obtén la merchandising oficial de PEASS & HackTricks
- Descubre La Familia PEASS, nuestra colección exclusiva de NFTs
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte tus trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
Información Básica
En el corazón de un desbordamiento de enteros se encuentra la limitación impuesta por el tamaño de los tipos de datos en la programación informática y la interpretación de los datos.
Por ejemplo, un entero sin signo de 8 bits puede representar valores de 0 a 255. Si intentas almacenar el valor 256 en un entero sin signo de 8 bits, se envuelve de vuelta a 0 debido a la limitación de su capacidad de almacenamiento. De manera similar, para un entero sin signo de 16 bits, que puede contener valores de 0 a 65,535, sumar 1 a 65,535 envolverá el valor de vuelta a 0.
Además, un entero con signo de 8 bits puede representar valores de -128 a 127. Esto se debe a que un bit se utiliza para representar el signo (positivo o negativo), dejando 7 bits para representar la magnitud. El número más negativo se representa como -128 (binario 10000000
), y el número más positivo es 127 (binario 01111111
).
Valores máximos
Para posibles vulnerabilidades web es muy interesante conocer los valores máximos admitidos:
{% tabs %} {% tab title="Rust" %}
fn main() {
let mut quantity = 2147483647;
let (mul_result, _) = i32::overflowing_mul(32767, quantity);
let (add_result, _) = i32::overflowing_add(1, quantity);
println!("{}", mul_result);
println!("{}", add_result);
}
{% endtab %}
{% tab title="C" %}
Desbordamiento de enteros
El desbordamiento de enteros ocurre cuando se intenta almacenar un valor en una variable que excede su capacidad máxima. Esto puede conducir a resultados inesperados y potencialmente a vulnerabilidades de seguridad si no se maneja correctamente.
Ejemplo de desbordamiento de enteros en C
#include <stdio.h>
int main() {
unsigned short a = 65535;
a = a + 1;
printf("El valor de a es: %hu\n", a);
return 0;
}
En este ejemplo, la variable a
es un unsigned short
que tiene una capacidad máxima de 65535. Al intentar sumarle 1, se produce un desbordamiento de enteros y el valor resultante será 0 en lugar de 65536.
Para evitar desbordamientos de enteros, es importante validar las entradas de datos y realizar comprobaciones adecuadas al realizar operaciones aritméticas.
#include <stdio.h>
#include <limits.h>
int main() {
int a = INT_MAX;
int b = 0;
int c = 0;
b = a * 100;
c = a + 1;
printf("%d\n", INT_MAX);
printf("%d\n", b);
printf("%d\n", c);
return 0;
}
Ejemplos
Desbordamiento puro
El resultado impreso será 0 ya que hemos desbordado el char:
#include <stdio.h>
int main() {
unsigned char max = 255; // 8-bit unsigned integer
unsigned char result = max + 1;
printf("Result: %d\n", result); // Expected to overflow
return 0;
}
Conversión de Firmado a No Firmado
Considere una situación en la que se lee un entero firmado desde la entrada del usuario y luego se utiliza en un contexto que lo trata como un entero no firmado, sin una validación adecuada:
#include <stdio.h>
int main() {
int userInput; // Signed integer
printf("Enter a number: ");
scanf("%d", &userInput);
// Treating the signed input as unsigned without validation
unsigned int processedInput = (unsigned int)userInput;
// A condition that might not work as intended if userInput is negative
if (processedInput > 1000) {
printf("Processed Input is large: %u\n", processedInput);
} else {
printf("Processed Input is within range: %u\n", processedInput);
}
return 0;
}
En este ejemplo, si un usuario ingresa un número negativo, será interpretado como un entero sin signo grande debido a la forma en que se interpretan los valores binarios, lo que potencialmente puede llevar a un comportamiento inesperado.
Otros Ejemplos
- https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html
- Solo se utiliza 1B para almacenar el tamaño de la contraseña, por lo que es posible desbordarlo y hacer que piense que su longitud es de 4 cuando en realidad es de 260 para evadir la protección de verificación de longitud.
- https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html
- Dados un par de números, descubre usando z3 un nuevo número que, multiplicado por el primero, dará el segundo:
(((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569)
- https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/
- Solo se utiliza 1B para almacenar el tamaño de la contraseña, por lo que es posible desbordarlo y hacer que piense que su longitud es de 4 cuando en realidad es de 260 para evadir la protección de verificación de longitud y sobrescribir en la pila la siguiente variable local y evadir ambas protecciones
ARM64
Esto no cambia en ARM64 como se puede ver en esta publicación de blog.
Aprende hacking en AWS desde cero hasta experto con htARTE (HackTricks AWS Red Team Expert)!
Otras formas de apoyar a HackTricks:
- Si deseas ver tu empresa anunciada en HackTricks o descargar HackTricks en PDF ¡Consulta los PLANES DE SUSCRIPCIÓN!
- Obtén la merchandising oficial de PEASS & HackTricks
- Descubre The PEASS Family, nuestra colección exclusiva de NFTs
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte tus trucos de hacking enviando PRs a los repositorios de HackTricks y HackTricks Cloud.