2010-12-15 5 views
10

Uso el script de shell para comunicarme con una base de datos MySQL. MySQL soporta la especificación de consulta como un argumento de la cáscara, así:¿Cómo prevenir la inyección de SQL en la interfaz shell de línea de comandos de MySQL?

mysql my_db -B -N -e "select id from Table" 

Sin embargo, si tengo un parámetro, que me gustaría utilizar en una consulta, ¿cómo puedo obtener la protección contra ataques de inyección?

Una forma ingenua es simplemente pegar valor de la variable a la solicitud, pero no es muy seguro:

mysql my_db -B -N -e "select id from Table where name='$PARAM'" 

¿Hay algún truco o interfaces documentados para hacer una consulta de inyección segura desde la línea de comandos?

+0

¿Está una aplicación web pasando estos 'params' al script de shell? Sugiero que busquen limpiar los datos en la aplicación web. – Jakub

Respuesta

0

Su aplicación es susceptible a un ataque de inyección SQL en cualquier momento que es la construcción de SQL mediante la concatenación de parámetros (como en el ejemplo). Hay un escrito sobre esto en wikipedia en este enlace: http://en.wikipedia.org/wiki/SQL_injection

Sospecho que querrá escribir un filtro Unix para construir su consulta SQL usando la función mysql_real_escape_string mencionada en el artículo.

considerar la aprobación de la SQL como el primer parámetro y la variable (s) como los parámetros posteriores a continuación, tiene que devolver el SQL construido. Si el nombre de su filtro "blobbo" el comando como por su ejemplo podría tener este aspecto:

blobbo "SELECT ID de la tabla donde name =% s" $ PARAM

0

Usted no sólo tiene que proteger contra la inyección de SQL , pero también contra la inyección de la cáscara. Es posible que desee escribir la consulta (después de desinfectar cualquier parte dinámica) en un archivo y luego redirigir ese archivo a mysql, en lugar de esperar que la consulta no rompa el shell. Consideremos:

PARAM="name'\"; rm -rf/; echo 'pwn3d U" 

convertirse

mysql my_db -B -N -e "select id from Table where name='name'"; rm -rf/; echo 'pwn3d U' 

o:

command 1: mysql my_db -B -N -e "select id from Table where name='name'" 
command 2: rm -rf/
command 3: echo 'pwn3d U' 

En su lugar, hacer algo como:

cat <<EOT > query.sql 
select .... blah blaah blah .... sanitized query here 
EOT 
mysql my_db -B -N < query.sql 

Esto evitaría que los datos especificados por el usuario de cada vez que aparece dentro del comando de shell auto, prevenir al menos un nivel de vulnerabilidad a la inyección. Pero entonces, todavía tiene que manejar el problema de inyección de SQL.

+0

Gracias por mencionar este tipo de problema. Sin embargo, el código publicado en la pregunta * está * protegido de la inyección de shell, si es ejecutado por el propio shell. Solo si invoco el comando desde otro script (que no), como este: 'system (" mysql -e '$ PARAM' ");' tiene este tipo de vulnerabilidad. –

5

Usted puede codificar el valor base 64, y luego decodificar Base64 una vez que es en MySQL. Hay UDF en MySQL para convertir datos de Base64 a datos comunes. Además, la mayoría de los sistemas tienen uuencode o el comando 'base64' para datos de codificación base64.

+0

Gran respuesta, el ejemplo también ayudaría: 'ENCODED = $ (echo $ 1 | base64); echo "SELECT * FROM T WHERE V = FROM_BASE64 ('$ ENCODED');" | mysql' – brablc

0

La respuesta por Sargun Dhillon me señaló a la dirección correcta. Lamentablemente, FROM_BASE64 no está disponible antes de MySQL 5.6, así que fui con UNHEX.

El script de abajo es un ejemplo para consultar los detalles de un usuario Redmine de una concha. Todavía no dormiría bien si los usuarios no confiables tuvieran acceso a este script, pero es lo suficientemente seguro en mi caso. (También está limitado a valores de cadena y no debe tener un signo de interrogación en su consulta, pero esas limitaciones están bien para mí).)

#!/bin/bash 

MYSQL_OPTS='--defaults-file=/etc/redmine/mysql.cnf' 

mysql_query() { 
    local db=$1 
    local sql=$2 
    shift 2 || return 1 
    declare -a args=("[email protected]") 

    sql=${sql//[%]/%%} 
    sql=${sql//[?]/UNHEX('%s')} 
    for ((i=0; i<${#args[@]}; i++)); do 
    args[$i]=$(echo -n "${args[$i]}" | hexdump -v -e '/1 "%02X"') 
    done 
    sql=$(printf "$sql" "${args[@]}") 
    mysql $MYSQL_OPTS "$db" -e "$sql" || return $? 
} 

for u in "[email protected]"; do 
    mysql_query redmine 'select * from users where login=?\G' "$u" 
done 

Si descubres cualquier inyección de SQL o Shell que omití, por favor comenta.

Cuestiones relacionadas