специальные символы в Perl

Я создаю форму CGI для обновления хранимой процедуры Sybase.

qq {execute procedure test(123,45,date,'$note');}; переменная $note представляет собой информацию, полученную из текстового поля, которое содержит информацию журнала регистрации неисправностей. Поскольку такие люди, которые вводят такую ​​информацию, могут и, скорее всего, будут использовать специальные символы, такие как '|"{} и т. д. Мне любопытно узнать, есть ли способ получить эту информацию в базе данных через переменную $note.

В большинстве моих исследований использовались функции DBI->quote(), но они, похоже, не работают, и я не уверен, насколько они актуальны, поскольку это хранимая процедура.

Прямо сейчас я пытаюсь сделать следующее:

use DBI;
$livedb = DBI->connect("dbi:Sybase:server=test","admin","pass") || die "could not connect to live DB, $DBI::errstr";
$note = "testing special characters:";
$livedb->do(qq {execute procedure jinsert(5304905,65,getdate,?);},undef,(param('$note')));

Я получаю следующую ошибку:

Undefined subroutine &main::param called at test.cgi line 11.

когда я использую следующие методы, код дает сбой, если ' существует в $note:

$qy = $livedb->prepare($note);
$qy->execute($test) || die "could not journal: $DBI::errstr";
$qy->finish();


person Mose    schedule 30.06.2010    source источник
comment
Можете ли вы включить код, который вы используете для общения с дескриптором базы данных (т.е. вызов DBI).   -  person Ether    schedule 01.07.2010
comment
Сейчас я пытаюсь сделать следующее:‹code›$livedb = DBI-›connect(dbi:Sybase:server=test,admin,pass) || die не удалось подключиться к активной БД, $DBI::errstr; $note = проверка специальных символов:; $livedb-›do(qq {выполнить процедуру jinsert(5304905,65,getdate,?);},undef,(param('$note')));‹/code› я получаю следующую ошибку: ‹code›Undefined подпрограмма &main::param вызывается в строке 11 test.cgi.‹/code›   -  person Mose    schedule 01.07.2010
comment
param — это метод из пакета CGI. Вы должны «использовать» его и создать экземпляр.   -  person Toto    schedule 01.07.2010
comment
возможный дубликат Как защититься от внедрения SQL атаки с использованием Perl DBI?   -  person Ether    schedule 02.07.2010
comment
@mose: пожалуйста, отредактируйте этот код в своем вопросе, чтобы вы могли использовать правильное форматирование и т. д.   -  person Ether    schedule 02.07.2010
comment
Я скоро обновлю, работать удаленно и копировать / вставлять через RDP не очень приятно.   -  person Mose    schedule 02.07.2010


Ответы (2)


Во-первых, чтобы ответить на ваш вопрос напрямую: DBI->quote() действительно ваш друг здесь :-) Он заключает кавычки вокруг строки в правильном порядке для языка используемой вами базы данных (что неизменно для SELECT /UPDATE/INSERT/DELETE запросы как для хранимых процедур, так как последние обычно состоят из комбинаций первых!).

Например, предположим, что $dbh было настроено как соединение DBI с вашей базой данных, тогда

my $string = "Here's a string that needs \"quoting\"!";

print $dbh->quote($string);

печатает что-то вроде:

'Here''s a string that needs "quoting"!'

Обратите внимание, как:

  • Это удвоило ' в Here's
  • Он заключает всю строку в '' кавычек.

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

Однако...

Глядя на то, что вы делаете, вам не нужно цитировать: пусть DBI сделает всю работу за вас, например:

$livedb->do(qq {execute procedure jinsert(5304905,65,getdate,?);}, undef, $note);

Код DBI знает, что делать, чтобы заменить ? на $note.

