浅析无参数RCE

发布于 2021-08-06  67 次阅读


什么是无参数RCE

if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp']){
eval($_GET['exp']);
}

如上,只使用函数,且函数不能带有参数,这里有种种限制:比如我们选择的函数必须能接受其括号内函数的返回值;使用的函数规定必须参数为空或者为一个参数。比如:

a();
a(b());
a(b(c()));

无参数RCE中的正则

正则可以分为三个部分:

1.  `[a-z,_]+\( 直到递归前面可以看作一个匹配整体,用来匹配所有小写字母下划线和左括号`
2.  `(?R)? 递归部分看作一个匹配整体,效果是用来递归匹配`
3.  `\) 递归后面的看作一个匹配整体,用来匹配右括号`
a( //匹配上面第一个匹配整体,然后进入第一次递归
b( //匹配上面第一个匹配整体,进入第二次递归
c( //匹配上面第一个匹配整体,进入第三次递归
//没有匹配第一个匹配整体,递归停止
) //匹配第二次递归剩下的表达式,即第三个匹配的整体\),
) //匹配第一次递归剩下的表达式,即\),
) //匹配原表达式剩下的表达式,即\),

*(?R),(?R)?,(?R),(?R)+的区别

  1. (?R) , (?R)+ 这两个表达式是匹配不到东西的,因为每次匹配的时候都会至少运行一次递归,无法终止,所以匹配不到任何东西。
  2. (?R)?,递归0次或1次,非贪婪,只能匹配a(b(c()))这种一层套一个函数的。
image-20210202223136407
image-20210202223219488
  1. (?R)*,递归0次或多次,贪婪,可以匹配a(b(c()d()))
image-20210202223246625

常用函数

数组操作

array_flip():

image-20210202223946462

array_rand:

image-20210202223758505

array_reverse:

image-20210202224226089

数组指针相关操作

  • current() - 返回数组中的当前指针的值,默认是数组第一个元素,别名pos
  • end() - 将数组的内部指针指向最后一个单元
  • key() - 从关联数组中取得键名
  • each() - 返回数组中当前的键/值对并将数组指针向前移动一步
  • prev() - 将数组的内部指针倒回一位
  • reset() - 将数组的内部指针指向第一个单元
  • next() - 将数组中的内部指针向前移动一位

其他函数

  • localeconv() 返回一包含本地数字及货币格式信息的数组。而数组第一项就是”.”
  • get_defined_vars()此函数返回一个包含所有已定义变量列表的多维数组,这些变量包括环境变量、服务器变量和用户定义的变量。
  • getenv,获取一个环境变量的值

文件相关操作函数

  • file_get_contents()将整个文件读入一个字符串
  • readfile()读取文件并写入到输出缓冲。
  • highlight_file()语法高亮显示一个文件
  • scandir( . ), 返回一个数组,包含当前目录下的文件和目录
  • getcwd()取得当前工作目录。
  • chdir($directory),将 PHP 的当前目录改为 directory。