Pregunta

¿Es posible usar un RegEx para validar o desinfectar datos de Base64? Esa es la pregunta simple, pero los factores que impulsan esta pregunta son los que la hacen difícil.

Tengo un decodificador Base64 que no puede confiar completamente en los datos de entrada para seguir las especificaciones RFC. Entonces, los problemas que enfrento son problemas como los datos de Base64 que tal vez no se dividan en 78 (creo que es 78, tendría que verificar el RFC, así que no me ding si el número exacto es incorrecto) líneas, o que las líneas pueden no terminar en CRLF; ya que puede tener solo un CR o LF, o tal vez ninguno.

Entonces, me he pasado un mal rato analizando datos de Base64 formateados como tales. Debido a esto, ejemplos como los siguientes se vuelven imposibles de decodificar de manera confiable. Solo mostraré encabezados MIME parciales por brevedad.

Content-Transfer-Encoding: base64

VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu

Ok, entonces el análisis no es un problema, y ??es exactamente el resultado que esperaríamos. Y en el 99% de los casos, usar cualquier código para al menos verificar que cada carácter en el búfer sea un carácter base64 válido, funciona perfectamente. Pero, el siguiente ejemplo arroja una llave en la mezcla.

Content-Transfer-Encoding: base64

http://www.stackoverflow.com
VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu

Esta es una versión de la codificación Base64 que he visto en algunos virus y otras cosas que intentan aprovechar el deseo de algunos lectores de correo de analizar mime a toda costa, en comparación con los que siguen estrictamente el libro, o más bien RFC; Si tu quieres.

Mi decodificador Base64 decodifica el segundo ejemplo para el siguiente flujo de datos. Y tenga en cuenta aquí, ¡la secuencia original es toda la información ASCII!

[0x]86DB69FFFC30C2CB5A724A2F7AB7E5A307289951A1A5CC81A5CC81CDA5B5C1B19481054D0D
2524810985CD94D8D08199BDC8814DD1858DAD3DD995C999B1BDDC8195E1B585C1B194B8

¿Alguien tiene una buena manera de resolver ambos problemas a la vez? No estoy seguro de que sea posible, además de hacer dos transformaciones en los datos con diferentes reglas aplicadas y comparar los resultados. Sin embargo, si tomó ese enfoque, ¿en qué resultado confía? Parece que la heurística ASCII se trata de la mejor solución, pero ¿cuánto más código, tiempo de ejecución y complejidad agregaría a algo tan complicado como un escáner de virus, en el que este código está realmente involucrado? ¿Cómo entrenaría al motor de heurística para saber qué es aceptable Base64 y qué no lo es?


ACTUALIZACIÓN :

Teniendo en cuenta la cantidad de puntos de vista que esta pregunta continúa recibiendo, he decidido publicar el sencillo RegEx que he estado usando en una aplicación C # durante 3 años, con cientos de miles de transacciones. Honestamente, me gusta la respuesta dada por Gumbo la mejor, por eso la elegí como la respuesta seleccionada Pero para cualquiera que use C # y busque una forma muy rápida de al menos detectar si una cadena o un byte [] contiene datos válidos de Base64 o no, he encontrado que lo siguiente funciona muy bien para mí.

[^-A-Za-z0-9+/=]|=[^=]|={3,}$

Y sí, esto es solo para un STRING de datos Base64, NO para un mensaje RFC1341 . Por lo tanto, si se trata de datos de este tipo, tenga esto en cuenta antes de intentar utilizar el RegEx anterior. Si se trata de Base16, Base32, Radix o incluso Base64 para otros fines (URL, nombres de archivo, codificación XML, etc.), entonces es altamente recomendable que lea RFC4648 que Gumbo mencionado en su respuesta, ya que debe ser consciente del conjunto de caracteres y terminadores utilizados por la implementación antes de intentar utilizar las sugerencias en este conjunto de preguntas / respuestas.

¿Fue útil?

Solución

Del RFC 4648 :

  

La codificación de datos base se usa en muchas situaciones para almacenar o transferir datos en entornos que, quizás por razones heredadas, están restringidos a datos ASCII de EE. UU.

Por lo tanto, depende del propósito del uso de los datos codificados si los datos deben considerarse peligrosos.

Pero si solo está buscando una expresión regular para que coincida con las palabras codificadas en Base64, puede usar lo siguiente:

^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$

Otros consejos

^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$

Este es bueno, pero coincidirá con una cadena vacía

Este no coincide con una cadena vacía:

^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$

Ni una " : " ni un " . " aparecerá en Base64 válido, por lo que creo que puede descartar sin ambigüedad la línea http://www.stackoverflow.com . En Perl, digamos, algo así como

my $sanitized_str = join q{}, grep {!/[^A-Za-z0-9+\/=]/} split /\n/, $str;

say decode_base64($sanitized_str);

podría ser lo que quieres. Produce

Esto es ASCII Base64 simple para el ejemplo StackOverflow.

La mejor expresión regular que pude encontrar hasta ahora está aquí https://www.npmjs.com/package/base64-regex

que está en la versión actual se ve así:

module.exports = function (opts) {
  opts = opts || {};
  var regex = '(?:[A-Za-z0-9+\/]{4}\\n?)*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)';

  return opts.exact ? new RegExp('(?:^' + regex + '$)') :
                    new RegExp('(?:^|\\s)' + regex, 'g');
};
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top