¿Puede la cadena .format () de Python ser segura para cadenas de formato que no son de confianza?

Estoy trabajando en una aplicación web donde los usuarios podrán suministrar cadenas en las que el servidor sustituirá las variables.

Preferiblemente, me gustaría usar la syntax del formato PEP 3101 () y estoy analizando la posibilidad de reemplazar los métodos en Formatter para que sea seguro para una entrada no confiable.

Estos son los riesgos que puedo ver con .format () tal como está:

  • El relleno le permite especificar longitudes arbitrarias, por lo que ‘{:> 9999999999}’. Formato (..) podría ejecutar el servidor sin memoria y ser un DOS. Necesito deshabilitar esto.
  • El formato le permite acceder a los campos dentro de los objetos, lo cual es útil, pero es espeluznante que pueda acceder a las variables dunder y comenzar a perforar bits de la biblioteca estándar. No se sabe dónde puede haber un getattr () que tenga efectos secundarios o que devuelva algo secreto. Yo pondría en la lista blanca de atributos / acceso al índice reemplazando a get_field ().
  • Tendría que atrapar algunas excepciones, naturalmente.

Mis suposiciones son:

  • Ninguna de las explotaciones de cadena de formato C tradicionales se aplica a Python, ya que especificar un parámetro es un acceso controlado por límites en una colección, en lugar de saltar directamente de la stack del hilo.
  • El marco web que estoy usando escapa a todas las variables que se sustituyen en una plantilla de página, y siempre que sea la última parada antes de la salida, estoy a salvo de los ataques de secuencias de comandos entre sitios que surjan de la eliminación de escapes.

¿Cuáles son tus pensamientos? ¿Posible? ¿Imposible? ¿Simplemente imprudente?


Edit: Armin Ronacher describe una fuga de información desagradable si no filtra el acceso variable de dunder, pero parece considerar el formato de seguridad () como posible:

{local_foo.__init__.__globals__[secret_global]}

http://lucumr.pocoo.org/2016/12/29/careful-with-str-format/

(Personalmente, no fui a la ruta de formato no confiable () en mi producto, pero estoy actualizando para completar)

Buen instinto Sí, un atacante que puede proporcionar una cadena de formato arbitrario es una vulnerabilidad en python.

  • La denegación de servicio es probablemente la más sencilla de abordar. En este caso, limitar el tamaño de la cadena o el número de operadores dentro de la cadena mitigará este problema. Debe haber una configuración en la que ningún usuario razonable deba generar una cadena con más variables que X, y esta cantidad de cómputo no corre el riesgo de ser explotada en un ataque DoS.
  • Ser capaz de acceder a los atributos dentro de un objeto podría ser peligroso. Sin embargo, no creo que la clase padre Object tenga información útil. El objeto suministrado al formato debería contener algo sensible. En cualquier caso, este tipo de notación puede limitarse con una expresión regular .
  • Si las cadenas de formato son proporcionadas por el usuario, es posible que un usuario deba conocer el mensaje de error para la depuración. Sin embargo, los mensajes de error pueden contener información sensitiva, como rutas locales o nombres de clase. Asegúrate de limitar la información que un atacante puede obtener.

Revise la especificación de cadena del formato python y prohíba la funcionalidad que no desea que el usuario tenga con una expresión regular.