Вы находитесь на странице: 1из 32

Лекция 3

• CGI-программирование.
– Использование CGI.pm.
– Функционально-ориентированное
CGI-программирование.
– Использование cgi-lib.pl.
– Защита CGI.
– Примеры приложений.
Использование CGI.pm.
• CGI сценарий - программа на Perl,
выполняет обычные команды Perl, когда
она вызывается броузером (когда броузеру
в качестве URL задается сценарий). Все,
что направляется в стандартный вывод,
передается броузеру. Так, если CGI-
сценарий выполняет команду print "Hello!",
этот текст будет возвращен броузеру, и на
странице появится надпись "Hello".
• Для чтения данных, введенных
пользователем с помощью элементов
управления, создания этих элементов
управления из сценария и многого другого
используется прилагающийся к Perl пакет
CGI.pm. Это стандартный способ работы с
Использование CGI.pm.
• CGI сценарий - программа на Perl,
выполняет обычные команды Perl, когда
она вызывается броузером (когда броузеру
в качестве URL задается сценарий). Все,
что направляется в стандартный вывод,
передается броузеру. Так, если CGI-
сценарий выполняет команду print "Hello!",
этот текст будет возвращен броузеру, и на
странице появится надпись "Hello".
• Для чтения данных, введенных
пользователем с помощью элементов
управления, создания этих элементов
управления из сценария и многого другого
используется прилагающийся к Perl пакет
CGI.pm. Это стандартный способ работы с
Использование CGI.pm.
• Начиная с пятой версии Perl CGI.pm стал
объектно-ориентированным, хотя упрощен-
ный функционально-ориентированный
интер-фейс все еще существует.
• Создавая с помощью CGI.pm объекты CGI,
будем вызывать различные методы этого
объекта. Существуют методы,
соответствую-щие практически всем тегам
HTML, и при их вызове создается нужный
тег с указанными атрибутами. Все они
могут получать именованные параметры
(за исключением методов, требующих один
аргумент), иными словами, требуется
указать не только значение атрибута
HTML, но и его имя.
Использование CGI.pm.
• В следующем примере объект CGI
создает Web-страницу посредством
встроенных методов. Обратите
внимание на именованные параметры
метода textarea, задающие имя
области редактирования текста
('textarea'), значение по умолчанию и
размеры:
• Листинг 6. Создание Web-страницы.
Использование CGI.pm.
• Создание и использование элементов
управления HTML. Ниже приводятся два
CGI-сценария: один создает Web-страницу
с элементами управления — полями ввода
текста, переключателями, кнопками,
включая Submit, а второй читает данные,
введенные пользователем на этой
странице. Оба сценария — вариации с
небольшими дополнениями на тему
оператора print, который собственно и
создает страницу.
• Первый сценарий приводится в листинге 7.
Когда пользователь открывает сценарий в
броузере, сценарий возвращает страницу с
элементами управления HTML и текстом.
Использование CGI.pm.
• Когда пользователь нажимает на
кнопку Submit, расположенную в
конце анкеты, броузер собирает
данные, введенные на странице, и
передает их другому CGI-сценарию,
приведенному в листинге 8.
Функционально-
ориентированное CGI-
программирование.
• Пакет CGI имеет и функционально-
ориентиро-ванный интерфейс. В примере
код генерирует текстовое поле с
предложением ввести имя пользователя.
После нажатия на кнопку Submit данные
возвращаются к тому же CGI-сценарию,
который с помощью функции param
выводит введенное имя в нижней части
Web-страницы:
• Листинг 9. Функционально
ориентированный интерфейс пакета CGI.
Использование cgi-lib.pl.
• He менее популярен среди программистов
пакет cgi-lib.pl. Авторские права на этот
пакет принадлежат Стивену Е. Бреннеру,
на домашней странице которого (http://cgi-
lib.stanford.edu/cgi-lib) можно получить
копию cgi-lib.pl. Вам разрешается работать
с cgi-lib.pl и даже изменять его. Процедура
установки не требуется — файл cgi-lib.pl
копируется в каталог, где хранятся CGI-
сценарии, и с помощью команды require
подключается к ним:
require 'cgi-lib.pl';
Использование cgi-lib.pl.
• Если у вас нет этого пакета - используйте
модуль CGI.pm в таком контексте:
use CGI qw/:ReadParse,
PrintHeader, HtmlTop,
HtmlBot, SplitParam/;
• Далее создаются два сценария,
генерирующие те же страницы, что и
в ранее, но вместо CGI.pm на сей
раз будет использован пакет cgi-
lib.pl.
Использование cgi-lib.pl.
• Пакет cgi-lib.pl подключается к сценарию с
помощью команды require. Количество
функций, генерирующих теги HTML в cgi-
lib.pl, крайне ограничено. Впрочем,
некоторые теги HTML все же генерируются
автоматически: подпрограмма PrintHeader
создает шапку HTML, необходимую для
страницы, раздел HtmlTop (метки <HEAD>
и <BODY>). Также с ее помощью можно
создать заголовок страницы, как показано
в следующем примере, демонстрирующем
такой результат:
Использование cgi-lib.pl.
• Чтобы завершить Web-страницу метками
HTML </BODY> и </HTML>, можно
использовать подпрограмму HtmlBot .
• Чтобы прочитать данные, переданные CGI-
сценарию, используется подпрограмма
ReadParse. Она создает хэш (обычно
называемый %in) и записывает в него
значения элементов данных, переданных
сценарию. Элементы данных адресуются
по именам, присвоенным соответствующим
элементам HTML.
Использование cgi-lib.pl.
• Подпрограммы в составе cgi-lib.pl:
– CgiDie — как и CgiError, печатает сообщение
об ошибке и, кроме того, останавливает
программу.
– CgiError — печатает сообщение об ошибке,
используя стандартные заголовки и HTML-код.
– HtmlBot — возвращает строку
"</BODY>\n</HTML>\n".
– HtmlTop — возвращает раздел <HEAD>
документа HTML и открывает раздел <BODY>.
Необязательный строковый параметр
используется в качестве названия Web-
страницы: добавляется тег HTML <H1> с этим
названием.
– MethGet — возвращает значение истина, если
текущий вызов CGI сделан при помощи метода
Использование cgi-lib.pl.
– MethPost — возвращает значение
истина, если текущий вызов CGI сделан
при помощи метода POST. В противном
случае возвращается значение ложь.
– MyBaseUrl — возвращает базовый
адрес (base URL) CGI-сценария, без
дополнительного пути или строк
запроса.
– MyFullUrl — возвращает базовый адрес
(base URL) CGI-сценария, включая
дополнительный путь и строки запроса.
– PrintEnv — форматирует и печатает
переменные среды, доступные
Использование cgi-lib.pl.
– PrintHeader — возвращает строку "Content-
type: text/html\n\n". С нее должны начинаться
все Web-страницы, создаваемые cgi-lib.pl.
– PrintVariables — форматирует и печатает
значения данных. Ей передается хэш или
запись таблицы символов (для вывода
элементов соответствующего массива). Без
аргументов PrintVariables выводит содержимое
хэша %in.
– ReadParse —читает и разбирает данные,
переданные CGI-сценарию методами GET или
POST. Используется для создания хэша %in.
Хэш содержит данные, переданные сценарию,
упорядоченные по именам элементов
управления. Необязательные второй и другие
параметры указывают, что надо заполнить
соответствующие хэши данными из принятых
Использование cgi-lib.pl.
– SplitParam — разбивает параметр,
содержащий несколько значений, на список из
единичных параметров. Эта подпрограмма
предназначена для работы с элементами HTML,
способными хранить несколько значений, —
например, группой кнопок.
• В примерах значения данных, переданных
элементами управления HTML, выводились
непосредственно оператором print. Но это
можно сделать и проще: то же самое
делает подпрограмма PrintVariables, но
только в фиксированном формате.
Например, можно заменить пример 11
следующим кодом.
Защита CGI.
• Обеспечение безопасности всегда было
серьезной проблемой. Поэтому на Unix-
системах CGI-сценарии обычно
запускаются от имени идентификатора
пользователя "nobody" («никто»). Такой
процесс имеет минимум привилегий.
Считалось, что процесс, имеющий минимум
привилегий, принесет меньше вреда.
Однако и по сей день могут возникать
проблемы — в частности, из-за
неаккуратности в CGI-сценариях.
Защита CGI.
• Рассмотрим сценарий, запускающий
программы, имена которых передаются
ему в качестве аргумента. Но хакер может
послать собственную строку такого вида:
http://www.server.com/user/perl.exe?-e+
nasty commands
• Так он сможет выполнить любые команды
Perl. Это одна из самых больших
опасностей CGI-сценариев, написанных на
Perl, — вызовы внешних программ без
проверки кода, передаваемого в конце
строки.
• В Perl внешние программы вызываются с
помощью строки, заключенной в обратные
апострофы, вызовов system или exec.
Защита CGI.
• В Perl существует механизм безопасности
—меченые данные. Если разрешено
отслеживание данных, Perl не позволяет
передавать пришедшие извне данные
функциям system, exec и т. д.
• Простое правило, позволяющее
обеспечить безопасность, —не передавать
непроверенные данные внешней
программе.
• Если это невозможно, следует проверять
аргументы на предмет наличия
метасимволов командной оболочки и
удаления их. Вот метасимволы командной
оболочки Unix:
Защита CGI.
• Работа с мечеными данными (tainted
data). Любые переменные, связанные с
данными, полученными извне (включая
переменные среды, стандартный поток
ввода и командную строку), считаются
мечеными. Пока они остаются таковыми,
их нельзя использовать для чего бы то ни
было за пределами вашей программы. Если
меченая переменная используется для
установки другой переменной, последняя
также становится меченой, что означает,
что помеченные данные могут
распространяться по программе сколь
угодно далеко, но они все равно будут
помечены.
Защита CGI.
• Вы можете включить проверку меченых
данных, передав интерпретатору Perl ключ
-T:
• #!/usr/local/bin/perl -T
• При выполнении потенциально опасных
операторов типа system при включенной
проверке меченых данных Perl сообщит о
возможной бреши в защите,
обусловленной использованием данных
окружения. Вот сообщение об ошибке,
которое вы увидите:
#!/usr/local/bin/perl -Т
print system( 'date');
Insecure $ENV(PATH) while running with
Защита CGI.
• Чтобы исправить это, вы можете при
включенной проверке меченых данных
самостоятельно установить $ENV{'PATH'}:
#!/usr/local/bin/perl -T
$ENV{'PATH'}='/bin:/usr/bin: /usr/local/bin';
print system('date'),
Thu Nov 12 19-55 53 NSK
• Даже если $ENV{'PATH'} устанавливается в
программе, сценарий все равно
прекращает работу, при попытке передать
меченые данные оператору system:
#!/usr/local/bin/perl -T
$ENV{'PATH'}=‘/bin:/usr/bin:/usr/local/bin’;
while(<>) { $command = $_; system($command); }
Insecure dependency in system while running
with -T switch at taint.pl line 5, <> chunk 1
Защита CGI.
• Очистка данных. Единственный способ
очистить меченую переменную —
использовать шаблоны, по которым из нее
выбираются подстроки. Меченая
переменная $tainted содержит
электронный адрес. Мы можем извлечь его
и сохранить как не меченый в другой
переменной :
$tainted =~/(^[\w]+)\@(^[w]+)/
$username = $1; $domain = $2;
print "$username\n";
print "$userdornain\n';
• Способ создания «чистых» данных
заключается в извлечении из меченых
данных подстрок, которые априори
Защита CGI.
• Не позволяйте другим перезаписывать
ваши сценарии или файлы данных.
Другими словами будьте особенно
внимательны к правам доступа к файлам,
чтобы их нельзя было заместить.
• Не посылайте пароли по электронной
почте, не набирайте их при работе с
бесплатными утилитами. He оставляйте
ваш счет в системе (account) на долгое
время неиспользуемым. Не позволяйте
CGI-сценариям получать слишком много
системной информации.
Защита CGI.
• Вот несколько Web-страниц, посвященных
безопасности CGI:
– страница WWW-консорциума, посвященная
безопасности CGI —
www.w3.org/Security/Faq/www-security-faq.html;
– часть сборника вопросов и ответов (FAQ) по
CGI-программированию на Perl, посвященная
проблемам безопасности, - www.perl.com/CPAN-
local/doc/ FAQs/cgi/perl-cgi-faq.html;
– страничка Селены Сол (Selena Sol),
рассказывающая, как вы рискуете при
установке чужих сценариев —
Stars.com/Authoring/Scripting/Sequrity;
Примеры приложений.
• В примерах вы найдете информацию том,
как писать CGI-сценарии для счетчиков и
гостевых книг.
• Счетчик посещений. Вы должны хранить
текущее значения счетчика в файле и
показывать его при необходимости.
• Чтобы он работал, в том же каталоге, что
и сценарий, должен находиться файл
counter.dat. Для начала отсчета запишите
в counter.dat 0 (ноль) с помощью любого
текстового редактора.
• Листинг 13. Счетчик посещений.
Примеры приложений.
• Гостевая книга собирает комментарии
пользователей и сохраняет их в файле,
имеющем формат HTML, чтобы затем
выводить их на странице. Наша гостевая
книга использует три файла, хранящихся в
одном каталоге: guestbook.htm (листинг
14), guestbook.pl (листинг 15) и book.htm
(листинг 16). Первая страница указывает
пользователю, что он может добавить
запись в книгу посетителей. Она получает
имя пользователя и комментарий. Когда
пользователь нажимает на кнопку
подтверждения, данные посылаются
сценарию guestbook.pl.
Примеры приложений.
• В guestbook.pl (листинг 15) мы открываем
собственно гостевую книгу, хранящуюся в
файле book.htm. Он заканчивается тегами
</BODY></HTML>. Поэтому сначала надо
установить указатель файла перед этими
словами с помощью следующего кода:
open (BOOK, ">>book.htm") or
die "Could not open guestbook!";
seek (BOOK, -length ($co->end_html),2);
• Поскольку строки </BODY></HTML> в
данном случае создаются с помощью CGI-
метода end_html, мы откатываемся назад
на длину генерируемой строки.
Примеры приложений.
• После этого код записывает вместо
тегов </BODY></HTML> новые
данные, добавляя в конце те же теги
вызовом CGI-метода end_html.
• Затем guestbook.pl создает страницу,
на которой располагается
благодарность пользователю за
комментарии и гиперссылка,
позволяющая просмотреть
содержимое гостевой книги.
Примеры приложений.
• Теневые посылки (cookies). Под этим
именем подразумевается использование
протокола HTTP для хранения
информации, полученной от сервера, на
машине клиента и обмен этой
информацией между компьютерами и
броузерами незаметно от пользователя, то
есть в теневом режиме.
• В большинстве броузеров верхний предел
теневых посылок — число порядка 200.
Теневые посылки позволяют отслеживать
передвижение пользователей по разделам,
а также хранить настройки пользователя.
Примеры приложений.
• Сценарий, приведенный в листинге 17,
позволяет посетителю изменить страницу
так, чтобы при следующих визитах она бы
приветствовала ею по имени, а в день
рождения еще и поздравляла бы.
Сценарий проверяет данные, полученные
от пользователя чтобы убедиться, что день
рождения введен в формате месяц/день
(mm/dd), содержит лишь цифры, а
единственный символ / находится в
нужном месте, и удаляет теги HTML,
которые он мог ввести в строку для имени.
Примеры приложений.
• Когда пользователь впервые открывает
сценарий hellocookie.pl, он может
настроить эту страницу, введя имя и дату
рождения в формате mm/dd. После
нажатия на кнопку подтверждения
сценарий записывает информацию под
именем greetings, сохраняя имя и день
рождения, на компьютере клиента.
• Когда пользователь снова открывает
hellocookie.pl, сценарий проверяет, нет ли
у посетителя теневой посылки greetings, и,
если она есть, выводит приветствие,
включая при необходимости поздравление
с днем рождения. Вот и все.