Привет, уважаемый читатель журнала. Уверен, что у тебя есть свой сайт. Может быть, это хом-пага, или новостной портал, или ты админишь и/или пишешь скрипты для корпоративного сайта твоей организации?
Возможно также, что ты счастливчик, и тебя не разу серьезно не ломали… или просто ты действительно хорошо представляешь как защитить свой сайт от хакеров, и взлом твоего сайта крайне затруднен. Ну что ж, не смотря на все это – рекомендую прочитать данную статью, для повышения своего опыта, для расширения кругозора… для того чтобы убить время, в конце концов :)

Первым делом, мы рассмотрим такое интересное явление, как стандартизация. Что это такое? Обратимся к некоторым справочникам:

«Стандартизация - это деятельность по установлению норм, правил и характеристик в целях обеспечения: безопасности продукции, работ и услуг для окружающей среды, жизни, здоровья и имущества; технической и информационной совместимости, а также взаимозаменяемости продукции».

И более словарное:

«Стандарт (от англ. норма, образец):
в широком смысле слова - образец, эталон, модель, принимаемые за исходные для сопоставления с ними других подобных объектов.»

Исходя из этого, вы наверно уже подумали – стандарт есть хорошо, штандарт - зер гут :)
Но теперь, небольшой жизненный пример:

Вы программист на PHP/Perl. Вы понимаете и знаете, что публичные скрипты использовать на своем сайте – опасно. И вы пишете свой скрипт/движок, по всем стандартам. И оказываете тем самым бесценную услугу взломщикам.
В данном вопросе – соблюдение стандарта, имеет смысл в отношении внутренней структуры программы (кода, данных и т.п), но не внешнего окружения (переменные, названия баз данных, названия каталогов и скриптов и их размещение).
Перейдем от голословных рассуждений к практическим примерам:
Ниже я перечислю полезные рекомендации, которых стоит придерживаться, если вы хотите, как можно меньше подвергать свой сайт попыткам взлома:

1. Не размещайте вход в административный интерфейс на главной странице сайта
2. Не размещайте вход в административный интерфейс по следующим путям:
- http://site.name/admin/
- http://site.name/admin.php
- http://site.name/login.php
-- все это относится и к скриптам на perl, только с поправкой на каталог /cgi-bin/, /cgi/, /cgi-perl/, или без поправки если вы используете mod-perl для всех каталогов вашего сайта.
3. Не храните конфигурацию для ваших скриптов в файлах с расширением отличным от .php (к примеру: config.inc, config.db. config.txt :))). Если вы храните конфигурацию в файле с расширением php – то сможете просто подключать ее к вашим скриптам через include-функцию. Perl программистам – так же рекомендую хранить конфигурацию в файлах с расширением .cgi или .pl. При этом – чтобы не генерить лишний раз ошибку с кодом 500, при случайном вызове этого скрипта из web, пропишите в начале скрипта примерно следующее:   

   3    if(defined $ENV{'REQUEST_METHOD'}) {
   4    
print "Content-Type: text/html\n\n";
   5    
print qq(Forbidden kids!);
   6    
exit 0;
   7    
}

Можно оспорить это утверждение, аргументируя возможностью проставить правильные права доступа к файлу. Но лучше застраховать себя от своей же забывчивости, к примеру при перезаписи файла, вы можете забыть сменить права, либо если работаете через всякие web-файловые менеджеры, которые сами могут содержать ошибки. В общем – рекомендую. И кстати, это реализовано во многих серьезных движках. К этому пункту, могу еще добавить, что не обязательно хранить конфигурацию в файле с названием config. Включите воображение, хотя естественно имя должно быть логичным, чтобы не путаться (к примеру, если вы работаете над скриптами в команде). Наиболее рационально – делать различные префиксы к именам файлов, как то: _config.php, Config__main.php, config2site.php и т.д

Пример из практики:
Как то раз, я решил проверить, сколько примерно сайтов имеют в своей корневой структуре каталог /admin/, и забил в гугле поисковый запрос: «Керамическая плитка»… Не совсем логичный запрос… Но я хотел пройтись по корпоративным сайтам небольших, как правило московских компаний. Из 20 просмотренных мной сайтов – 12 оказались с папкой /admin/ в корне. В 3-х из этих сайтов меня пустили в административную часть с логином admin, и идентичным паролем. В 2-х интерфейсах имелся файловый менеджер, для загрузки файлов на сервер, и просмотр файлов в каталоге. При этом – для ограничения просмотра файловой структуры, в одном из интерфейсов был применен метод защиты «от дурака» - окно файлового менеджера было с обрезанной адресной строкой, и нельзя было отследить параметры передаваемые скрипту… Но это как известно защита от пользователей IE, да и то – недалеких… В броузере Opera – я без лишних телодвижений просмотрел всю файловую систему сервера (доступную для чтения). (!)Здесь стоит сказать о пользе PHP опции safe_dir, которая позволяет ограничивать действие php скриптов только домашним каталогом пользователя.
В одном из оставшихся 9 сайтов с каталогом /admin/, я смог попасть в админку при помощи нехитрого запроса: Логин: admin Пароль: 1'or'1'='1.

