伪全局:

什么是伪全局?简单的来说就是自动注册变量,将用户输入的GET POST等自动注册为PHP变量就是伪全局:

<?php

foreach($_REQUEST as $key=>$value)
{
    $$key=$value;
}
echo $test;
?>

QQ截图20200706182141.png

伪全局默认会接受来自以下几种超全局变量:

  1. GET
  2. POST
  3. FILES
  4. COOKIE

FILES:

当PHP使用FILES来获取变量时会自动创建tmp文件:

<?php

var_dump($_FILES['file']);

?>

返回:

array(1) { ["file"]=> array(5) { ["name"]=> string(36) "QQ截图20200706182141.png" ["type"]=> string(9) "image/png" ["tmp_name"]=> string(22) "C:\Windows\phpE8C9.tmp" ["error"]=> int(0) ["size"]=> int(3614) } }

众所周知,php会自动删除临时文件,但是他是在什么时候删除?一般情况下是在PHP执行结束时删除。

<?php

var_dump($_FILES);
sleep(20);

?>

QQ截图20200706182141.png

伪全局+FILES:

当目标使用了伪全局,那么我们就不用寻找调用了FILES的地方了:

<?php
foreach($_REQUEST as $key=>$value)
{
    $$key=$value;
}
var_dump($test);
sleep(20);
?>

如图:

QQ截图20200706182141.png

获取文件名:

如何获取到tmp的文件名?我们需要找一个输出了未初始化变量的地方,来进行输出我们的tmp,在这之前需要开启register_globals,上面的伪全局代码只是为了方便理解:

<?php
echo $test;
?>

这时候当我们上传的时候就会自动打印出tmp的地址:

C:\Users\root>curl http://127.0.0.1/o.php -F test=@C:\Users\root\Desktop\1.png
C:\Windows\php71C3.tmp

RCE:

到此为止,需要考虑的就只有如何在目标删除之前包含tmp文件了。思考一个问题,如果说服务器对客户端返回数据过大,不能一次性全部取回来,那么服务端会怎么做?没错,他会分多次取出数据。

<?php
$a = "xxxxx";
while(true){
    echo $a;
}
?>

从下图可以看出目标一直在向客户端返回数据,并且浏览器也在持续输出数据。而POST_DATA在PHP中是100MB的大小。只要POST的数据够大,那么我就一定可以在文件删除之前包含成功。

1.png