做网站保存什么格式最好,网站编辑器,做网站的那些高清图上哪里找,云南网网站什么是无参数RCE#xff1f; 无参rce#xff0c;就是说在无法传入参数的情况下#xff0c;仅仅依靠传入没有参数的函数套娃就可以达到命令执行的效果 核心代码 if(; preg_replace(/[^\W]\((?R)?\)/, , $_GET[code])) { eval($_GET[code]); } 这段代码的核心就是只…什么是无参数RCE 无参rce就是说在无法传入参数的情况下仅仅依靠传入没有参数的函数套娃就可以达到命令执行的效果 核心代码 if(; preg_replace(/[^\W]\((?R)?\)/, , $_GET[code])) { eval($_GET[code]); } 这段代码的核心就是只允许函数而不允许函数中的参数就是说传进去的值是一个字符串接一个()那么这个字符串就会被替换为空如果替换后只剩下;那么这段代码就会被eval执行。
而且因为这个正则表达式是递归调用的所以说像a(b(c()));第一次匹配后就还剩下a(b());第二次匹配后就还剩a();第三次匹配后就还剩;了所以说这一串a(b(c()))就会被eval执行但相反像a(b(111));这种存在参数的就不行因为无论正则匹配多少次它的参数总是存在的。
那假如遇到这种情况我们就只能使用没有参数的php函数。
没有参数的php函数
getallheaders()
这个函数的作用是获取http所有的头部信息也就是headers然后我们可以用var_dump把它打印出来但这个有个限制条件就是必须在apache的环境下可以使用其它环境都是用不了的
那我们用phpstudy搭建一个网站看看
代码如下
?php
highlight_file(__FILE__);
if(isset($_GET[code])){
if(; preg_replace(/[^\W]\((?R)?\)/, , $_GET[code])) { eval($_GET[code]);}
elsedie(nonono);}
elseecho(please input code);
? 可以看到所有的头部信息都已经作为了一个数组打印了出来 在实际的运用中我们肯定不需要这么多条不然它到底执行哪一条呢
所以我们需要选择一条出来然后就执行它这里就需要用到php中操纵数组的函数了这里常见的是利用end()函数取出最后一位这里的效果如下图所示而且它只会以字符串的形式取出值而不会取出键所以说键名随便取就行:
(这里由于我没有实操演示出来所以借用大佬的看看大佬链接附在结尾 那我们把最前面的var_dump改成eval不就可以执行phpinfo了吗换言之就可以实现任意php代码的代码执行了那在没有过滤的情况下执行命令也就轻而易举了具体效果如下图所示 那自然执行whoami命令也是可以的
system(whoami); get_defined_vars()
getallheaders()是有局限性的因为如果中间件不是apache的话它就用不了了那我们就介绍一种更为普遍的方法get_defined_vars()这种方法其实和上面那种方法原理是差不多的 可以看到它并不是获取的headers而是获取的四个全局变量$_GET $_POST $_FILES $_COOKIE而它的返回值是一个二维数组我们利用GET方式传入的参数在第一个数组中。这里我们就需要先将二维数组转换为一维数组这里我们用到current()函数这个函数的作用是返回数组中的当前单元而它的默认是第一个单元也就是我们GET方式传入的参数我们可以看看实际效果: 这里可以看到成功输出了我们二维数组中的第一个数据也就是将GET的数据全部输出了出来相当于它就已经变成了一个一维数组了那按照我们上面的方法我们就可以利用end()函数以字符串的形式取出最后的值然后直接eval执行就行了这里和上面就是一样的了 那我们把var_dump改成eval即可执行我们的phpinfo代码 那同样也能执行whoami命令 总结一下这种方法和第一种方法几乎是一样的就多了一步就是利用current()函数将二维数组转换为一维数组 session_id()
简单来说就是把恶意代码写到COOKIE的PHPSESSID中然后利用session_id()这个函数去读取它返回一个字符串然后我们就可以用eval去直接执行了这里有一点要注意的就是session_id()要开启session才能用所以说要先session_start()这里我们先试着把PHPSESSID的值取出来
(这里依旧是没有演示成功依旧是借用大佬的看看) 直接出来就是字符串那就非常完美我们就不用去做任何的转换了但这里要注意的是PHPSESSIID中只能有A-Z a-z 0-9-所以说我们要先将恶意代码16进制编码以后再插入进去而在php中将16进制转换为字符串的函数为hex2bin 那我们就可以开始构造了首先把PHPSESSID的值替换成这个然后在前面把var_dump换成eval就可以成功执行了同时我们还要加上hex2bin函数 php函数直接读取文件
上面我们一直在想办法在进行rce但有的情况下确实无法进行rce时我们就要想办法直接利用php函数完成对目录以及文件的操作 接下来我们就来介绍这些函数
1.localeconv
localeconv() 函数返回一个包含本地数字及货币格式信息的数组
解释见PHP localeconv() 函数 | 菜鸟教程
我们在代码中将localeconv()的返回结果输出出来它返回的是一个二维数组而它的第一位居然是一个点 .
那按照我们上面讲的是可以利用current()函数将这个点取出来的但这个点有什么用呢点代表的是当前目录我们可以利用这个点完成遍历目录的操作相当于就是linux中的ls 我们利用current函数把这个点取出来 完成目录遍历操作 2.scandir函数
scandir() 函数返回指定目录中的文件和目录的数组。 3.current(pos)
pos()函数是current()函数的别名两者是一样的
current() 函数返回数组中的当前元素单元。
每个数组中都有一个内部的指针指向它“当前的”元素初始指向插入到数组中的第一个元素。
详情见PHP current() 函数 4.dirname()和chdir()
chadir()这个函数是用来跳目录的有时想读的文件不在当前目录下就用这个来切换因为scandir()会将这个目录下的文件和目录都列出来那么利用操作数组的函数将内部指针移到我们想要的目录上然后直接用chdir切就好了如果要向上跳就要构造chdir(..)
首先我们可以利用getcwd()获取当前目录 ?codevar_dump(getcwd()); string(13) /var/www/html 那么怎么进行当前目录的目录遍历呢 这里用scandir()即可 ?codevar_dump(scandir(getcwd())); array(3) { [0] string(1) . [1] string(2) .. [2] string(9) index.php } 那么既然不在这一层目录如何进行目录上跳呢 我们用dirname()即可 ?codevar_dump(scandir(dirname(getcwd()))); array(4) { [0] string(1) . [1] string(2) .. [2] string(14) flag_phpbyp4ss [3] string(4) html } 那么怎么更改我们的当前目录呢这里我们发现有函数可以更改当前目录 chdir ( string $directory ) : bool 将 PHP 的当前目录改为 directory。 所以我们这里在 dirname(getcwd()) 进行如下设置即可 chdir(dirname(getcwd())) 我们尝试读取/var/www/123 http://localhost/?codereadfile(next(array_reverse(scandir(dirname(chdir(dirname(getcwd()))))))); 即可进行文件读取 5.array_reverse()
array_reverse() 函数将原数组中的元素顺序翻转创建新的数组并返回。
将整个数组倒过来有的时候当我们想读的文件比较靠后时就可以用这个函数把它倒过来就可以少用几个next() 6.highlight_file()
打印输出或者返回 filename 文件中语法高亮版本的代码相当于就是用来读取文件的 全文引用知识点见:
PHP Parametric Function RCE · skys blog
https://www.cnblogs.com/pursue-security/p/15406272.html