Как я могу защитить от атак с использованием кода на SQL с помощью DBI Perl?

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

40
задан Sinan Ünür 20 February 2010 в 12:58
поделиться

4 ответа

Правильный способ обеззараживания данных для вставки в базу данных - использовать заполнители для всех переменных, вставляемых в строки 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 docs.

66
ответ дан 27 November 2019 в 01:18
поделиться

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

Заявление об ограничении ответственности. Следующий пример является фиктивным и не предназначен для иллюстрации очень редкого случая , о котором я упоминал.

$dbh->do('INSERT INTO ' . $dbh->quote_identifier($table) . ' (id, name) VALUES '
    '(NULL, ' . $dbh->quote($name) . ')');
8
ответ дан 27 November 2019 в 01:18
поделиться

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

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

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

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

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

20
ответ дан 27 November 2019 в 01:18
поделиться

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

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

7
ответ дан 27 November 2019 в 01:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: