Synology PAT/SPK ์•”ํ˜ธํ™” ์•„์นด์ด๋ธŒ ๋ณตํ˜ธํ™”

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ

๊ฐœ์š”

์—ฌ๋Ÿฌ Synology ์žฅ์น˜ (DSM/BSM NAS, BeeStation ๋“ฑ)๋Š” ์•”ํ˜ธํ™”๋œ PAT / SPK ์•„์นด์ด๋ธŒ๋กœ ํŽŒ์›จ์–ด ๋ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํŒจํ‚ค์ง€๋ฅผ ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์•„์นด์ด๋ธŒ๋Š” ๊ณต์‹ ์ถ”์ถœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋‚ด์žฅ๋œ ํ•˜๋“œ์ฝ”๋”ฉ๋œ ํ‚ค ๋•๋ถ„์— ๊ณต๊ฐœ ๋‹ค์šด๋กœ๋“œ ํŒŒ์ผ๋งŒ์œผ๋กœ ์˜คํ”„๋ผ์ธ์—์„œ ๋ณตํ˜ธํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๋Š” ์•”ํ˜ธํ™”๋œ ํ˜•์‹์ด ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹๊ณผ ๊ฐ ํŒจํ‚ค์ง€ ๋‚ด๋ถ€์— ์žˆ๋Š” ํ‰๋ฌธ TAR๋ฅผ ์™„์ „ํžˆ ๋ณต๊ตฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋‹จ๊ณ„๋ณ„๋กœ ๋ฌธ์„œํ™”ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ ˆ์ฐจ๋Š” Pwn2Own Ireland 2024 ๋™์•ˆ ์ˆ˜ํ–‰๋œ Synacktiv ์—ฐ๊ตฌ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฉฐ ์˜คํ”ˆ ์†Œ์Šค ๋„๊ตฌ synodecrypt์—์„œ ๊ตฌํ˜„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

โš ๏ธ ํ˜•์‹์€ *.pat (์‹œ์Šคํ…œ ์—…๋ฐ์ดํŠธ)์™€ *.spk (์• ํ”Œ๋ฆฌ์ผ€์ด์…˜) ์•„์นด์ด๋ธŒ ๋ชจ๋‘์— ๋Œ€ํ•ด ์ •ํ™•ํžˆ ๋™์ผํ•ฉ๋‹ˆ๋‹ค โ€“ ์„ ํƒ๋˜๋Š” ํ•˜๋“œ์ฝ”๋”ฉ๋œ ํ‚ค ์Œ๋งŒ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.


1. ์•„์นด์ด๋ธŒ ๊ฐ€์ ธ์˜ค๊ธฐ

ํŽŒ์›จ์–ด/์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์—…๋ฐ์ดํŠธ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ Synology์˜ ๊ณต๊ฐœ ํฌํ„ธ์—์„œ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

$ wget https://archive.synology.com/download/Os/BSM/BSM_BST150-4T_65374.pat

2. PAT ๊ตฌ์กฐ ๋คํ”„ํ•˜๊ธฐ (์„ ํƒ ์‚ฌํ•ญ)

*.pat ์ด๋ฏธ์ง€๋Š” ์—ฌ๋Ÿฌ ํŒŒ์ผ(๋ถ€ํŠธ ๋กœ๋”, ์ปค๋„, rootfs, ํŒจํ‚ค์ง€ ๋“ฑ)์„ ํฌํ•จํ•˜๋Š” cpio ๋ฒˆ๋“ค์ž…๋‹ˆ๋‹ค. ๋ฌด๋ฃŒ ์œ ํ‹ธ๋ฆฌํ‹ฐ patology๋Š” ํ•ด๋‹น ๋ž˜ํผ๋ฅผ ๊ฒ€์‚ฌํ•˜๋Š” ๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค:

$ python3 patology.py --dump -i BSM_BST150-4T_65374.pat
[โ€ฆ]
$ ls
DiskCompatibilityDB.tar  hda1.tgz  rd.bin  packages/  โ€ฆ

*.spk ํŒŒ์ผ์˜ ๊ฒฝ์šฐ 3๋‹จ๊ณ„๋กœ ๋ฐ”๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3. Synology ์ถ”์ถœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”์ถœ

์‹ค์ œ ๋ณตํ˜ธํ™” ๋กœ์ง์€ ๋‹ค์Œ์— ์žˆ์Šต๋‹ˆ๋‹ค:

  • /usr/syno/sbin/synoarchive โ†’ ๋ฉ”์ธ CLI ๋ž˜ํผ
  • /usr/lib/libsynopkg.so.1 โ†’ DSM UI์—์„œ ๋ž˜ํผ ํ˜ธ์ถœ
  • libsynocodesign.so โ†’ ์•”ํ˜ธํ™” ๊ตฌํ˜„ ํฌํ•จ

