Vulnhub - PwnLab:init の Write-Up

Description

Vulnhub靶机PwnLab:init的练习记录。整体难度不高,最终目的是拿到/root/flag.txt文件。

Gathering Information

首先找下靶机地址:

扫描一下靶机的开放端口和服务:

Game Start

先看下80端口的服务:

Login界面是一个看起来很简陋的登陆界面:

尝试对登录接口爆破和SQL注入均无结果。

但是针对界面的URL:http://172.16.83.142/?page=login和http://172.16.83.142/?page=upload的形式,猜测可能存在文件包含的问题。

结合nikto给出的信息:

/config.php文件存在可能泄露数据库的信息,但是直接访问是没有数据的。

接下来就尝试读取/config.php文件的内容,详细内容可参考这篇文章php伪协议实现命令执行的七种姿势。最终通过php://filter实现内容读取,这个技巧也是CTF中经常用到的。

最终payload是这样的:http://172.16.83.142/?page=php://filter/read=convert.base64-encode/resource=config(注意不用加.php后缀)

base64解码出来之后的结果中果然含有数据库的信息:

同样的方法我们可以获得login.php

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
<?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:

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');
}
}
}

?>

通过泄露的数据库账号密码可以通过root远程登录mysql数据库:

根据提示在Users表中找到了3个账号。

密码很明显是base64编码的,解码之后得到3对账户和密码:

  • kent/JWzXuBJJNy

  • mike/SIfdsTEn6I

  • kane/iSv5Ym2GRo

登录系统之后直接跳转到upload界面,允许上传文件。但是通过上面我们down下来的upload.php源码来看,上传文件是后端的白名单验证后缀,而且上传上去之后会改文件名再添加后缀。但是只是检查了imageinfo,那可以伪造一个文件头加后缀就可以了。

就在kali自带的php webshell里挑一个php-reverse-shell.php改一下就可以。

先加个文件头:

再把反连IP和端口改成自己的:

最后文件名加上.gif的后缀,就可以成功上传:

Hint

但是又出现了新的问题,我们没法访问这个图片……

在网上找了一些提示之后才想起来,我们下载了config.phplogin.phpupload.php3个源码文件,但是还有主页的源码没看。再次利用php伪协议读取主页源代码:

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
//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>

可以看到cookie里有个有趣的参数lang可以实现访问任意文件:

于是利用这个漏洞触发webshell反弹shell:

可以看到利用Burp发包之后kali就接收到里反弹的shell。通过下面的命令即可转换成交互式shell。

1
python -c '__import__("pty").spawn("/bin/bash")’

Exploring

现在我们已经拿到目标机器的shell,下一步就是寻找有价值的信息。在home下发现4个用户:

尝试切换到这几个用户,kent下什么也没有:

mike的密码不对:

kane目录下找到一个奇怪的文件msgmike

是个可执行文件且存在setuidsetgid。执行发现调用了cat命令:

接下来将cat命令换成bash

通过export PATH=.:$PATH命令修改一下系统路径PATH,再次运行msgmike就可以得到mike的bash:

回到mike的目录下,有个新的msg2root的程序,根据名字感觉是提权到root权限的东西:

但是看起来就是简单的将输入变成输出:

联想到PwnLab的名字,通过scp命令将这个程序传回本地,逆向分析一下:

msg2root逆向后的主函数伪代码如下:

其实是个很简单的程序,将输入写入到/root/message.txt中,然后system执行。那通过;截断就可以绕过了。

Finished

可以看到我们已经得到了root的权限,最后就是去根目录下读flag.txt文件了:

完结,撒花~~

文章作者: ColdSnap
文章链接: https://coldwave96.github.io/2020/10/22/PwnLab-init/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ColdSnap の Blog