Подтвердить что ты не робот

Как предотвратить SQL-инъекцию в интерфейсе командной строки командной строки MySQL?

Я использую shell script для связи с базой данных MySQL. MySQL поддерживает указание запроса как аргумент оболочки, например:

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

Однако, если у меня есть параметр, который я хотел бы использовать в запросе, как я могу получить защиту от инъекций?

Наивный способ - просто вставить значение переменной в запрос, но это не очень безопасно:

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

Есть ли какие-либо трюки или документированные интерфейсы для создания безопасных запросов в командной строке?

4b9b3361

Ответ 1

Вы можете кодировать значение base64, а затем base64 декодировать его в MySQL. В MySQL используются UDF для преобразования данных Base64 в общие данные. Кроме того, большинство систем либо имеют uuencode, либо команду base64 для данных кодировки base64.

Ответ 2

Ваше приложение восприимчиво к атаке SQL Injection при каждом построении SQL путем конкатенации параметров (как в вашем примере). В wikipedia есть запись об этом по ссылке: http://en.wikipedia.org/wiki/SQL_injection

Я подозреваю, что вам захочется написать unix-фильтр для создания вашего SQL-запроса с помощью функции mysql_real_escape_string, упомянутой в статье.

Рассмотрите возможность передачи SQL как первого параметра и переменной (ов) в качестве последующих параметров, а затем возврата построенного SQL. Если вы назовете ваш фильтр "blobbo", команда, подобная вашему примеру, может выглядеть так:

blobbo "выберите id из таблицы, где name=% s" $PARAM

Ответ 3

Вам не только нужно защищать от SQL-инъекции, но и от инъекции оболочки. Возможно, вы захотите написать запрос (после дезинфекции любых динамических частей) в файл, а затем перенаправить этот файл в mysql, вместо того чтобы надеяться, что запрос не сломает оболочку. Рассмотрим:

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

становится

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

или

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

Вместо этого сделайте что-нибудь вроде:

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

Это предотвратит появление каких-либо данных, заданных пользователем, в самой команде оболочки, предотвратит хотя бы один уровень уязвимости в отношении инъекций. Но тогда вам все равно придется обрабатывать проблему с SQL-инъекцией.

Ответ 4

Ответ Саргун Дхиллон указал мне в правильном направлении. К сожалению, FROM_BASE64 недоступен до MySQL 5.6, поэтому я пошел с UNHEX.

Ниже приведено script ниже, чтобы запросить детали пользователя Redmine из оболочки. Я все еще не спал бы хорошо, если бы недоверенные пользователи имели доступ к этому script, но в моем случае это достаточно безопасно. (Он также ограничен строковыми значениями, и вы не должны иметь вопросительный знак в своем запросе, но эти ограничения в порядке со мной.)

#!/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

Если вы обнаружите какие-либо инъекции SQL или Shell, которые я пропустил, прокомментируйте.