๋‘ ๋ฐ”์ด๋„ˆ๋ฆฌ๋Š” ์‹œ์Šคํ…œ rootfs (hda1.tgz) ๋ฐ ์••์ถ•๋œ init-rd (rd.bin)์— ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. PAT๋งŒ ์žˆ๋Š” ๊ฒฝ์šฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

# rd.bin is LZMA-compressed CPIO
$ lzcat rd.bin | cpio -id 2>/dev/null
$ file usr/lib/libsynocodesign.so
usr/lib/libsynocodesign.so: ELF 64-bit LSB shared object, ARM aarch64, โ€ฆ

4. ํ•˜๋“œ์ฝ”๋”ฉ๋œ ํ‚ค ๋ณต๊ตฌํ•˜๊ธฐ (get_keys)

libsynocodesign.so ๋‚ด๋ถ€์˜ get_keys(int keytype) ํ•จ์ˆ˜๋Š” ์š”์ฒญ๋œ ์•„์นด์ด๋ธŒ ํŒจ๋ฐ€๋ฆฌ์— ๋Œ€ํ•ด ๋‘ ๊ฐœ์˜ 128๋น„ํŠธ ์ „์—ญ ๋ณ€์ˆ˜๋ฅผ ๋‹จ์ˆœํžˆ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค:

case 0:            // PAT (system)
case 10:
case 11:
signature_key = qword_23A40;
master_key    = qword_23A68;
break;

case 3:            // SPK (applications)
signature_key = qword_23AE0;
master_key    = qword_23B08;
break;
  • signature_key โ†’ ์•„์นด์ด๋ธŒ ํ—ค๋”๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” Ed25519 ๊ณต๊ฐœ ํ‚ค.
  • master_key โ†’ ์•„์นด์ด๋ธŒ๋ณ„ ์•”ํ˜ธํ™” ํ‚ค๋ฅผ ํŒŒ์ƒํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๋ฃจํŠธ ํ‚ค.

๊ฐ DSM ์ฃผ์š” ๋ฒ„์ „๋งˆ๋‹ค ์ด ๋‘ ์ƒ์ˆ˜๋ฅผ ํ•œ ๋ฒˆ๋งŒ ๋คํ”„ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

5. ํ—ค๋” ๊ตฌ์กฐ ๋ฐ ์„œ๋ช… ๊ฒ€์ฆ

synoarchive_open() โ†’ support_format_synoarchive() โ†’ archive_read_support_format_synoarchive()๋Š” ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค:

  1. ๋งค์ง ์ฝ๊ธฐ (3 ๋ฐ”์ดํŠธ) 0xBFBAAD ๋˜๋Š” 0xADBEEF.
  2. ๋ฆฌํ‹€ ์—”๋””์•ˆ 32๋น„ํŠธ header_len ์ฝ๊ธฐ.
  3. header_len ๋ฐ”์ดํŠธ + ๋‹ค์Œ 0x40 ๋ฐ”์ดํŠธ Ed25519 ์„œ๋ช… ์ฝ๊ธฐ.
  4. crypto_sign_verify_detached()๊ฐ€ ์„ฑ๊ณตํ•  ๋•Œ๊นŒ์ง€ ๋ชจ๋“  ๋‚ด์žฅ ๊ณต๊ฐœ ํ‚ค๋ฅผ ๋ฐ˜๋ณตํ•ฉ๋‹ˆ๋‹ค.
  5. MessagePack์œผ๋กœ ํ—ค๋”๋ฅผ ๋””์ฝ”๋”ฉํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค:
[
data: bytes,
entries: [ [size: int, sha256: bytes], โ€ฆ ],
archive_description: bytes,
serial_number: [bytes],
not_valid_before: int
]

entries๋Š” libarchive๊ฐ€ ๊ฐ ํŒŒ์ผ์„ ๋ณตํ˜ธํ™”ํ•  ๋•Œ ๋ฌด๊ฒฐ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

6. ์•„์นด์ด๋ธŒ๋ณ„ ์„œ๋ธŒ ํ‚ค ์œ ๋„

MessagePack ํ—ค๋”์— ํฌํ•จ๋œ data ๋ธ”๋กญ์—์„œ:

  • subkey_id = ์˜คํ”„์…‹ 0x10์˜ ๋ฆฌํ‹€ ์—”๋””์•ˆ uint64
  • ctx = ์˜คํ”„์…‹ 0x18์˜ 7 ๋ฐ”์ดํŠธ

32๋ฐ”์ดํŠธ ์ŠคํŠธ๋ฆผ ํ‚ค๋Š” libsodium์„ ์‚ฌ์šฉํ•˜์—ฌ ์–ป์Šต๋‹ˆ๋‹ค:

crypto_kdf_derive_from_key(kdf_subkey, 32, subkey_id, ctx, master_key);

7. Synology์˜ ์ปค์Šคํ…€ libarchive ๋ฐฑ์—”๋“œ

