Проблема сетевой безопасности — штука очень серьезная, и, пренебрегая даже одним из базовых правил, ты рискуешь потерять все. Эту аксиому всегда надо держать в голове. Как бы ты ни укреплял строение, какие бы бастионы ты ни возводил, но, не построив прочного фундамента, нельзя двигаться дальше. Сетевая безопасность и есть тот фундамент. А как все может пойти без одного кирпичика, ты увидишь в сегодняшнем рассказе.

Начало

Сегодня я хотел бы поделиться с тобой, дорогой читатель, историей, которая приключилась в далеком 2010 году. На дворе стояло лето, солнце нещадно жгло нас своими лучами, а столбики термометров в тени поднялись до 35 градусов. Поэтому выходить из дома, где работал кондиционер, лишний раз совсем не хотелось. Тем более работы хватало. Как раз одна забугорная контора, которой я периодически помогал как аутсорсер, подкинула мне заказ на аудит безопасности одной достаточно крупной медиасети. Поэтому я решил незамедлительно приступить к делу.

WARNING

Описанная в статье ситуация не является призывом к взлому, а лишь указывает администраторам на возможные ошибки в конфигурации и реализации проектов.


Зайдя на главную страницу медиапортала, я сразу же пошел в раздел Magazines, их там оказалось около тридцати штук. Ну что же, подумал я, посмотрим, есть ли где-то поблизости баги. Чтобы зря не терять время, первым делом запустил демоверсию XSpider’a с одним из стандартных профилей, в которую занес сайты из раздела, а сам, надеясь на легкий и максимально быстрый результат, принялся насиловать гугл дорками типаsite:magazine1.com filetype:php. Увы, этот запрос, равно как и запросы видаsite:magazine1.com warning failed и site:magazine1.com mysql error, которые, по идее, должны были отобразить страницы с ошибками, ничего путного не дали.

Немного опечалившись, я решил посмотреть на первые результаты работы сканера. Но и XSpider в этот раз отказался меня порадовать. Наружу были открыты всего два порта: 80 и 443, а из дополнительной информации было получено: версия апача, файл robots.txt, crossdomain.xml, в котором были прописаны доверенные домены, и папка admin с basic-авторизацией. Никаких phpinfo, папок test, misc и тому подобного не было. Из полезной информации также получилось выцедить, что у компании в управлении две сетки с адресами 209.108.50.* и 209.108.51.*. Рабочие сайты крутились на 209.108.50.111 и 209.108.51.16, таким образом, можно было запустить сканер на проверку всех IP-адресов в этих сетях в надежде найти тестовые серверы, где, возможно, присутствуют баги.

Ну что же, сканер сканером, а мне представилась возможность ознакомиться с контентом сайта лично. Открыв браузер и запустив Tamper Data, начинаю изучать содержимое. После двух часов анализа я понял, что сайты этой медиасети крутятся на какой-то CMS, скорее всего самописной, а также, что, вполне вероятно, найти в ней уязвимость не получится. Напоследок решаю зайти в раздел site_map.

Первая победа

В site_map-то и надо было зайти в первую очередь! Ссылка видаhttp://magazine1.com/site_map/category_3245 сразу же заставила меня провести нехитрую математическую операцию http://magazine1.com/site_map/category_3246-1.

Моей радости не было предела, когда я увидел, что результаты одинаковы. После этого, используя конструкцию orber by, я выяснил, что в запросе участвует 28 полей, а затем, заюзав union select, узнал, что третье поле выводится в браузер. Теперь мне не оставалось ничего, кроме как узнать версию MySQL-сервера, базу и пользователя, от которого идут запросы к базе:

`http://www.magazine1.com/site_map/category_3245 union select 1,2,concat(user(),0x3a,version(),0x3a,database()),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28`

Из ответа я узнал, что имя пользователя wwwuser, версия MySQL — 5.1.40, а база данных именуется ezine. Увидев версию MySQL, я порадовался еще раз и скомандовал:

