Vulnhub-Overflow
文章目录
基本介绍
靶机地址
https://www.vulnhub.com/entry/overflow-1,300/
目标
获取两个 flag,user / root。
环境
名称 | 介绍 |
---|---|
主机 | Manjaro 20.1 |
虚拟化软件 | Virtualbox 6.1.12 |
靶机网络 | Host-only (vboxnet0) |
kali in docker | 2020.3 |
Ubuntu in docker | 16.04.7 LTS |
工具版本
名称 | 版本 |
---|---|
arp-scan | 1.9.7 |
Nmap | 7.80 |
Ghidra | 9.1 |
IDA Pro | 7.3 |
信息收集
获取 IP 地址
使用 arp-scan 对 vboxnet0 接口进行二层扫描,可知靶机的地址为 192.168.56.121。
{% blockquote %}
|
|
arp-scan -I vboxnet0 –localnet Interface: vboxnet0, type: EN10MB, MAC: 0a:00:27:00:00:00, IPv4: 192.168.56.1 Starting arp-scan 1.9.7 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.56.100 08:00:27:14:c7:34 PCS Systemtechnik GmbH 192.168.56.121 08:00:27:37:66:a9 PCS Systemtechnik GmbH
2 packets received by filter, 0 packets dropped by kernel Ending arp-scan 1.9.7: 256 hosts scanned in 2.039 seconds (125.55 hosts/sec). 2 responded {% endblockquote %}
端口扫描
使用半连接方式对靶机进行全 TCP 端口扫描,该靶机只开放了两个端口:
{% blockquote %}
|
|
Starting Nmap 7.80 ( https://nmap.org ) at 2020-08-26 04:33 UTC Nmap scan report for 192.168.56.121 Host is up (0.00014s latency). Not shown: 65533 closed ports PORT STATE SERVICE 80/tcp open http 1337/tcp open waste MAC Address: 08:00:27:37:66:A9 (Oracle VirtualBox virtual NIC)
Nmap done: 1 IP address (1 host up) scanned in 1.14 seconds {% endblockquote %}
服务枚举
继续使用 Nmap 进行服务枚举,可见 80 端口上运行着 apache;而另一个端口就比较奇怪了,并看不出是什么。
{% blockquote %}
|
|
Starting Nmap 7.80 ( https://nmap.org ) at 2020-08-26 04:34 UTC Nmap scan report for 192.168.56.121 Host is up (0.00038s latency).
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.25 ((Debian))
|_http-server-header: Apache/2.4.25 (Debian)
|http-title: Site doesn’t have a title (text/html).
1337/tcp open waste?
| fingerprint-strings:
| DNSStatusRequestTCP, DNSVersionBindReqTCP, FourOhFourRequest, GenericLines, GetRequest, HTTPOptions, Help, JavaRMI, Kerberos, LANDesk-RC, LDAPBindReq, LDAPSearchReq, LPDString, NCP, NotesRPC, RPCCheck, RTSPRequest, SIPOptions, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServer, TerminalServerCookie, WMSRequest, X11Probe, afp, giop, ms-sql-s, oracle-tns:
| COMMAND : TRY HARDER!
| NULL:
| COMMAND :
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port1337-TCP:V=7.80%I=7%D=8/26%Time=5F45E660%P=x86_64-pc-linux-gnu%r(NU
SF:LL,A,“COMMAND\x20:\x20”)%r(GenericLines,16,“COMMAND\x20:\x20TRY\x20HARD
SF:ER!\n”)%r(GetRequest,16,“COMMAND\x20:\x20TRY\x20HARDER!\n”)%r(HTTPOptio
SF:ns,16,“COMMAND\x20:\x20TRY\x20HARDER!\n”)%r(RTSPRequest,16,“COMMAND\x20
SF::\x20TRY\x20HARDER!\n”)%r(RPCCheck,16,“COMMAND\x20:\x20TRY\x20HARDER!\n
SF:")%r(DNSVersionBindReqTCP,16,“COMMAND\x20:\x20TRY\x20HARDER!\n”)%r(DNSS
SF:tatusRequestTCP,16,“COMMAND\x20:\x20TRY\x20HARDER!\n”)%r(Help,16,“COMMA
SF:ND\x20:\x20TRY\x20HARDER!\n”)%r(SSLSessionReq,16,“COMMAND\x20:\x20TRY\x
SF:20HARDER!\n”)%r(TerminalServerCookie,16,“COMMAND\x20:\x20TRY\x20HARDER!
SF:\n”)%r(TLSSessionReq,16,“COMMAND\x20:\x20TRY\x20HARDER!\n”)%r(Kerberos,
SF:16,“COMMAND\x20:\x20TRY\x20HARDER!\n”)%r(SMBProgNeg,16,“COMMAND\x20:\x2
SF:0TRY\x20HARDER!\n”)%r(X11Probe,16,“COMMAND\x20:\x20TRY\x20HARDER!\n”)%r
SF:(FourOhFourRequest,16,“COMMAND\x20:\x20TRY\x20HARDER!\n”)%r(LPDString,1
SF:6,“COMMAND\x20:\x20TRY\x20HARDER!\n”)%r(LDAPSearchReq,16,“COMMAND\x20:
SF:x20TRY\x20HARDER!\n”)%r(LDAPBindReq,16,“COMMAND\x20:\x20TRY\x20HARDER!
SF:n”)%r(SIPOptions,16,“COMMAND\x20:\x20TRY\x20HARDER!\n”)%r(LANDesk-RC,16
SF:,“COMMAND\x20:\x20TRY\x20HARDER!\n”)%r(TerminalServer,16,“COMMAND\x20:
SF:x20TRY\x20HARDER!\n”)%r(NCP,16,“COMMAND\x20:\x20TRY\x20HARDER!\n”)%r(No
SF:tesRPC,16,“COMMAND\x20:\x20TRY\x20HARDER!\n”)%r(JavaRMI,16,“COMMAND\x20
SF::\x20TRY\x20HARDER!\n”)%r(WMSRequest,16,“COMMAND\x20:\x20TRY\x20HARDER!
SF:\n”)%r(oracle-tns,16,“COMMAND\x20:\x20TRY\x20HARDER!\n”)%r(ms-sql-s,16,
SF:“COMMAND\x20:\x20TRY\x20HARDER!\n”)%r(afp,16,“COMMAND\x20:\x20TRY\x20HA
SF:RDER!\n”)%r(giop,16,“COMMAND\x20:\x20TRY\x20HARDER!\n”);
MAC Address: 08:00:27:37:66:A9 (Oracle VirtualBox virtual NIC)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 158.02 seconds {% endblockquote %}
访问网页
在浏览器中访问 http://192.168.56.121,页面中只有一句话:
相当简洁明了,得到了 1337 端口上运行的程序 vulnserver,不用继续枚举 Web 了。
Vulnserver 分析
文件信息
首先查看这个文件的基本信息:
{% blockquote %}
|
|
vulnserver: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=22c480f83765e0d4ca860fe9469074ba8f17295c, not stripped {% endblockquote %}
可见是一个 32 位的动态链接 ELF 文件,没有剥离调试信息,继续查看防护措施:
{% blockquote %}
|
|
{% endblockquote %}
没有任何防护!
静态分析
这里我是用 Ghidra 来进行反汇编和反编译,直接看 main 函数:
|
|
从以上的代码可知该程序创建了一个 TCP 套接字,监听本地的 1337(0x539) 端口,最多能同时建立 10 条连接。接着分析:
|
|
该程序使用了 fork 的方式来处理连接的请求,对于每个连接,先读取最多 1024 个字节(0x400),如果以 “OVERFLOW “(注意有一个空格)打头,则调用 handleCommand 函数进一步处理。handle 函数如下:
|
|
很简单,对之前接受的内容直接调用 strcpy 复制到局部的 buffer 中,而这个 buffer 的大小只有 36 字节(还有 4 字节保存了 ebx 寄存器)。很容易看出来只要发送的数据长度超过 44 (0x2c) 就会覆盖到 eip。
动态调试
简单介绍一下我的调试环境,由于这是一个网络程序,直接在宿主机上调试意味着端口会暴露在整个局域网上,这是很不安全的。当然可以配置防火墙策略来阻止其它主机的访问,但我选择搭建隔离的调试环境。多年的折腾经验下来最终还是使用了 docker,使用了 ubuntu/ubuntu:16.04 的镜像,网络为默认的桥接网络,调试容器的 IP 为 172.17.0.2,主机的 IP 为 172.17.0.1。在容器内安装了 gdb,gdb-peda;当然,tmux 不能少。
首先运行 vulnserver,接着 gdb-peda attach 上去:
我对 handleCommand 函数下断点,命令为:
|
|
但是仅仅这样是断不下来的,因为 handleCommand 函数由 fork 出的子进程处理,但是我 attach 的是父进程,可以在 gdb 内进行以下设置:
|
|
控制 EIP
这样 gdb 在 fork 操作之后就会去跟踪子进程,之后输入 “c”,让程序继续运行。这里尝试构造一个刚好能够溢出返回地址从而控制 EIP 的 payload,预计 EIP 会被写入 0x42424242:
{% blockquote %}
|
|
OVERFLOW AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB {% endblockquote %}
同时发送:
|
|
可以发现 gdb 这边成功断下来了,按 “c” 继续执行,成功控制 EIP:
执行 shellcode
由于该程序没有开启 NX 防护,故栈是可执行的,所以后续将在栈上写入 shellcode 并执行 shellcode。这里 ESP 正好指向写入的位置,首先搜寻 jmp esp 作为跳板:
{% blockquote %}
|
|
Gadgets information
0x0804903b : jmp 0x8049020 0x08049260 : jmp 0x80491f0 0x080493c0 : jmp 0x80493d4 0x0804929a : jmp esp
Unique gadgets found: 4 {% endblockquote %}
恰好可以找到,地址为 0x0804929a。
接着使用 msfvenom 生成 shellcode,这里我选用了 linux/x86/meterpreter/reverse_tcp:
{% blockquote %}
|
|
Found 1 compatible encoders Attempting to encode payload with 1 iterations of x86/shikata_ga_nai x86/shikata_ga_nai succeeded with size 150 (iteration=0) x86/shikata_ga_nai chosen with final size 150 Payload size: 150 bytes Final size of python file: 743 bytes
|
|
{% endblockquote %}
最终的 exploit 如下:
|
|
打开 msfconsole 进行侦听,成功连接,将以上 exploit 的 IP 更换为靶机即可:
成功获得 user.txt,可见系统的版本很新,看内核版本应该是 debian 9,实际验证确实是。搜索靶机上的 SUID 文件,可以发现有 printauthlog,将该文件下载到本地进行分析。
printauthlog 分析
同样是一个 32 位动态链接的 ELF 文件,但是开了 NX 防护。Ghidra 显示栈中的字符串实在是不太行,这里便使用 ida pro 进行反编译。
静态分析
main 函数真的很简单:
|
|
checkPassword 逻辑:
|
|
也是 strcpy 使用不当直接栈溢出。这里直接控制 checkPassword 函数的返回地址即可,由于 NX 的缘故不能在栈上直接写 shellcode 了。但是该程序中有 system 函数的地址,只需要将返回地址改成 system 的地址,然后控制其参数即可。
这里使用了一个技巧叫做命令劫持,即自行创建可执行程序加修改 PATH 来劫持不以 “/” 开头的命令,这里我使用 “puts” 的地址作为 system 函数的参数,puts.c 的内容如下:
|
|
本地编译好得到 puts,上传到靶机。最终构造的 payload 如下,其中 0x08049060 为 system 的地址,0xdeadbeef 只是填充,0x080482c5 指向 “puts\x00”。为了方便,将内容保存为文件 haha,并上传到靶机。
|
|
最终在靶机上执行以下命令:
|
|
成功获得 root 权限,可见 root.txt。
文章作者 Josephine
上次更新 2020-08-30