Synology๋Š” ๋งค์ง์ด 0xADBEEF์ผ ๋•Œ ๊ฐ€์งœ โ€œtarโ€ ํ˜•์‹์„ ๋“ฑ๋กํ•˜๋Š” ํŒจ์น˜๋œ libarchive๋ฅผ ๋ฒˆ๋“ค๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:

register_format(
"tar", spk_bid, spk_options,
spk_read_header, spk_read_data, spk_read_data_skip,
NULL, spk_cleanup, NULL, NULL);

spk_read_header()

- Read 0x200 bytes
- nonce  = buf[0:0x18]
- cipher = buf[0x18:0x18+0x193]
- crypto_secretstream_xchacha20poly1305_init_pull(state, nonce, kdf_subkey)
- crypto_secretstream_xchacha20poly1305_pull(state, tar_hdr, โ€ฆ, cipher, 0x193)

๋ณตํ˜ธํ™”๋œ tar_hdr๋Š” ๊ณ ์ „์ ์ธ POSIX TAR ํ—ค๋”์ž…๋‹ˆ๋‹ค.

spk_read_data()

while (remaining > 0):
chunk_len = min(0x400000, remaining) + 0x11   # +tag
buf   = archive_read_ahead(chunk_len)
crypto_secretstream_xchacha20poly1305_pull(state, out, โ€ฆ, buf, chunk_len)
remaining -= chunk_len - 0x11

๊ฐ 0x18-byte nonce๋Š” ์•”ํ˜ธํ™”๋œ ์ฒญํฌ ์•ž์— ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  ํ•ญ๋ชฉ์ด ์ฒ˜๋ฆฌ๋˜๋ฉด libarchive๋Š” ํ‘œ์ค€ ๋„๊ตฌ๋กœ ์••์ถ• ํ•ด์ œํ•  ์ˆ˜ ์žˆ๋Š” ์™„๋ฒฝํ•˜๊ฒŒ ์œ ํšจํ•œ .tar ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

8. synodecrypt๋กœ ๋ชจ๋“  ๊ฒƒ์„ ๋ณตํ˜ธํ™”ํ•ฉ๋‹ˆ๋‹ค.

$ python3 synodecrypt.py SynologyPhotos-rtd1619b-1.7.0-0794.spk
[+] found matching keys (SPK)
[+] header signature verified
[+] 104 entries
[+] archive successfully decrypted โ†’ SynologyPhotos-rtd1619b-1.7.0-0794.tar

$ tar xf SynologyPhotos-rtd1619b-1.7.0-0794.tar

synodecrypt๋Š” PAT/SPK๋ฅผ ์ž๋™์œผ๋กœ ๊ฐ์ง€ํ•˜๊ณ , ์˜ฌ๋ฐ”๋ฅธ ํ‚ค๋ฅผ ๋กœ๋“œํ•˜๋ฉฐ, ์œ„์— ์„ค๋ช…๋œ ์ „์ฒด ์ฒด์ธ์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.

9. ์ผ๋ฐ˜์ ์ธ ํ•จ์ •

  • signature_key์™€ master_key๋ฅผ ๊ตํ™˜ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค โ€“ ์ด๋“ค์€ ์„œ๋กœ ๋‹ค๋ฅธ ๋ชฉ์ ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
  • nonce๋Š” ๋ชจ๋“  ๋ธ”๋ก(ํ—ค๋” ๋ฐ ๋ฐ์ดํ„ฐ)์˜ ์•”ํ˜ธ๋ฌธ ์•ž์— ์œ„์น˜ํ•ฉ๋‹ˆ๋‹ค.
  • ์ตœ๋Œ€ ์•”ํ˜ธํ™” ์ฒญํฌ ํฌ๊ธฐ๋Š” 0x400000 + 0x11(libsodium ํƒœ๊ทธ)์ž…๋‹ˆ๋‹ค.
  • ํ•œ DSM ์„ธ๋Œ€์— ๋Œ€ํ•ด ์ƒ์„ฑ๋œ ์•„์นด์ด๋ธŒ๋Š” ๋‹ค์Œ ๋ฆด๋ฆฌ์Šค์—์„œ ๋‹ค๋ฅธ ํ•˜๋“œ์ฝ”๋”ฉ๋œ ํ‚ค๋กœ ์ „ํ™˜๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

10. ์ถ”๊ฐ€ ๋„๊ตฌ

  • patology โ€“ PAT ์•„์นด์ด๋ธŒ๋ฅผ ํŒŒ์‹ฑ/๋คํ”„ํ•ฉ๋‹ˆ๋‹ค.
  • synodecrypt โ€“ PAT/SPK/๊ธฐํƒ€๋ฅผ ๋ณตํ˜ธํ™”ํ•ฉ๋‹ˆ๋‹ค.
  • libsodium โ€“ XChaCha20-Poly1305 secretstream์˜ ์ฐธ์กฐ ๊ตฌํ˜„์ž…๋‹ˆ๋‹ค.
  • msgpack โ€“ ํ—ค๋” ์ง๋ ฌํ™”.

์ฐธ๊ณ  ๋ฌธํ—Œ

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