`http://www.magazine1.com/site_map/category_3245 union select 1,2,concat(schema_name,0x3a,table_name,0x3a,column_name),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28 from information_schema.columns limit 1,1`

А вот ответ совсем удовольствия не принес: пустая страница говорила о том, что доступ этому пользователю к чтению служебных таблиц запрещен. Вот это был действительно удар! Грамотная настройка MySQL в крупных компаниях — это скорее исключение, чем правило. На моей практике такая ситуация встречалась максимум раз пять. Иногда, конечно, попадается запрет на чтение information_schema.tables, и в таких случаях обращение к таблице columns позволяет обойти досадное ограничение. Но не в этот раз. Мне оставалось только попробовать сбрутить названия таблиц и полей в них. Запустив SIPT, я решил немного отдохнуть.

Подойдя к компьютеру после отдыха, я увидел, что программка нашла таблицу users и два поля в ней — email и password. Всего учетных записей оказалось 1290. Все почтовые ящики принадлежали к доменам компании, и у меня появилась надежда на то, что полученные результаты можно будет применить к папке admin. Пароли были зашифрованы DES’ом, поэтому для дальнейшей работы были переданы в John the Ripper. Через пару часов Джон расхешил более половины пассов, и данные были переданы еще одному незаменимому помощнику — Brutus’у. Был выбран комборежим, где в виде логинов были как сами почтовые адреса, так и имена пользователей от почтовых адресов. Проверка шла по basic-авторизации. И снова облом! Ни одна учетная запись не подошла. Но сам факт инъекции на продакшн-сервере говорил о том, что бага была не последняя.

Попытка № 2

Как я говорил выше, сайты, принадлежащие компании, находились в двух сетях класса С. XSpider к этому моменту показал живые хосты в сетях, и я решил попробовать получить инфу о сайтах через инструмент Reverse IP domain check ресурса yougetsignal.com. Первые два десятка хостов оказались для меня неинтересными, ибо при заходе выдавали страницу подписки, а yougetsignal не имел инфы о данных IP-адресах.

А вот на третьем десятке мне улыбнулась удача. Полезный ресурс выдал, что на данном IP крутилось девять сайтов, причем часть из них не была указана в разделе Magazines. Начав по очереди открывать сайты в браузере, я понял, что попал на один из тестовых серверов. Некоторые сайты не открывались, какие-то были полуживые, а некоторые функционировали нормально. Также был найден WordPress версии 2.3.1 без возможности регистрации.

Теперь, начав терзать гугл более целенаправленно, я стал получать более интересные результаты. Например, спросил XSpider, что ему известно о stylewar.magazine2.com, и в ответ получил около двадцати ссылок, часть из которых выводила ошибки на странице, а другая часть содержала ссылки с параметрами. Одной из них была такая вот ссылка:http://stylewar.magazine2.com/styles/account/782855. Правда, на самой страничке никакой полезной информации не выводилось, но, подставив кавычку в запрос, я получил и вывод самого SQL-запроса, и вывод всех ошибок.

Ну что же, бага есть — будем раскручивать. Order by сообщил, что в запросе участвует всего одно поле, а union select, со своей стороны, любезно добавил, что это поле в браузер не выводится. Опять двадцать пять, ну никак не получается легкой победы. Пришлось использовать error-based технику. В итоге запрос, выводящий название базы и имя таблицы, получился следующим:

http://stylewar.magazine2.com/styles/account/-1 order by (select 1 from(select count(*),concat((select concat(table_schema,0x3a,table_name) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

А запрос, выводящий логин и пасс админа, выглядел следующим образом:

http://stylewar.magazine2.com/styles/account/-1 order by (select 1 from(select count(*),concat((select concat(username,0x3a,password) from starup.users limit 0,1),floor(rand(0)*2))x from starup.users group by x)a) 
Рис. 1. Логин админа и его пасс в MD5
Рис. 1. Логин админа и его пасс в MD5