Из пункта 3 вытекает правило №4.

4.Старайтесь не наделять административный интерфейс возможностями работы с файлами на прямую. И ни в коем случае не добавляйте опции прямой работы с командным интерпретатором. Что под этим подразумевается. К примеру, вам надо иметь возможность загружать файлы, удалять файлы и производить прочие операции над файлами в определенных каталогах сайта. Это лучше реализовать, к примеру следующим образом:
Опция А: - Загрузить файл в папку Документы
Опция Б: - Отобразить файлы в папке Документы
и т.п.

То есть пользователь должен работать с виртуальными именами, с псевдо файловой системой. В приведенном примере – папка "Документы" может физически располагаться в /public_html/UserDocs/. При этом формируя запросы к скрипту – нельзя применять нижеследующий синтаксис (или аналогичный):

filemanager.php?file=name.txt&dir=../../some/dir

Пути должны быть более или менее жестко прописаны. Или хотя бы прописаны абсолютно одного каталога. К примеру запрос:

filemanager.php?file=name.txt&dir=Документы

более безопасный. К тому же тут идет работа через так называемые псевдонимы. Папки «Документы» – физически нет на диске, а ей соответствует псевдоним, прошитый в скрипте или в конфигурации. Естественно - необходимо тщательно фильтровать имена файлов - никаких точек кроме точки для расширения. Или еще лучше – вы можете определить круг допустимых расширений, и делать соответствующую проверку. К слову сказать, на Perl это реализуется просто и надежно – одним регэкспом в конструкции типа:

if ($filename=~/.doc$|.txt$|.pdf$/) { print “Good”; } else { $filename=~s/\.*$/.txt/; }

Относительно выполнения команд, тоже самое – работайте через псевдонимы, к примеру поменять разрешение на файл можно осуществлять таким запросом:

filemanager.php?file=name.txt&mode=up+1

В общем – идея в минимизировании СТАНДАРТНОЙ логики, которая может быть сходна с операциями в реальной системе с реальным командным интерпретатором.

5. Не размещайте скрипты, которые не предназначены для работы через WEB в доступных из WEB каталогах. К примеру, скрипты предназначенные для работы через cron, есть смысл размещать выше папки public_html*
* - на большинстве хостингов структура пользовательского каталоги примерно такая:

/usr/home/username/…
--- директории доступные из web ---
/public_ftp/
/public_html/

Не думайте, что вы не можете создать в корне вашей папки еще каталоги. И не думайте, что корнем вашей папки является /public_html/ (или www – алиас на эту папку).
Смело создавайте новую папку и размещайте там все скрипты предназначенные не для WEB, а то кто-нибудь запустит ваш еще не дописанный скрипт для бэкапа базы данных вашего сайта, и в лучшем случае - сохранит их к себе на диск, в худшем – попортит базу.

1. Если вы используете публичные скрипты. Что стоит предпринять для снижения вероятности взлома (во всяком случае, шального взлома – через поисковый запрос на Google)?
Первое – по возможности измените имена скриптов. Во многих серьезных движках это предусмотрено в конфигурации (к примеру, движок Movable Type – позволяет задавать пользователю в конфигурационном файле имена для основных скриптов).
Второе – покопайтесь в исходном коде, возможно вы заметите ошибку первым (если вы конечно разбираетесь в языке программирования на котором написан движок).
Третье – попробуйте удалить информацию о версии движка, а в идеале и об его названии. Хоть это и не приветствуется разработчиками, и может быть в некоторой степени нечестно… Но… в общем решать вам. К слову сказать, на любимом мной форуме Ikonboard, за возможность удалить информацию о названии движка берут деньги. А проблема решается – изменением кода в одном файле. И поверьте это гораздо проще, чем может показаться на первый взгляд. Всего лишь загляните в файл /Source/Admin/BoardTemplates.pm, в функцию add, после правки, которой можно изменить шаблон как угодно. Но это так, к слову.
Четвертое – не устанавливайте движки по стандартным путям. К примеру – печально известный phpbb, в основном ставится в каталог /phpbb/, по подобным запросам жертв и находят (не считая слов Powered by.. но об этом я уже сказал).
Пятое – очень полезная вещь – это Базовая авторизация. Ее не сложно применить к вашему сайту (на большинстве хостингов, это можно сделать через cpanel, что вообще элементарно). Где ее стоит использовать? К примеру, на доступ к каталогу с админкой (к описанному выше /admin/, хотя я надеюсь, вы уже переименовали этот каталог??). Что это дает для публичных движков? Дополнительный уровень защиты. Для того чтобы проэксплуатировать известную уязвимость, злоумышленнику достаточно найти ваш сайт и следовать инструкции из багтрака. Но он не ожидает от вас такой подлости, как базовая авторизация :). К плюсам ее стоит добавить, то что она не передается в cookie-файлах, и поэтому украсть данные о пароле (хэше) через межсайтовый скриптинг не удастся (во всяком случае обычными и провереннями методами... есть идеи с внедрением через ActiveX сниффера, и отлова хэша... Хотя в этом случае проще отловить нажатия на клавиатуре :-))). К минусам - отсутствует защита от перебора (брутфорса). Это решаемо отчасти, через установку на директиву ErrorDocument редирект на ваш скрипт, который, к примеру может отсылать уведомление на почту администратору, в случае многократных попыток подбора паролей (то есть не удачных входов с одного IP).

