Как я могу защитить от атак SQL-инъекций с использованием Perl DBI? - PullRequest
40 голосов
/ 20 февраля 2010

Есть ли функция, которую я могу использовать в Perl для очистки ввода перед помещением его в базу данных MySQL? Я не очень хорошо знаю регулярные выражения, поэтому, прежде чем приступить к выполнению своих собственных функций, я подумал, а не сделал ли он уже один.

Ответы [ 5 ]

66 голосов
/ 20 февраля 2010

Правильный способ очистки данных для вставки в базу данных - это использовать заполнители для всех переменных, которые будут вставлены в строки SQL. Другими словами, НИКОГДА не делайте этого:

my $sql = "INSERT INTO foo (bar, baz) VALUES ( $bar, $baz )";

Вместо этого используйте ? заполнители:

my $sql = "INSERT INTO foo (bar, baz) VALUES ( ?, ? )";

А затем передайте переменные, которые должны быть заменены при выполнении запроса:

my $sth = $dbh->prepare( $sql );
$sth->execute( $bar, $baz );

Вы можете комбинировать эти операции с некоторыми удобными методами DBI; вышесказанное также может быть написано:

$dbh->do( $sql, undef, $bar, $baz );

См. Документацию DBI для получения дополнительной информации.

20 голосов
/ 20 февраля 2010

Незначительное (и, по общему признанию, педантичное) дополнение к ответам «использовать заполнители»: параметризованные запросы, строго говоря, не являются «дезинфицирующими». Они никак не изменяют данные, чтобы сделать их безопасными. Вместо этого они защищают от внедрения SQL, отправляя структуру запросов (команды) и данные по отдельным каналам.

Причина, по которой я считаю это различие значительным, заключается в том, что обработка санации / цитирования / экранирования ваших данных и использование параметризованных запросов как одно и то же подразумевает, что они взаимозаменяемы или, в лучшем случае, параметры являются лучшим способом процитировать опасные символы так что нет ничего страшного, если вы продолжите цитировать вместо того, чтобы пытаться выяснить это заполнитель.

По правде говоря, это совершенно разные техники с совершенно разными уровнями надежности. Цитирование может обеспечить превосходную защиту от внедрения, но всегда есть вероятность, что решительный злоумышленник может найти какой-то угловой случай, который сломает или ускользнет через ваш алгоритм цитирования и позволит им выполнить успешное внедрение SQL. Параметризованные запросы, с другой стороны, обеспечивают абсолютную защиту от внедрения SQL. Поскольку команды и данные отправляются отдельно, невозможно , чтобы ядро ​​базы данных можно было обмануть для выполнения данных в виде команды.

Если только вы не в том случае, если ваш язык или механизм базы данных не позволят вам использовать параметр в своем запросе, никогда цитирует / экранирует / дезинфицирует ввод пользователя как защиту от внедрения SQL. Всегда используйте для этой цели параметризованные запросы, если вы можете это сделать.

И обязательная ссылка: http://bobby -tables.com / содержит примеры использования параметризованных запросов на нескольких языках, включая Perl.

7 голосов
/ 20 февраля 2010

В очень редких случаях вы не можете использовать заполнители, как описано в других ответах. Но даже в таком редком случае вы не должны вмешиваться в данные самостоятельно, так как это создает место для потенциальной ошибки. Лучше использовать методы DBI quote и quote_identifier. Кроме того, это делает ваш код менее зависимым от конкретной СУБД.

Отказ от ответственности. Ниже приводится фиктивный пример, который не предназначен для иллюстрации очень редкого случая , о котором я говорил.

$dbh->do('INSERT INTO ' . $dbh->quote_identifier($table) . ' (id, name) VALUES '
    '(NULL, ' . $dbh->quote($name) . ')');
7 голосов
/ 20 февраля 2010

Как вы называете базу?

DBI поддерживает подготовленные операторы с использованием заполнителей . DBIx :: Class и Rose :: DB :: Object автоматически очищают значения, если вы используете метод "find", предоставляемый каждой библиотекой.

0 голосов
/ 16 марта 2015

Ответ: использовать заполнители SQL (?).

Зачем: структура оператора SQL и значения данных, представленные заполнителями, отправляются в базу данных совершенно отдельно. поэтому абсолютно невозможно, чтобы значения данных можно было интерпретировать как команды SQL.

...