person psmears    schedule 30.06.2010
comment
DBI-›quote не является предпочтительным подходом. Вместо классической уязвимости SQL-инъекций в исходном примере кода лучше использовать заполнители ('?') и передавать значения в качестве дополнительных аргументов $sth-›execute(). - person Grant McLean; 01.07.2010
comment
@Grant McLean: DBI-›quote и? заполнители эквивалентны, и оба решают проблему SQL-инъекций — действительно, один реализован с точки зрения другого! Согласен, ? во многих случаях заполнители более аккуратны, но иногда (например, при программном построении сложного запроса) имеет смысл заранее указать явное цитирование, а не отслеживать последовательность ? параметры на протяжении всего построения запроса. Из вопроса неясно, является ли генерируемая строка частью более крупной последовательности для выполнения, поэтому явное цитирование не является совершенно необоснованным... - person psmears; 01.07.2010
comment
Я рассматриваю не только одинарные кавычки, поле ‹code›$note‹/code› служит той же цели, что и поле «Добавить комментарий» на этом форуме. Я просто ищу способ передать все символы в ‹code›$note‹/code› в ‹code›qq {выполнить тест процедуры (123,45,date, '$note');};‹/code› и вставить их в БД. - person Mose; 01.07.2010
comment
@mose: Да, DBI-›quote() сделает это за вас, как и ? метод, упомянутый Грантом. Если у меня будет время позже, я обновлю свой ответ, чтобы описать оба метода и причины их использования. - person psmears; 01.07.2010
comment
мне нужно сбежать не столько от одного персонажа. Моя форма очень похожа на форму «Добавить комментарий», где люди могут вводить что угодно (включая специальные символы), и это отправляет в базу данных. Мне нужно иметь возможность привязать переменную к заметкам в текстовом поле и вставить ее в SQL. - person Mose; 01.07.2010
comment
@mose - да, я знаю - и оба предложенных решения будут делать именно то, что вы хотите :) Я постараюсь уточнить свой ответ! - person psmears; 01.07.2010
comment
При тестировании этих решений, если кто-то вводит $, perl интерпретирует смежную работу как переменную и выводит 0 вместо соседнего слова, поэтому, хотя да, он имеет дело с проблемой одиночной кавычки, похоже, он не исправляет никакие другие специальные символы, такие как @${} и |. Кроме того, пользователи не собираются добавлять \ для разрыва специальных символов. Они просто будут набирать сообщения и ожидать, что то, что они увидят в текстовом поле, появится в базе данных. - person Mose; 01.07.2010
comment
@mose: Если вы это видите, проблема должна быть в другом месте кода... вы уверены, что (1) переменная $note имеет именно то значение, которое вы ожидаете (т.е. возможно ли, что $ получил интерпретируется заранее) и (2) значение не повреждается после считывания из базы данных (т. е. приведенное выше работает, но код, который извлекает его из базы данных, не работает)? Из того, что вы говорите, похоже, что где-то есть дополнительный вызов eval (или результат передается без кавычек в сценарий оболочки или что-то подобное)... но приведенный выше код правильный, я обещаю :-) - person psmears; 02.07.2010
comment
Верно, но это то, к чему я веду. Проверить это невозможно. Я думаю, что все сосредоточены на аспекте вставки в базу данных, а не на его переменной части. Хотя методы, о которых вы говорите, будут обращаться к ошибочной одинарной кавычке, они не относятся к другим специальным символам, таким как $,} и т. д. В этом поле примечания обычно есть дампы экрана устройств Linux и Cisco. Поэтому такие символы, как $, # и круглые скобки, будут очень распространены. Я действительно не знаю, как еще описать то, чего я пытаюсь достичь, кроме как сослаться на то, как здесь работает «Добавить комментарий». - person Mose; 02.07.2010
comment
Я пытался использовать tr/\$/\\$ или что-то в этом роде, но регулярное выражение не моя сильная сторона. Также я нашел много библиотек через CPAN, которые очень помогли в преобразовании дат и других подобных общих задачах. Однако я наткнулся на точку преткновения, когда дело доходит до этой темы. - person Mose; 02.07.2010
comment
@mose: Люди сосредотачиваются на части базы данных, потому что это единственная часть, описанная в вопросе (и потому, что изначально опубликованный код имел серьезные проблемы с некоторыми символами). Если данные повреждаются в другом месте, нам нужно знать, где и как, иначе мы не сможем реально помочь (потому что цитирование должно быть сделано там и будет зависеть от того, как происходит повреждение). Я не уверен, что вы подразумеваете под «нет способа проверить это» - не можете ли вы добавить несколько printfs для проверки значения и/или прямого подключения к базе данных? - person psmears; 02.07.2010
comment
@psmears: $note = qq{тестирование специальных символов!@#$%^&*()_+}{;:'‹›.,;}; Если кто-то вводит это в текстовое поле, он терпит неудачу. $note не будет иметь согласованных данных. Это мемо-поле, которое независимо от того, что в него введено, должно быть вставлено в БД. Итак, моя первая задача состоит в том, чтобы понять, как заставить Perl не распознавать ничего из текстового поля как что-либо, кроме текста. В этот момент вставка базы данных должна быть легкой. У меня есть этот код базы данных, работающий для других частей страницы, которые принимают только числа, поэтому я предполагаю, что если perl игнорирует специальные символы, эта строка тоже будет работать. - person Mose; 03.07.2010
comment
@mose: если вы устанавливаете $note с qq{}, это говорит Perl, что он должен интерпретировать специальные символы! Я думал, вы сказали, что ввод исходил из CGI-формы? Если это так, то Perl вообще не будет интерпретировать никаких специальных символов! Вы действительно ожидали, что мы обнаружим проблему в части вашего кода, которая даже не упоминалась в вопросе? - person psmears; 03.07.2010

Наконец-то я понял, в чем проблема. Я могу избежать всех специальных символов из perl, используя q {$note};. dbh->quote здесь неприменим, так как он вызывает хранимую процедуру, и проблема не просто в сопоставлении кавычек. Одиночные кавычки должны передаваться в хранимую процедуру. Комбинация q и sed исправила это:

use DBI;
$livedb = DBI->connect("dbi:Sybase:server=test","admin","pass") || die "could not connect to live DB, $DBI::errstr";
$note = q {testing special characters:''''''''''''''!@#$%^%^&*()};
$note =~ s/'/\\'/g;
$livedb->do(qq {execute procedure jinsert(5304905,65,getdate,?);},undef,(param('$note')))

Короче говоря, при вызове такой хранимой процедуры, как эта, одиночные кавычки нужно экранировать дважды (один раз в perl, второй тип для хранимой процедуры).

person Mose    schedule 03.07.2010
comment
Здесь применима функция dbh-›quote() , потому что вы ее используете!! Как я уже сказал в своем ответе, вот как? механизм, который вы используете, работает. Дело не в совпадении кавычек - person psmears; 03.07.2010
comment
dbh-›qoute() не экранирует кавычки один раз внутри хранимой процедуры. Если я удалю $note =~ s/'/\\'/g; это ломает. - person Mose; 04.07.2010