Files
Serdtse-Sysoly/qualifiers/sealtail-crypto-easy/WRITEUP.md
T
2026-09-17 00:50:07 +03:00

2.9 KiB

SealTail

Crypto easy

Релизная очередь принимает release.capsule: заголовок, RSA-подпись и команды в TLV-формате. В заголовке есть signed_len — длина подписанной части. Проверяющий использует именно её, а очередь после успешной проверки разбирает весь payload до конца файла.

Решение

Сначала прогоняем исходную капсулу через публичный verifier:

python3 public/verify_capsule.py public/release.capsule

Он показывает signature_valid=True, payload_len=181, signed_len=181, unsigned_tail_len=0. Пока подпись покрывает весь payload, неподписанного хвоста нет.

Открываем FORMAT.md. Для экспорта карантинного ключа предусмотрен тег 0x42 EXPORT_QUARANTINE_KEY. TLV-запись состоит из байта тега, двух байт длины в big-endian и значения. Дописываем такую команду в конец капсулы:

from pathlib import Path

value = (b"lane=quarantine\nrequestor=release-audit\n"
         b"reason=post-signature-tail-check\n")
tail = bytes([0x42]) + len(value).to_bytes(2, "big") + value
original = Path("public/release.capsule").read_bytes()
Path("modified.capsule").write_bytes(original + tail)

Подписанные байты и signed_len остались прежними. Проверяем модифицированный файл той же утилитой. Значение unsigned_tail_len должно стать больше нуля, а signature_valid остаться True.

python3 public/verify_capsule.py modified.capsule

Отправляем капсулу в очередь:

curl -sS --data-binary @modified.capsule \
  -H 'Content-Type: application/octet-stream' \
  http://<host>:31337/submit

RSA-проверка принимает исходный префикс, затем TLV-парсер доходит до добавленной неподписанной команды и возвращает ключ с флагом.

Подпись подтверждает только те байты, которые в неё включили. Если после проверки исполнять ещё и неподписанный хвост, целостность всего релиза она уже не гарантирует.

Солвер.

Флаг

caplag{signed_prefix_is_not_a_release}