¿Cómo desinfecto y verifico los números grandes que se enviarán a una biblioteca BigNum no administrada como GMP?

1

Necesito procesar los datos que envían los usuarios en formato LargeNumber. Mis opciones actuales son

  • BigInteger (Código administrado por .Net)

  • IntX (Código administrado, más rápido para algunas operaciones)

  • GMP / MPIR ( Código no administrado, más rápido con una envoltura 1 o 2 )

Dado que tratar con grandes números tiene la capacidad de crear algunos errores de punto flotante, y el código no administrado tiene la capacidad de crear desbordamientos de búfer:

  • ¿Hay algo que pueda hacer para escanear y validar de forma proactiva grandes números que se usarán en estas bibliotecas?

  • ¿Algunas operaciones son más riesgosas que otras? (mult vs add)

  • ¿Algunas bibliotecas son mejores que otras? (¿Es el código administrado más seguro debido a la verificación de límites? ... ¿importa incluso, es solo un número?)

  • ¿Es incluso posible escanear un gran número en casos inusuales que podrían causar un desbordamiento? ¿Qué buscaría?

pregunta random65537 05.03.2013 - 07:20
fuente

2 respuestas

1

Un número es un número. Cuando se trata de números, hay tres pasos:

  1. Decodificar los valores de una representación externa (por ejemplo, un grupo de bytes que, en su protocolo, siguen una convención determinada).
  2. Aplicar operaciones matemáticas en los valores.
  3. Codifique los resultados.

Los desbordamientos de búfer debidos a datos maliciosos se producirán solo en las fases 1 y 3, y muy raramente. Durante la fase 2, no hay problema de ese tipo (si hay un desbordamiento de hay , eso es un error en la biblioteca en sí, pero no se conocen tales errores para implementaciones existentes, como regla, los desarrolladores las bibliotecas matemáticas son locas por rastrear y destruir insectos).

Como usuario de la biblioteca, debe ocuparse de las dos cosas siguientes:

  • Cuando codifique , no asuma que el valor "se ajustará a una longitud de búfer dada". Utilice la biblioteca para ver la longitud real del valor.
  • Cuando se usan muchas multiplicaciones, los enteros pueden crecer hasta tamaños ilimitados, lo que lleva a grandes asignaciones de memoria y un gran consumo de CPU. Es posible que desee incluir controles en la longitud de enteros en varios lugares de su código, para ver si está tratando con valores que son mucho más grandes de lo que deberían.

Le sugiero que comience con BigInteger (de .NET) porque eso es lo más simple y ya está ahí. Imagine cambiar a otra cosa solo si se encuentra con un problema de rendimiento real, debidamente medido y cuantificado.

(No tendrá ningún "error de punto flotante" cuando use enteros, por definición. El punto flotante es otro dominio).

    
respondido por el Thomas Pornin 05.03.2013 - 13:38
fuente
1

Como han dicho otros, la lectura / impresión es su área de mayor riesgo para los desbordamientos de búfer.

Sin embargo, es posible que puedas usar la biblioteca bignum para rociar el montón. Por ejemplo, MPIR / GMP usa una estructura bignum que se parece un poco a esto:

typedef struct
{
    off_t count;
    mpn_limb_t* limbs;
} mpz+t;

Donde off_t describe el número de miembros y su signo describe el signo del número general. Luego, cada mpn_limb_t se escribe a un tamaño apropiado para su plataforma.

Claramente, esto no se puede asignar y no se puede asignar a la pila, así que básicamente estás escribiendo todos estos números ( mpn_limb_t ) en el montón, lo que te permite heap spray que no explotará directamente la biblioteca, pero puede facilitar otro exploit.

El proceso de desinfección para esto es no confiar en una serialización binaria de su número, ya que cada bit se usa para almacenar el número en forma bruta y colocarlo en la memoria que le brinda el rango completo de códigos de operación. Realmente necesitas leer el número en un formato legible por humanos, que aunque es menos eficiente, hace que sea un poco más difícil producir shellcode útil (a menos que puedas escribir algo con los opcodes representados por el ascii de 0-9, lo cual dudo ).

La adición, la multiplicación, etc. "no pueden" desbordarse, en el sentido de que gmp / mpir al menos no asignará suficiente memoria para el objetivo mpz_t y se detendrá allí.

Debe haber (definitivamente hay una función de impresión) una función para leer números enteros de la representación de texto. Me aseguraría de que use esto y use la función de impresión correspondiente para la salida. Entonces podrá manejar los números hasta los límites impuestos por su memoria mientras no escriba sin sentido arbitrario en la memoria. Puede consultar la documentación de estas funciones para verificar su comportamiento en caracteres no enteros / decimales.

Las excepciones de punto flotante no deben ser causadas por ninguna biblioteca flotante mp, ya que el tamaño / representación interna del flotador en cuestión no puede ser manejado por el procesador de todos modos. Si observa los algoritmos (consulte algoritmos para APFPA utilizados en este tipo de código, verás que utilizan operaciones de punto flotante de precisión normal. Cualquier biblioteca decente debería asegurarse de que no causen una excepción de punto flotante cuando trabajen en "miembros".

    
respondido por el user2213 05.03.2013 - 14:12
fuente

Lea otras preguntas en las etiquetas