php命令执行函数
preg_match的/e模式
preg_match(pattern, 替换成的字符串, str)
当pattern中采用了/ / ..e模式时,每当str中匹配到pattern,就会把参数2当做代码执行。
- 参数2可控 —> 直接执行命令
- 参数2固定格式,如
1 |
|
1 |
|
\\1
是正则表达式中的第一个捕获项,由于表达式是(\S*),$str均被匹配,因此
执行的是strtolower("${getFlag()}")
接下来回答以下几个问题
Q1: 为什么不使用.*匹配
A: 以下这些字符作为变量名时,会被替换成’_’,其中就包括了字符’.’
Q2: 为什么要用${getFlag()}而不用getFlag()?
A: 因为如果用后者,那么将执行strtolower("getFlag()")
,其中getFlag()只是普通的字符串.而执行strtolower("${getFlag()}")
, 其中${}的格式是可变变量
,也就是会先自动解析{}中的变量,然后再把它作为变量名.显然$flag{…}是未定义的变量,也就是null.所以得到flag依赖于getFlag()函数中将flag打印出来
Q3: 为什么不能直接url?\S*=${system('ls')}
?
A: 经测试会报错 unexpected “ls”
2025/3/10:
传递的参数是字符串,'
和"
也不例外, 因此'
变认为是一个常量字符串,
传递url?\S*=${system('ls')}
时, 执行的是strtolower("${system(\'ls\')}")
, 也就是说'
会被转义, 因此会报syntax error, unexpected '
和网页上的报错一致
终于…
可能与'strtolower("\\1")'
中把'
和"
都用掉了有关系,导致
$str这个参数不能出现引号. ==> nope
奇怪的是url?\S*=${system(ls)}
意外的可以运行
但是ls /
又不能运行, … 暂时不深究