Init. Commit
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
<h1 align="center">TagPreview</h1>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/category-Crypto-blueviolet" alt="Crypto"/>
|
||||
<img src="https://img.shields.io/badge/difficulty-easy-brightgreen" alt="easy"/>
|
||||
</p>
|
||||
|
||||
Сервис хранит запечатанную заметку и умеет проверять её целостность. При успешной проверке он подтверждает приём, но текст не показывает. Для отклонённых записей сервис возвращает поле `preview`. Проверяем его содержимое.
|
||||
|
||||
## Решение
|
||||
|
||||
Забираем исходную запись:
|
||||
|
||||
```bash
|
||||
curl -sS http://<host>:31359/sealed-note -o note.bin
|
||||
```
|
||||
|
||||
Публичный клиент на неизменённой записи получает `status=accepted` без plaintext:
|
||||
|
||||
```bash
|
||||
python3 public/client.py http://<host>:31359
|
||||
```
|
||||
|
||||
В `inspect_record()` сначала вычисляется открытый текст, затем проверяется authentication tag. Сама расшифровка до проверки ещё не раскрывает данные клиенту. Ошибка находится в ветке отказа. При несовпадении тега функция возвращает эти байты в поле `preview`.
|
||||
|
||||
Последние 16 байт записи — тег. Меняем один его байт, не трогая шифротекст, чтобы расшифровка осталась прежней, а проверка провалилась:
|
||||
|
||||
```python
|
||||
from pathlib import Path
|
||||
|
||||
record = bytearray(Path("note.bin").read_bytes())
|
||||
record[-1] ^= 1
|
||||
Path("tampered.bin").write_bytes(record)
|
||||
```
|
||||
|
||||
Отправляем подготовленный `tampered.bin` в `POST /inspect` с `Content-Type: application/octet-stream`.
|
||||
|
||||
```bash
|
||||
curl -sS --data-binary @tampered.bin \
|
||||
-H 'Content-Type: application/octet-stream' \
|
||||
'http://<host>:31359/inspect'
|
||||
```
|
||||
|
||||
При несовпадении тега обработчик возвращает открытый текст вместе с флагом в поле `preview`. Одной испорченной записи достаточно, поскольку утечка происходит непосредственно в обработчике ошибки.
|
||||
|
||||
> Расшифрованные байты до проверки тега нельзя отдавать вызывающему коду. Здесь проверка обнаружила повреждение, но обработчик ошибки всё равно раскрыл содержимое заметки.
|
||||
|
||||
[Солвер](solve/solve.py).
|
||||
|
||||
## Флаг
|
||||
|
||||
`caplag{tag_failure_previewed_the_plaintext}`
|
||||
Reference in New Issue
Block a user