UPD 23/11/11: пока только описание WEB270 The Kirovsky Plant, CRYPTO170/190 METRO1/2, WEB100 The State Hermitage Museum

Совсем скоро откроет двери долгожданная конференция ZeroNights, где впервые в России в одном зале соберутся западные и отечественные эксперты ИБ. Именно эксперты, а не маркетологи, менеждеры, руководители и прочие важые люди.

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

Прежде всего, отмечу плюсы и минусы организационной работы:

+ Впервые представлены задания на соц. инжерению (голосовое скайп общение и ICQ)

+ Множество заданий без ярковыраженного акцента на безопасность веб-приложений

+ Максимально приближенные к реальной жизни задания (поэтому и брута было так много)

- Не было объявлено точной даты окончания квеста заранее

- Соц. инженереия работала не 24/7 (что вполне себе отвечает реальной жизни)

- Не было ценных призов (нормальная практика всех анонсов разыгрывать только инвайты)

Не затягивая больше, перейду к описанию самих конкурсных заданий.

Описывать буду в порядке убывания сложности.

1. WEB270. The Kirovsky Plant (https://hackquest.zeronights.org/missions/kirovsky.php).

Задание расположено на примечательном месте – Кировский завод, где уже несколько раз проходил СС.

Первый этап – найти исходный код, ищется без труда с помощью логики и эрудиции – по адресу /kirovsky/auth.inc:
<?php
class auth {
public $attempt;
public function getRole($login,$pass){
if($login==='4DM1N' && $pass==='pa55w0rd'){
return true;
}else{
return false;
}
}
public function __destruct(){
buildXML($this->attempt);
}
}
class failed {
public $failed_count;
?>

Как видим, доступны логин/пароль и некий объект auth, с параметром attempt, который попадает в функцию buildXML(), исходника которой у нас уже нет. Вводим логин/пароль из исходника и радостно понимаем, что задание несколько обширнее, чем просто поиск файла. После авторизации в параметр $_COOKIE['admin_data_asdgwugq7gw7er6wqge7riqwgrqwe87or'] попадает значение 10.

Меняя это значение на 10-1, и проверяя затем 10a, понимаем, что теперь имеем дело с внедрением операторов СУБД, осложненного двумя факторами: во-первых одинарные кавычки вырезаются, во-вторых, внедрение полностью слепое (без вывода ошибок и самих данных в HTTP-ответе).

Использовалась СУБД SQLite (и в остальных квестах тоже, кстати), поэтому единственным возможным способом получить данные быол использование Time-based техники. Примеров оных под SQLite нет, на что и был расчет. Тут каждый придумывал сам, смысл только в том, чтобы построить конструкцию CASE WHEN THEN ELSE с логическим условием, которое вызывает отработку тормозящей функции/конструкции, когда результат проверки логики положительный/отрицательный.

Долго ли, коротко ли, получаем записи data из admins, которые имеют следующий вид:

i:10

Понимаем, что они проходят десериализацию и проводим вторую инъекция так, чтобы возвращаемое значение содержало нужным нам объект. Каким может быть этот объект? Только auth с параметром attempt, больше ведь ничего не доступно в исходниках.

После десериализации строка из attempt идет на вход XML парсерсу. Уязвимостей XML не много, собственно на серверной стороне можно набеятся только на XXE. Пробуем ее и о приближаемся к победе. Уязвимость дает чтение локальных файлов из директории ./kirovsky/.

O:4:”auth”:1:{s:7:”attempt”;s:62:”<!DOCTYPE asd [<!ENTITY dsa SYSTEM "./kirovsky/config.php">]>”}

Только через инъекцию без одинарных кавычек так просто не просунуть двойные. Надо использовать Escape chars и конкатенацию, ну это уже лирика.

Читаем сначала config.php, затем flag.blabla-antibrute.php, имя которого лежит в конфиге.

Все, флаг получен %)

2. CRYPTO170. The Subway (https://hackquest.zeronights.org/missions/metro.php).

Задание не очень-то на криптографию, скорее на общее понимание форматов и смекалку.
Имеем два билета на фотограциях и два дампа их электронного содержимого.
Прежде всего смотрим что у нас есть из информации на картинках – номер билета, дата и время продажи.
Ясно, что надо подделывать дату.
Начинаем битфлип и быстро получаем флаг (если проходите в первый деь публикации задания).
Если не в первый день публикации задания, то начинаем брутить по байту и чуть дольше получаем флаг.

3. CRYPTO190. Metro#2 (https://hackquest.zeronights.org/missions/metro2.php).

Работаем с билетами первого метро. Чтобы пройти второе надо понять их формат полностью.
Когда узнали где лежит дата, можем без труда понять как она храниться  - номер дня от начала года.
По той же логике находим номер билета (4 байта без ведущего нуля) и его ключ.
После этого понимаем, что 12 байт данных билетов в обоих метро ксорятся нехитрым ключем – METRO, то есть METROMETROME, учитывая блоки.
Зная что должно быть в дате ксорим ее с дампом и понимаем ключ шифрования.
В конце, как водится, стоит контрольная сумма, в первом метро она не мешает получить флаг (ошибка выдается, но и флаг тоже) и не ксорится с ключем. Второе метро отличается только тем, что там контр. сумма ксорится и проверяется, в случае, если не сходится, то и флаг не выдается.
Проверяем crc32  от первых 12 байт и смотрим что вышло, а затем смотрим что в последний 4 байтах – таже самая CRC32, только без старшего разряда. Все, контрольная сумма разгадалана.
Считаем CRC32 от 12 байт билета второго метро, ксорим с тем, что там записано в последних 4 байтах и понимаем ключ для контр. суммы билетов второго метро – ключ получается HASH.
Теперь все разгадано – тупо сдвигаем номер билета сильно вперед, дату на текущую, генерим билет, ксорим данные, считаем CRC32, ксорим ее, отправляем, получаем флаг.
ВУАЛЯ =) Кстати, формат билетов взят с реальных пропусков, которые мне доводилось видеть.

3. WEB100. The State Hermitage Museum (https://hackquest.zeronights.org/missions/hermitage.php).

Самое тугое по прохождению задание, с точки зрения логов =)

Ничего сложного тут нет. Загружается картинка, и дано описание, что это должна быть фотография Эрмитажа. Ну как скрипт может проверять фотографию на дислокацию? Конечно, только по EXIF тэгам с координатами.

Когда отправялется такая картинка, скрипт выдает сообщение: “Can not find photo location in database :( “, что явно намекает на СУБД и внедрение операторов. Создаем картинку с кавычкой в координатах и видим, как все радостно падает. Дальше – дело техники.

Редактирование EXIF метаданных – излюбленный способ хакеров снабжать картинки полехной нагрузкой в виде шеллов для проведения RCE через LFI при полноценной валидации картинки графическими библиотеками.

Уязвимый участок кода был дан в подсказке в Твиттере, вот он:
$exif = exif_read_data($_FILES['photo']['tmp_name'],"GPS");
if(@$exif['GPSLatitude'] && @$exif['GPSLongitude']){
if(is_array($exif['GPSLatitude'])){
$lat = implode(" ",$exif['GPSLatitude']);
}else{$lat = $exif['GPSLatitude'];}
if(is_array($exif['GPSLongitude'])){
$lon = implode(" ",$exif['GPSLongitude']);
}else{$lon = $exif['GPSLongitude'];}
$res = $db->query("select id,descr from objects where id in
(select object_id from object_locations where latitude='$lat' and longitude='$lon')
");
$row = $res->fetchArray();
if($row){
echo "Upload OK. Thank you! Location: {$row['descr']}";
}else{
echo "Can not find photo location in database :( ";
}
}else{
echo "Can not verify that this photo of the Hermitage!";
}

Как видим, не сложное 100 балльное задание.