А сами логин и пасс были следующими: admin@starup:24f1d7bec343596cf0a74011ab92d2ca. Как ты можешь видеть, пароль представлял собой обычный MD5-хеш. И уже через 15 секунд гугл сообщил, что это слепок от пароля promtime. Ну что же, есть логин и пасс администратора, и следующий вполне закономерный шаг — это поиск собственно самой админки. Для этого я использовал шустрый сканер файлов и папок ArxScanSite. Так вот, буквально через пару минут он сообщил, что админка находится в папке cms. Отлично, вперед к новым свершениям, перехожу по ссылке и…

Мегабаг

Честно говоря, я уже устал обламываться. Но устал не устал, а факт остается фактом — админка не работала. Не хватало какого-то контроллера.

Рис. 2. Неработающая админка
Рис. 2. Неработающая админка

Пришлось заодно просканировать и другие сайты на этом хосте. В итоге из всех девяти сайтов у меня получилось найти только одну живую админку:http://stylewar.magazine2.com/cms. Зайдя на страничку, ввожу полученные логин и пароль и в который уже раз не получаю желаемого результата. Не знаю, на что я рассчитывал, начав проверять возможные дефолтные комбинации логина и пасса, но какое-то странное стечение обстоятельств или похмельный синдром админа, а может быть, просто матрица решила посмеяться над администратором, заставив последнего совершить epic fail. Со второй попытки я оказался внутри. Логин и пароль, впустившие меня внутрь, были admin:password. Такого не должно было быть в принципе! И тем не менее это реальность!

Немного побродив по админке, нашел форму загрузки картинок в разделе добавления стилей и, как это обычно случается, по ошибке вместо JPG-файла загрузил пхпшный шелл. Админка успешно переварила скрипт, предоставив мне новые возможности для творчества.

Внутренний анализ

Первым делом собираем все необходимые данные для дальнейшей работы. Коннект наружу из локалки при помощи нетката оказался закрыт файрволом. Можно, конечно, было воспользоваться HTTPTunnel, но он оставляет много следов в логах веб-сервера. Поэтому я стал работать через веб-шелл. Конфигурационные файлы апача лежали в/usr/local/apache/conf/, здесь же лежал и файл users (скорее всего, это был переименованный .htpasswd) с шестью пользователями-разработчиками и их зашифрованными паролями. Они также были переданы JTR. Следующим интересным файлом оказался compiled_conf.dat, расположенный по адресу/home/webuser/servers/production.new/state/conf.

Рис. 3. Смешные пассы в конфиге
Рис. 3. Смешные пассы в конфиге

Про всевозможные *.inc и *.php конфиги, расположенные в веб-директориях, особо стоит заметить, что пар login:pass, в них содержащихся, как правило, хватает для подключения к локалхосту или какому-то хосту/хостам в сети. Что уже позднее предполагает большее количество векторов в развитии возможной атаки. Меня же в тот момент интересовала возможность получения доступа в веб-админку управления серверами компании.

К этому времени Джон выдал один из пассов. Он оказался до безобразия прост — 1942. Как видно, динозавры вполне себе живут и здравствуют. К тому же во время сканирования сети XSpider’ом был обнаружен один интересный сабдоменhttp://betapreview.magazine3.co.uk/. Во время обхода сети сканер сообщил, что возможна авторизация с комбинацией логина пароля test:test. Правда, у данного пользователя прав было минимум, а вот пароль админа с тестового сервера подошел, и я оказался в полноценной админке.

Админка

В панели управления было несколько разделов, из них наиболее интересные Internal Tools и Systems. В секции внутренних инструментов обнаружилось около десяти ссылок, в том числе на Server Status, Database Tools и Server Info. В статусах можно было увидеть проблемные серверы (их локальные адреса), а также внешние IP-адреса с ссылкой на админку. Ссылка Server Info должна была выдавать какой-то отчет о запрошенном сервере, но в реале не выдавала, хотя весь список был обозначен.

