Существует ли функция, которую я могу использовать в Perl для очистки входа прежде, чем поместить его в дб MySQL? Я не знаю regex очень хорошо поэтому, прежде чем я сделаю свою собственную функцию, я задавался вопросом, был ли уже один сделанный.
Правильный способ обеззараживания данных для вставки в базу данных - использовать заполнители для всех переменных, вставляемых в строки 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.
В очень редких случаях вы не можете использовать заполнители, как описано в других ответах. Но даже в таком редком случае вам не следует вмешиваться в данные самостоятельно, поскольку это создает место для потенциальной ошибки. Лучше использовать методы DBI quote
и quote_identifier
. Также это делает ваш код менее зависимым от конкретной СУБД.
Заявление об ограничении ответственности. Следующий пример является фиктивным и не предназначен для иллюстрации очень редкого случая , о котором я упоминал.
$dbh->do('INSERT INTO ' . $dbh->quote_identifier($table) . ' (id, name) VALUES '
'(NULL, ' . $dbh->quote($name) . ')');
Небольшое (и, по общему признанию, педантичное) дополнение к ответам на вопрос "использовать заполнители": Параметризованные запросы, строго говоря, не являются "санирующими". Они никак не изменяют данные, чтобы сделать их безопасными. Вместо этого они защищают от SQL-инъекций, посылая структуру запроса (команды) и данные по отдельным каналам.
Причина, по которой я считаю это различие существенным, заключается в том, что если рассматривать санирование/цитирование/вывод данных и использование параметризованных запросов как одно и то же, то это означает, что они взаимозаменяемы или, в лучшем случае, что параметры - это просто лучший способ цитирования опасных символов, поэтому нет ничего страшного, если вы будете использовать цитирование, а не утруждать себя выяснением того, что такое заполнитель.
На самом деле, это совершенно разные техники с совершенно разными уровнями надежности. Цитирование может обеспечить отличную защиту от инъекций, но всегда есть шанс, что решительный злоумышленник найдет какой-то угловой случай, который сломает или проскользнет через ваш алгоритм цитирования и позволит ему выполнить успешную SQL-инъекцию. Параметризованные запросы, с другой стороны, обеспечивают абсолютную защиту от SQL-инъекций. Поскольку команды и данные посылаются отдельно, нет никакой возможности обмануть механизм базы данных и заставить его выполнить данные как команду.
Если только вы не столкнулись с ситуацией, когда ваш язык или механизм базы данных не позволяет использовать параметр в запросе, никогда не цитируйте/эскейпируйте/санируйте пользовательский ввод в качестве защиты от SQL-инъекций. Всегда используйте параметризованные запросы для этой цели, если у вас есть такая возможность.
И обязательная ссылка: http://bobby-tables.com/ содержит примеры использования параметризованных запросов в нескольких различных языках, включая Perl.
Как вы вызываете базу данных?
DBI имеет поддержку подготовленных операторов с использованием placeholders. И DBIx::Class, и Rose::DB::Object автоматически санируют значения, если вы используете метод "find", предоставляемый каждой библиотекой.