¿Es la conversión indeseable de un número científico una vulnerabilidad?

29

En varias pruebas de penetración, noté que PHP está convirtiendo valores como 1e9 a 1000000000 , mientras que la longitud máxima de cadena aceptada de este número es 3 (en el almacenamiento de la base de datos y como propiedad maxlength en los formularios HTML).

Sin embargo, al ingresar 1e9 (3), PHP devolverá 1000000000 (10) como su salida. Ese es un número más alto de lo que la aplicación espera y puede manejar adecuadamente. Por lo tanto, consideraría una mejor validación de la entrada del usuario para evitar esto.

En primer lugar, asumo que este comportamiento no es peligroso sino simplemente indeseable, ¿es legítimo asumir esto? En segundo lugar, ¿puedo considerar esto como una vulnerabilidad real (gravedad baja)?

También la entrada 9e9 dará como resultado el valor máximo de 32 bits 2147483647 (10) en lugar de 9000000000 (10). ¿Es esto solo (sistema o configuración de 32 bits) considerado como una fuga de información del sistema o peligroso de alguna manera?

    
pregunta Bob Ortiz 20.06.2016 - 11:56
fuente

2 respuestas

18

Estrictamente hablando? No, por sí solo no es una vulnerabilidad. Pero sí sugiere que hay un problema potencial que necesita más investigación.

Este es uno de los problemas inherentes con las pruebas de lápiz. Encuentras algo ambiguo como este, y no sabes si es explotable. Incluso para comenzar a descubrir si esto es una vulnerabilidad, debe comprender lo que hace la limitación de entrada.

Por ejemplo, si el programa fue diseñado para limitar las transferencias bancarias a menos de $ 1000 y el campo de entrada era la cantidad, y no hay más cheques en ningún lado, acaba de encontrar una gran vulnerabilidad.

Por otra parte, si el campo es solo los primeros 3 dígitos de un número de teléfono que crea una base de datos de números de teléfono para que los padres ingresen los números de contacto de una escuela, y la validación es simplemente para asegurarse de que el usuario solo ingrese el primeros 3 dígitos, es probable que no haya encontrado nada más que un caso de esquina donde un padre muy nerd puede arruinar su propia entrada de número de teléfono en la base de datos.

    
respondido por el Steve Sether 20.06.2016 - 16:16
fuente
26

¿Por qué sucede esto?

Se debe a que PHP tiene escritura suelta . Echa un vistazo a este ejemplo:

$x = "1e6";
echo strlen($x); // 3
echo $x * 1;     // 1 000 000

En la segunda línea, se supone que $x es una cadena, y como tal obviamente tiene una longitud de tres caracteres. En la tercera línea, $x se interpreta como un número entero, o 1 000 000 en este caso.

¿Es un problema?

Esto definitivamente puede causar errores, y cada error es una vulnerabilidad de seguridad potencial. Pero por sí solo, no hace que su aplicación sea vulnerable de forma predeterminada. Pero intentemos imaginar un escenario en el que podría causar un problema.

Digamos que un foro tiene grupos numerados a los que los usuarios pueden unirse libremente, pero los primeros 10 grupos (de 0 a 9) están reservados para los administradores. El código para joingroup.php tiene este aspecto:

$group = $_POST['group'];
if(strlen($group) > 1 || $isadmin) {
    join_group($group, $uid);
}
else {
    // Fail.
}

Puedes ingresar a un grupo de administradores sin ser un administrador al publicar, por ejemplo. 0.3e1 , que tiene una longitud de cadena 5 pero se evalúa como 3. Lo sé, es un ejemplo tonto. El punto que quiero señalar es que si confía en strlen() (o cualquier otra cosa que trate la entrada como una cadena) para validar los datos numéricos, podría ser vulnerable.

La publicación de 3.0 o  3 también pasará por alto esta comprobación. Para obtener más información sobre cómo PHP convierte implícitamente cadenas en números, consulte el manual .

¿Cómo debo lidiar con esto en PHP?

Valide la entrada del usuario. Compruebe que realmente obtiene un número entero cuando espera obtener un número entero:

if(!ctype_digit($group)) {
    // Fail.
}

También es una buena idea tratar siempre algo que debe ser un entero como un entero y no como una cadena:

$group = (int) $_POST['group']
if($group > 9 || $isadmin) {
    // ...

¿Se está filtrando información del sistema?

Al parecer, esto puede revelar el valor entero máximo. Quizás alguien podría deducir que estás usando PHP a partir de esto, pero probablemente ya hay muchas otras formas de hacerlo. El valor máximo depende de la plataforma, por lo que podría utilizarse para la toma de huellas dactilares. Pero en la práctica, probablemente se usan 32 bits en un sistema de 32 bits y 64 bits en un sistema de 64 bits. Esa es la única información que está filtrando.

    
respondido por el Anders 20.06.2016 - 13:26
fuente

Lea otras preguntas en las etiquetas