pentest python shell escaping

python - pentest - ¿Cómo escapar de las llamadas a os.system()?



python tty shell (10)

Creo que os.system simplemente invoca cualquier consola de comandos configurada para el usuario, por lo que no creo que pueda hacerlo de una manera independiente de la plataforma. Mi shell de comando podría ser cualquier cosa, desde bash, emacs, ruby ​​o incluso quake3. Algunos de estos programas no esperan el tipo de argumentos que les estás transmitiendo, y aunque lo hicieran, no hay garantía de que escapen de la misma manera.

Cuando se usa os.system () a menudo es necesario para escapar los nombres de archivo y otros argumentos pasados ​​como parámetros a los comandos. ¿Cómo puedo hacer esto? Preferiblemente algo que funcionaría en múltiples sistemas operativos / shells pero en particular para bash.

Actualmente estoy haciendo lo siguiente, pero estoy seguro de que debe haber una función de biblioteca para esto, o al menos una opción más elegante / robusta / eficiente:

def sh_escape(s): return s.replace("(","//(").replace(")","//)").replace(" ","// ") os.system("cat %s | grep something | sort > %s" % (sh_escape(in_filename), sh_escape(out_filename)))

Editar: he aceptado la respuesta simple de usar comillas, no sé por qué no pensé en eso; Supongo que porque vengo de Windows donde ''y'' se comportan un poco diferente.

En cuanto a la seguridad, entiendo la preocupación, pero, en este caso, estoy interesado en una solución rápida y fácil que os.system () proporciona, y la fuente de las cadenas no es generada por el usuario o al menos ingresada por un usuario de confianza (yo).


Esto es lo que uso:

def shellquote(s): return "''" + s.replace("''", "''//'''") + "''"

El intérprete de comandos siempre aceptará un nombre de archivo entrecomillado y eliminará las comillas circundantes antes de pasarlo al programa en cuestión. En particular, esto evita los problemas con los nombres de archivo que contienen espacios o cualquier otro tipo de metacaracter de shell desagradable.

Actualización : si está utilizando Python 3.3 o posterior, use shlex.quote lugar de hacer el suyo propio.


La función que uso es:

def quote_argument(argument): return ''"%s"'' % ( argument .replace(''//', ''////') .replace(''"'', ''//"'') .replace(''$'', ''//$'') .replace(''`'', ''//`'') )

es decir: siempre encierro el argumento entre comillas dobles, y luego barra invertida, cito los únicos caracteres especiales entre comillas dobles.


La verdadera respuesta es: no use os.system() en primer lugar. Use subprocess.call lugar y proporcione los argumentos no protegidos.


Quizás tenga una razón específica para usar os.system() . Pero si no, probablemente debería estar utilizando el módulo de subprocess . Puede especificar los tubos directamente y evitar el uso del shell.

Lo siguiente es de PEP324 :

Replacing shell pipe line ------------------------- output=`dmesg | grep hda` ==> p1 = Popen(["dmesg"], stdout=PIPE) p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) output = p2.communicate()[0]


Si usa el comando del sistema, trataré de incluir en la lista blanca lo que entra en la llamada a os.system () .. Por ejemplo ...

clean_user_input re.sub("[^a-zA-Z]", "", user_input) os.system("ls %s" % (clean_user_input))

El módulo de subproceso es una mejor opción, y recomendaría tratar de evitar el uso de cualquier sistema o subproceso cuando sea posible.


Tal vez subprocess.list2cmdline es una mejor oportunidad?


Tenga en cuenta que pipes.quote está realmente roto en Python 2.5 y Python 3.1 y no es seguro de usar: no maneja argumentos de longitud cero.

>>> from pipes import quote >>> args = [''arg1'', '''', ''arg3''] >>> print ''mycommand %s'' % ('' ''.join(quote(arg) for arg in args)) mycommand arg1 arg3

Ver Python, número 7476 ; se ha corregido en Python 2.6 y 3.2 y más recientes.



Aviso : esta es una respuesta para Python 2.7.x.

Según la source , pipes.quote() es una forma de " pipes.quote() forma confiable una cadena como un argumento único para / bin / sh ". (Aunque está en pipes.quote y finalmente expuesto públicamente en Python 3.3 como la función shelx.quote() ).

Por otro lado , subprocess.list2cmdline() es una forma de " Traducir una secuencia de argumentos en una cadena de línea de comando, usando las mismas reglas que el tiempo de ejecución MS C ".

Aquí estamos, la plataforma independiente de citar cadenas para líneas de comando.

import sys mswindows = (sys.platform == "win32") if mswindows: from subprocess import list2cmdline quote_args = list2cmdline else: # POSIX from pipes import quote def quote_args(seq): return '' ''.join(quote(arg) for arg in seq)

Uso:

# Quote a single argument print quote_args([''my argument'']) # Quote multiple arguments my_args = [''This'', ''is'', ''my arguments''] print quote_args(my_args)