А вот самый интересный раздел назывался Database Tools. Ссылка Show Tables выдавала список всех таблиц выбранной базы, а при переходе на таблицу можно было увидеть перечень всех ее колонок.

Рис. 4. Таблицы в базе
Рис. 4. Таблицы в базе

>

Рис. 5. Колонки в таблице uni_reg
Рис. 5. Колонки в таблице uni_reg

Раздел Systems из интересного имел в себе только ссылку users, в которой находилась информация о текущих специалистах и уровень их доступа в систему. На рис. 6 показаны полномочия пользователя с паролем 1942.

Рис. 6. Суперадмин
Рис. 6. Суперадмин

Как видно, люди с большими полномочиями тоже люди и страдают от всех людских болезней. В данной конкретной ситуации это как минимум простой пароль, а возможно, и использование повторяющихся паролей. Ничто не ново под луной, и это не последний случай в моей (да и не только моей) практике.

Также во время просмотра админки мне посчастливилось найти еще пару инъекций, которые выводили записи из БД в нужном количестве, то есть сделать кривой дамп в разумное время было возможно, хотя и пришлось бы поплясать с бубном возле костра. Но, как известно, лень — двигатель прогресса, и этот вариант я оставил на потом. Через инъекцию была получена информация о серверах в сети (та самая, которую не захотел выводить скрипт из Server Info). Получив заведомо известные используемые диапазоны IP-адресов, я решил немного углубить свое знакомство с локальной сетью организации. Локальные IP-адреса принадлежали десятку сеток класса С. Nmap’a на сервере не оказалось, поэтому в /tmp был закинут перловый скрипт для поиска открытых портов. Очень хороший и шустрый скрипт, который также проверяет наличие работающих демонов на указанных портах. Опций минимум: -h — сканировать хост/хосты, -p — указать конкретный порт. Начинаем сканирование:

perl scan.pl -h 172.20.5.1-254 -p 3306

И так ко всем диапазонам. Параллельно с этим я все так же собирал информацию с сервера. При ручном осмотре был обнаружен файл dbBackup.pl в папке /home/webuser/bin/. И в нем черным по белому было указано:

my $user = 'Mybackup';
my $pass = 'cx5vfgb34';

Имя пользователя говорит само за себя — как правило, пользователи с именем, в корне которого есть repl или backup, имеют гораздо более высокие права и привилегии. Понимая это, я начал проверять эту пару на всех доступных мне MySQL-серверах. Хотелось получить еще доступ к базе ezine и таблице uni_reg. И вот на очередном сервере была найдена искомая база.

Рис. 7. Серверы с базами
Рис. 7. Серверы с базами

Запрос к information_schema.tables раскрыл, что таблица uni_reg содержала более 38К пользователей — совсем немало. На этой мажорной ноте, решив, что нашел уже немало серьезных брешей, я приостановил дальнейшее проникновение и сел писать отчет о найденных уязвимостях владельцам ресурса.

Заключение

Подводя итог этой поучительной истории, хочется отметить, что помогло мне при анализе, — то есть те моменты, которые ни в коем случае не рекомендуется повторять.

  1. Тестовый сервер. Он должен быть доступен только из локалки, никаких рабочих проектов. Дефолтные логин и пароль на серваке пустили меня внутрь и позволили залить шелл.
  2. Одинаковые пассы — позволяют увеличить радиус поражения, включая и рабочие проекты.
  3. Слабое разграничение прав при организации внутренней защиты. Можно сказать, фактическое отсутствие этой самой минимальной защиты позволило мне прочитать конфиги для подключения к БД, содержащей информацию обо ВСЕХ пользователях. То есть, получив минимальные права на тестовом сервере, я смог дотянуться до святая святых компании.

Если ты хочешь, чтобы твой ресурс был в безопасности, — никогда не повторяй перечисленных ошибок. Ведь ты сам прекрасно помнишь, кто учится на своих ошибках, а кто на чужих.

 

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    6 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии