Всех обитателей Сети можна разбить на несколько груп:
простые посетители Web-ресурсов;
владельцы этих ресурсов;
владельцы серверов, на которых располагаются сами страницы;
подлые хакеры (принадлежащие иногда к вышеперечисленным группам), мечтающие всем досадить.
Строго говоря, далее по тексту хакерами я назвал людей, которые ищут глюки в программном обеспечении и психологии человека. Не обязательно они делают что-то плохое. А под нарушением безопасности я понимал не только изменение главной страницы сайта на надпись «СайТ ХаКНуТ кРУтЫмИ ХаКерАмИ», но и действия, приводящие к унижению и потери уважения.
Простейший пример — оставить мат в гостевой книге. Вроде бы мелочи, но если владелец сайта вовремя не проконтролирует (уехал в отпуск), то запись увидят посетители, читающие книгу. Понятно, что хорошего в этом мало. Разве что запись представляет собой шедевр русского мата.
А ведь такое может сделать каждый, причем есть еще форумы, электронная почта, чаты. Как раз на днях я просматривал старые выпуски «Компьютерры» и нашел заметку про участие Ольги Дергуновой в чате. Такое впечатление, что сетевое хамство становится все большей нормой в интернетовской жизни... Впрочем, это тема для отдельной статьи, а пока рассмотрим более интересные вопросы.
Скорее всего, у вас есть домашняя страница или даже интересный для многих ресурс. В первом случае место для хранения информации легко найти, ведь существует большое число русских бесплатных серверов (Народ.Ру, Newmail.ru, by.ru). Однако со временем ваш сайт разрастется, и все чаще вам не будет хватать возможностей для реализации задумок: 50 мегабайт, кажущие в начале огромной величиной, быстро закончатся. Вам надоест переделывать каждый файл после изменения дизайна или смены адреса электронной почты. Вы с удивлением узнаете (хотя, наверное, сейчас уже все про это слышали), что можно не указывать длинные адреса типа http://mysite.server.ru/file.html, а просто писать file.html. Катастрофой будет момент, когда ваш сайт закроют из-за наличия несуществующих запрещенных материалов. Головной болью обернется временная недоступность сервера. Вам захочется иметь свой форум и чат, но стандартные бесплатные вас уже не будут устраивать. Вот тогда-то вы узнаете про всякие CGI, Perl, SSI, CSS. К огромнейшему сожалению окажется, что часть из перечисленного нельзя использовать простому смертному. Вы загоритесь мыслью заиметь домен второго уровня (эх, жалко, что первого нельзя) и получить неограниченный хостинг. В конце концов, вы найдете сервер, предоставляющий то, что нужно, на приемлемых для вас условиях. К этому времени вы уже будете уметь писать CGI-скрипты, и вот тут появляются новые проблемы.
Perl я выучил, когда готовился к экзамену в университете (если бы знал, что его поставят автоматом, то не скоро бы за этот язык взялся, а зря, потому что это «рулез форева»). Perl — превосходный язык для написания программ для сайта. Можно создать именно тот форум, гостевую, чат, счетчик, которые подходят именно вам. Свобода действий огромнейшая! Благо, что для языка дополнительных библиотек полно, можно и с реестром работать, и Windows-интерфейс использовать в страницах.
Фильтруй теги!
Но эта самая свобода обворачивается тем, что можно допустить непростительную ошибку. Писал я как-то чат. Хороший он вышел, не использовал Refresh, логи сообщений велись, шепот работал и т.д. И показалось мне, что неплохо будет, если пользователи смогут использовать в посылках HTML-теги. Естественно, только те пользователи, которым я или назначенные администраторы это позволят. Иначе очередной «продвинутый» сетевой хам напишет что-нибудь вроде HELLO!!!. И это еще цветочки, а ведь есть и инструкции ... Чтобы сильно не думать (ленивый я), достал толстую книжечку по Perl и взял из нее кусок кода, фильтрующий теги. Уже когда лег спать, вдруг осенило меня: не всегда это будет работать! Во-первых, не все теги фильтруются, во-вторых, ведь можно неправильно их писать, или писать правильно, но не закрывать. Попробовал - и действительно, если пользователь посылает в сообщении и не закрывает его, то следующие записи уже выводятся жирным начертанием. Пришлось добавить проверку на открывающиеся и закрывающиеся теги и ограничить их использование только стандартными.
Фильтрацию тегов нужно делать не только в чатах, но вообще везде, где возможен вывод того, что ввел пользователь. Контролировать надо даже имя в анкете.
Идентификация
Теперь про идентификацию. Вы задумывались над тем, что происходит при вводе вашего имени и пароля? Естественно, ввод сравнивается с базой данных, а дальше? Почему ничего не спрашивается далее, ведь вы не можете зайти по адресу на вторую страницу — выкинет на главную. Весь трюк в том, что ваша идентификационная информация передается прямо в скрытых элементах формы. На простеньких чатах вы можете найти свое имя и пароль в теле HTML. Кодируется примерно так:
Любой человек, имеющий доступ к компьютеру, имеет возможность узнать это. Вы ходите в интернет-кафе? А в чат оттуда заходите? Кстати, иногда идентификационные данные передаются прямо в строке адреса. Не надо даже копаться в кэше броузера, достаточно глянуть на экран.
А на совсем простых чатах для идентификации хранится только имя. Десятилетним «хакерам» очень нравится сохранять страницу, задающую фреймовую структуру, на диск и менять имя. Выходило так, что вы внезапно начинали ругаться.
Чтобы не передавать имя с паролем, рекомендуется при входе пользователя выделять ему временный случайный идентификатор и дальше работать уже с ним. В HTML-файлах ссылки теперь будут ссылаться на http://server.ru/cgi-bin/chat.pl?id=Wfw999YsJBdJ. Через заданный промежуток времени, если от пользователя не получено подтверждения, что он висит на линии, идентификатор обнуляется и теряет силу. То же самое происходит после того, как вы жмете ссылку «Выход».
Иногда для удобства вводится несколько режимов входа: обычный и с чужого компьютера. Если вы уверены, что никто не подсмотрит ваш идентификатор, имя с паролем спросят только один раз. После этого можно прямо заходить по ссылке, указав идентификатор. Или просто вынесите ссылку на рабочий стол, а потом ее используйте.
Все бы хорошо, но несколько лет назад я придумал способ, позволяющий узнать идентификатор человека. Мне надо было, чтобы этот человек зашел ко мне на сайт, нажав на гиперссылку. Сильно не приходилось уговаривать, просто назывался как-то загадочно и вешал на ник ссылку на сайт (хорошие форумы и чаты позволяют это делать). Пользователь попадал ко мне на страницу, а на ней грузилась картинка счетчика. Кроме функций счетчика велась небольшая статистика (подробнее о возможностях счетчика см. статью «Мне в логах видно все...»). Из нее я узнавал, с какой страницы ко мне зашли. Как вы догадались, я получал именно http://server.ru/cgi-bin/chat.pl?id=Wfw999YsJBdJ. Когда рассказал об этом создателю одного отличного чата, он долго думал о способе защиты. Теперь перед переходом на чей-то сайт в новом окне запускается скрипт, производящий редирект.
Заметьте, в этом примере мое участие было минимальным, просто когда-то на глаза попала статистика. А что, если кто-то решит серьезно заняться вашим сайтом?
Гостевые
Скрипты на Perl помогают существенно сократить время. Иногда в неблаговидных целях. Вернемся к гостевым книгам. В них обычно допускается ввод имени, e-mail, адреса сайта и отзыва. «Гостевые» нынче растут как грибы. Зашел человек на сайт, ничего полезного не нашел — у него самого все гораздо круче, только вот обидно, что никто этого не замечает. Дай, думает человек, оставлю запись в гостевой: «Круто, но у меня еще круче», и укажу адрес своей страницы. Хотя бы один человек, да зайдет.
Что представляет собой запись в гостевую? Есть форма, в которой несколько полей и кнопка Submit, отправляющая данные указанному скрипту. Все открыто, можете узнать поля и не заполнять их для отправки, а просто ввести адрес, оформленный по правилам:
http://server.ru/cgi-bin/guestbook.cgi?id=1&name=
Petya&email=&comment=
Кто мешает автоматизировать этот процесс? Хотите во все гостевые книги, существующие на сервере Guestbook.Ru, отправить сообщение? Напишите простейший скрипт, выложите на своем сервере и простым циклом пошлите заданную строку. А также отправьте ее во все известные форумы и чаты. Хотите сказать людям, что Вася Пупкин лучший литературный герой? Запостите это раз 1000 на соответствующий скрипт, обрабатывающий голосование. Если не умеете программировать, то придется 1000 раз нажать на кнопочку «Проголосовать» и «Вернуться».
Большая вероятность, что ничего не получится. По крайней мере, с отправлением на один и тот же адрес. Но вы использовали известные уважаемые сервера. А если то же самое сделает кто-то другой, но уже на ваш скрипт? Скорее всего, он (скрипт) захлебнется. Очень трудно предусмотреть все варианты фильтрации. Да и размер программы при этом увеличивается, а скорость обработки падает. Простейший вариант защиты — все обращения к скрипту фиксировать в лог-файле. Вам надо знать минимум две вещи — время записи и IP-адрес посетителя. Перед выдачей результата поищите в логе адрес пользователя, только что запустившего скрипт. Если таковой есть, причем пользователь делал это, к примеру, в последние сутки, то говорите «до свидания» и можете не фиксировать заход, все равно он повторный. Если посетителей у вас мало, то советую кроме времени и адреса записывать другую информацию о пользователе — откуда он запустил скрипт, какой имеет браузер и пр. Эти статистические данные помогут лучше узнать ваших посетителей. Если же ваш скрипт очень популярен и используется большим числом людей, то рекомендую проверять повторность постинга хотя бы за последние 5 минут. Не поленитесь завести отдельный файл для всех сообщений. Так, если вы держите у себя много гостевых книг, это предотвратит массовую рассылку, ну а далее проверяйте выбранную книгу уже за больший промежуток времени.
Обидно, что у многих пользователей интернета IP-адрес выделяется динамически провайдером. Можно столкнуться с ситуацией, когда вы решили проголосовать за что-то, а сервер вернул сообщение о повторном голосовании. Не пинайте админов ногами, просто перед вами там уже был кто-то от того же провайдера.
Рассылки
Если уж мы стали рассматривать вопросы массового спама, то поговорим о списках рассылок. Представьте, что будет, если ими воспользуется спамер. Самое печальное — то, что некоторые из них даже не надо похищать. Однажды мне понадобилось завести у себя список рассылки. Администрация сервера, предоставившая мне услуги хостинга, была против использования чужих рассылок и предложила использовать их стандартные. Работать с этой рассылкой было неудобно, но куда деваться?
Расскажу подробнее про рассылку. Чтобы подписаться на нее, пользователь должен послать на определенный адрес нужную строчку. После чего ему придет письмо, подтверждающее подписку. Если человек согласен, то на это письмо ему нужно ответить.
Итак, когда на сайте производилось обновление, я должен был отправить со своего адреса на адрес рассылки письмо с текстом новостей. После этого подписчики получали e-mail с новостями, причем перед самим текстом шла реклама, обрамленная звездочками. Да, забыл сказать, кодировки иногда не совпадали. Некоторым это, конечно, не понравилось и они отписались, но не это главное. Вы еще ничего странного не заметили? Чтобы подписчики получили рассылку, достаточно было послать письмо с ОПРЕДЕЛЕННОГО адреса на ОПРЕДЕЛЕННЫЙ. Последний легко узнаваем, потому что совпадает с названием рассылки, а мой тоже не секрет. Что из этого следует, писать не буду. Sapienti sat.
Хранение данных
Ладно, со скриптами вроде разобрались. Вспомним теперь, где хранятся данные к ним. Пароли, анкетные данные пользователей находятся в обычных файлах, чаще всего в текстовом виде. Номера кредитных карточек хранятся в таких же файлах, ничего сверхсекретного тут нет. Разве что формат будет другой, но для умного хакера это не проблема.
Скрипты обычно располагаются в каталоге cgi-bin. В принципе, название ничего не значит, главное, чтобы программы могли из него выполняться. Для простоты пользователи в этом же каталоге хранят и файлы данных. Если Web-сервер работает под ОС семейства Unix, права к любому файлу определяются как rwxrwxrwx. В этой абракадабре первые три буквы относятся к владельцу файла, следующие три — к группе пользователей, к которой принадлежит владелец, а остальные — ко всем остальным. r означает «read» (чтение), w — «write» (запись), x — «eXecute» (выполнение). Общепринято задание прав в восьмеричной системе счислений. Так, 0666 означает, что файл могут читать и писать владелец, группа и все остальные. Для скриптов права обычно другие — 0555 (можно читать и исполнять). Последний пример — 0700, с файлом может работать только владелец.
Давайте опять вспомним гостевую книгу и подумаем, какие права у нас в файлах с данными. Введенные записи можно посмотреть не только после ввода, но и через какое-то время, следовательно, у нас должен быть доступ на чтение и запись. Так как на большинстве серверов скрипты выполняются от имени nobody, то есть от третьей группы пользователей, то выходит, что для файлов мы должны как минимум задавать права 0006. Получается, что у нас сразу появляется потенциальная возможность читать и писать данные. Пусть файлы хранятся в каталоге /myhome/guestbook. Из интернета он может быть доступен по адресу http://myhome.site.ru/guestbook. Если записи сохранили в rec.dat, то при вводе http://myhome.site.ru/guestbook/rec.dat любой желающий прочитает всю информацию. Даже если имя файла с данными не известно, при некорректной настройке можно получить содержимое всего каталога, если пойти напрямую на http://myhome.site.ru/guestbook. Ведь права надо задавать не только для файлов, но и для каталогов.
Если же на сервере открыт доступ по ftp для guest или anonymous, то можно еще и изменять данные. Выход один — запретить анонимных пользователей и хранить информацию в каталоге, недоступном из интернета для обычных посетителей. Сделать это достаточно легко. Для Apache каждому пользователю положен каталог Name, в нем те файлы, которые попадут в интернет, лежат в каталоге Public_html. Просто создайте еще один каталог Name/cgi-dat. Доступ из скриптов на Perl к нему делается так:
open F, "../../cgi-dat/file.dat"; # открыли для чтения
Остается еще одна проблема. Не секрет, что к любым вашим файлам имеет доступ владелец сервера, пусть даже он честный человек. Но кроме него есть еще другие пользователи, входящие в ту же группу, что и вы. Например, на некоторых серверах вы входите в группу, к которой относятся все люди, пользующиеся услугами сервера. При создании файла автоматически назначаются права 0644. Я сталкивался с ситуацией, когда права были 0664. Каталог с данными у нас находится в безопасном месте. Но к нему точно так, как и вы, имеют доступ пользователи сервера. И они свободно могут читать файлы с паролями пользователей, скрипты и прочее. Каюсь, я сам на одном из серверов переписал себе все скрипты из библиотеки Мошкова. А иногда файлы можно еще и менять...
Защититься можно только одним способом — для группы пользователей, которым принадлежит файл, всегда ставить 0. Но и тут есть дыра. Член группы может написать скрипт, который прочитает все файлы из чужого каталога. Ведь, как уже говорилось, скрипт исполняется от лица nobody, а ему разрешено чтение, иначе сайт просто не будет доступен. Кроме этого, скрипт может писать в наш файл с данными от гостевой книги.
Но выход есть! К сожалению, приемлемый вариант я встретил только у фирм, предлагающих коммерческий хостинг. Все скрипты исполняются не от nobody, а он имени непосредственного владельца, то вас. Ставите файлам права 0600 — и вы на сто процентов защищены. Только будьте внимательны: малейшая ошибка в скрипте обернется крахом вплоть до полного уничтожения вашего каталога.