2010-01-29 10 views
12

Mi aplicación (basada en Perl) necesita permitir a los usuarios ingresar expresiones regulares, para hacer coincidir varias cadenas detrás de las escenas. Mi plan hasta el momento ha sido tomar la cuerda y lo envuelve en algo así como¿Cómo puedo usar las expresiones regulares de forma segura desde la entrada del usuario?

$regex = eval { qr/$text/ }; 
if (my $error = [email protected]) { 
    # mangle $error to extract user-facing message 

($text haber sido despojado de saltos de línea antes de tiempo, ya que es en realidad múltiples expresiones regulares en un campo de texto de varias líneas que yo split).

¿Existe algún riesgo de seguridad potencial al hacer esto? ¿Alguna entrada extraña que podría llevar a la ejecución de código arbitrario? (Además de las vulnarabilidades de desbordamiento del búfer en los motores de expresiones regulares como CVE-2007-5116). Si es así, ¿hay formas de mitigarlos?

¿Hay una mejor manera de hacerlo? ¿Algún módulo Perl que ayude a abstraer las operaciones de convertir la entrada del usuario en expresiones regulares (como extraer mensajes de error ... o proporcionar modificadores como /i, que no necesito estrictamente aquí, pero sería bueno)? Busqué CPAN y no encontré mucho que fuera prometedor, pero considero la posibilidad de que me haya perdido algo.

+4

¿Quieres decir como '(? {Code})' tokens? –

+0

¿Has oído hablar de taintperl? – Ether

+3

@Ether: ¿Cómo ayuda la contaminación aquí? Le ayuda a evitar accidentalmente el uso de una entrada no confiable donde podría causar un problema de seguridad. Aquí, estamos buscando una forma de usar de forma segura una expresión regular no confiable. – cjm

Respuesta

5

Con la construcción (?{ code }), la entrada del usuario se puede usar para ejecutar código arbitrario. Vea el ejemplo de perlre#code y donde dice

local $cnt = $cnt + 1, 

sustituirla por la expresión

system("rm -rf /home/fennec"); print "Ha ha.\n"; 

(En realidad, no lo haga.)

+4

Afortunadamente, '(? {Code})' causa un error de tiempo de compilación si la expresión regular incluye interpolación variable a menos que diga 'use re 'eval'' (por exactamente esta razón). – cjm

+1

@cjm - Pero no es un error decir '$ re = eval {qr/$ corrompido /}' y luego usar esa expresión regular, como lo ha hecho el OP (a menos que use 'taintperl') – mob

+0

Ah, con la ayuda de su puntero encontré esto dentro de los documentos: "Antes de que Perl supiera cómo ejecutar código interpolado dentro de un patrón, esta operación era completamente segura desde un punto de vista de seguridad, aunque podría generar una excepción de un patrón ilegal". Esto es reconfortante – fennec

3

la mejor manera, es no dejar que los usuarios tengan demasiados privilegios. Proporcione una interfaz lo suficiente para que los usuarios hagan lo que quieran. (como un cajero automático con solo botones para varias opciones, sin necesidad de ingresar el teclado). Por supuesto, si necesita que el usuario ingrese la entrada, luego proporcione un cuadro de texto y luego en la parte posterior, use Perl para procesar la solicitud (por ejemplo, desinfección, etc.). El motivo detrás de dejar que los usuarios ingresen una expresión regular es buscar patrones de cadena ¿verdad? Entonces, en ese caso, la forma más simple y segura es decirles que ingresen solo la cadena. Luego, al final, usas la expresión regular de Perl para buscarla. ¿Hay alguna otra razón convincente para que los usuarios ingresen la expresión regular?

+1

Presumiblemente, si desean buscar * patrones *, la búsqueda de cadenas simples va a ser órdenes de magnitud menos poderosas que la capacidad de buscar por expresiones regulares. – geoffspear

+1

Sí. $ los clientes exigen más flexibilidad de la que puede ofrecer una simple coincidencia de cadena en este caso. En cuanto a los privilegios, sin embargo, solo los usuarios moderadamente confiables pueden hacer las expresiones regulares de todos modos. Simplemente no quiero extender estas capacidades del sistema de usuarios ("rm -rf /") y similares. – fennec

6

Uso de la introducción no es de confianza como crea una expresión regular vulnerabilidad de denegación de servicio como se describe en perlsec:

Expresiones regulares: El motor de expresiones regulares de Perl se denomina NFA (autómata finito no determinista), que entre otras cosas significa que puede consumir grandes cantidades de tiempo y espacio si la expresión regular puede coincidir de varias maneras. La elaboración cuidadosa de las expresiones regulares puede ayudar, pero a menudo realmente no hay mucho que se pueda hacer (se requiere leer el libro "Mastering Regular Expressions", consulte perlfaq2). Quedarse sin espacio se manifiesta cuando Perl se queda sin memoria.

+2

Puedo lidiar con la exposición de una vulnerabilidad de DOS. Dios sabe que hay mucho en el resto de la aplicación para las personas que pueden ingresar a estos regexpen. Sin embargo, un botón mágico de "limpiar el disco duro" es otra cuestión. :) – fennec

1

Quizás podría utilizar un motor de expresiones regulares diferente que no tenga el soporte de código de código peligroso.

No lo he probado, pero hay un PCRE para perl. También puede limitar o eliminar el soporte de código usando this info on creating custom regex engines.

1

Hay un poco de discusión sobre esto en The Monastery.

TLDR: use re::engine::RE2 -strict => 1;

Asegúrese de añadir -strict => 1 a su estado de uso o re :: :: RE2 motor caerá de nuevo a volver de Perl.

La siguiente es una cita de Paul Wankadia (Junyer), propietario de la project on GitHub:

RE2 fue diseñado e implementado con un objetivo explícito de ser capaz de manejar expresiones regulares de usuarios no confiables y sin riesgo. Una de sus principales garantías es que el tiempo de coincidencia es lineal en la longitud de la cadena de entrada. También se escribió teniendo en cuenta las preocupaciones de producción: el analizador, el compilador y los motores de ejecución limitan su uso de memoria trabajando dentro de un presupuesto configurable, fallando elegantemente cuando están agotados, y evitan el desbordamiento de pila al evitar la recursión.

Para resumir los puntos importantes:

  • Es seguro de la ejecución de código arbitrario de forma predeterminada, pero añaden "hay re 'eval';" para prevenir PERL5OPT o cualquier otra cosa? de configurarlo en ti. No estoy seguro de si hacerlo así lo previene todo.

  • Utilice un subproceso (fork) con BSD :: Resource (incluso en Linux) para ulimitar la memoria y matar al niño después de un tiempo de espera.

Cuestiones relacionadas