Вроде бы все о публичных движках. Вернемся к самописным движкам и скриптам.

Хорошей практикой для вас, как программиста, может стать такая привычка: после установки на ваш сайт нового скрипта – попробуйте поэкспериментировать с запросами к нему. Подставляйте, там где поступают цифры, отрицательные значения, кавычки (‘,”), для скриптов на perl – попробуйте значения типа: s//, ~s/$/, $DATA. Там где идет обращение к файлам – попробуйте использовать символы перехода по каталогам (../../), и после имени файла – завершающим нуль-символом (%00). Если ваш скрипт на все ваши извращения не ругнулся ни разу матерным словом, все перенес стойко – то это уже плюс вам, как разработчику.

Пример из практики:
Есть такой замечательный портал medlinks.ru, посвященный вопросам медицины. При поверхностном тестировании этого сайта, обнаружился внутренний инклуд, в параметре file. Об этом было сообщено администратору сайта, после чего пришла благодарность от него и брешь закрыли. Для простого теста я попробовал отправить такой же запрос, но уже в переменную name. И история повторилась. Снова письмо админу сайта, с более подробными руководствами, но ответа не последовало, и уязвимость еще действует.
Здесь стоит сказать об одной особенности программы Midnight Commander. Она вроде бы не причем, но я думаю стоит упомянуть именно здесь о ней. Многие администраторы пользуются этой утилитой (а также владельцы сайтов с шелл-доступом). Помимо того, что они пользуются mc, они недооценивают уязвимость типа – внутренний инклуд (возможность чтения файлов на сервере). Так вот в сочетании с mc – внутренний инклуд становится чрезвычайно полезен для взломщика. Как известно – каталог с настройками mc хранится в /usr/home/username/.mc/, и выйти на этот каталог нетрудно. В этом каталоге присутствует несколько файлов, как-то:
total 22
-rw-r--r-- 1 poizon wheel 35 25 17:35 Tree
drwx------ 2 poizon wheel 512 7 10:55 cedit
-rw-r--r-- 1 poizon wheel 4029 25 11:41 filepos
-rw------- 1 poizon wheel 8675 25 17:35 history
-rw-r--r-- 1 poizon wheel 2681 25 17:35 ini
Для примера я взял данные из своего каталога. Нас интересуют тут файлы доступные для чтения всем – это ini и filepos, при этом в каталоге у пользователя root, эти файлы так же доступны для чтения. Рекомендую изучить их содержимое на досуге. Через чтение этих файлов – можно добраться до очень укромных уголков вашей системы. В частности на сервере medlinks.ru была обнаружена информация для доступа к БД в исходниках на C++.

Из всего сказанного в этом абзаце – вытекает следующий принцип.
Тщательно фильтруй все данные. При этом важно – чтобы ты понимал какие данные – куда ожидаются поступить. Так как я не силен в PHP, приведу простые примеры на Perl:

Если ожидаешь в переменной только цифры – все остальное режь:

$var=~s/[^0-9]ш;

Если ожидаешь только буквы латинского алфавита, все остальное режь:

$var=~s/[^a-z]ш;

И т.п и т.д. Так называемая концепция "белых списков", а не черных. То есть пропускать только то что разрешено, а не фильтровать то что запрещено. Естесственно, не забудь определять для каждого запроса - значения по умолчанию.
В этом плане – perl – чертовски хорош. В нем нельзя так просто переопределять значения переменных, так как это можно на php. Но если вы тщательно фильтруете данные, то будте спокойны, не зависимо от языка реализации приложения. Нет плохих языков – есть плохие программисты (за небольшим исключением – ошибки в самих интерпретаторах).

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

До встреч в сети.

 
     
     
Назад
by PoizOn
Вперед