Как предотвратить SQL-инъекцию в интерфейсе командной строки MySQL? - PullRequest
10 голосов
/ 15 декабря 2010

Я использую сценарий оболочки для связи с базой данных 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'"

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

Ответы [ 4 ]

6 голосов
/ 18 декабря 2010

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

0 голосов
/ 31 июля 2014

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

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

#!/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=("$@")

  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 "$@"; do
  mysql_query redmine 'select * from users where login=?\G' "$u" 
done

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

0 голосов
/ 15 декабря 2010

Вы должны защищать не только от внедрения 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.

0 голосов
/ 15 декабря 2010

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

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

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

blobbo "выберите идентификатор из таблицы, где имя =% s" $ PARAM

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...