一、rce漏洞概述
在Web应用开发中为了灵活性、简洁性等会让应用调用代码执行函数或系统命令执行函数处理,若应用对用户的输入过滤不严,容易产生远程代码执行漏洞或系统命令执行漏洞。
二、常见RCE漏洞函数
1.系统命令执行函数
- system():能将字符串作为OS命令执行,且返回命令执行结果;
- exec():能将字符串作为OS命令执行,但是只返回执行结果的最后一行(约等于无回显);
- shell_exec():能将字符串作为OS命令执行
- passthru():能将字符串作为OS命令执行,只调用命令不返回任何结果,但把命令的运行结果原样输出到标准输出设备上;
- popen():打开进程文件指针
- proc_open():与popen()类似
- pcntl_exec():在当前进程空间执行指定程序;
反引号``:反引号``内的字符串会被解析为OS命令;
2.代码执行函数
- eval():将字符串作为php代码执行;
- assert():将字符串作为php代码执行;
- preg_replace():正则匹配替换字符串;
- create_function():主要创建匿名函数;
- call_user_func():回调函数,第一个参数为函数名,第二个参数为函数的参数;
- call_user_func_array():回调函数,第一个参数为函数名,第二个参数为函数参数的数组;
可变函数:若变量后有括号,该变量会被当做函数名为变量值(前提是该变量值是存在的函数名)的函数执行。
三、RCE漏洞的绕过方式:
具体看:RCE漏洞详解及绕过总结(全面)-CSDN博客
接下里看例题:
一.eval执行
进入题目就看见了源代码
php函数意思是:
是否由变量cmd 如果有,就执行eval($_REQUEST["cmd"]);
也就是木马
补充:
eval函数,将字符串认为是php代码来执行。
具体:
__isset判断一个变量是否已设置, 即变量已被声明,且其值为ture
所以我们在访问的时候使用变量 cmd
先直接查看根目录有没有flag
/?cmd=sysytem("ls");
注意:这几条命令最后面的“;”都不能省略
发现有php文件,但是没有flag文件
那么就查看上一级目录
/?cmd=system("ls /");
发现了有flag文件,那么就访问这个文件
/?cmd=system("cat /flag_3748");
得到flag
二.文件包含
进入题目,看见有一个GET传参,然后下面还有一个shell的超链接
点开看一下
这里又包含了eval函数,而且要求赋值给ctfhub,原网页还有一个get传参 所以这题应该是get+post传参的 并且要赋值给ctfhub才可以执行命令(这里就要用到hackbar了)
那么就按照它说的做,先用get传参
/?file=shell.txt
然后再进行post传参
ctfhub=system("ls");
我们通过查看根目录发现了两个文件
但是并没有发现flag文件
所以查看上一级目录
ctfhub=system("ls /");
发现了flag的字眼,继续查找flag
ctfhub=system("cat /flag");
发现了flag
三.php://input
先了解一下是什么?
php://input 是 PHP 提供的一个伪协议,允许开发者 访问 POST 请求的原始内容。对于 POST 请求数据,PHP 提供了 $_POST 与 $FILES 超全局变量,在客户端发起 POST 请求时,PHP 将自动处理 POST 提交的数据并将处理结果存放至 $_POST 与 $FILES 中。
所以php://input要用 post请求才可以
使用php://input的条件也满足
接下来就是要用bp进行抓包,然后操作
先在题目地址栏中访问php://input,然后抓包(/?file=php://input)
<?php system("ls");?>
注:在本题使用<?php system('ls');?>
无效,要直接使用<?php system('ls /');?>
查看根目录
并且这里修改发送方法为post,目标修改为/?file=php://input
<?php system("ls /");?>
查看上一级目录
<?php system("cat /flag_8199");?>
查看这个flag下的所有内容
得到flag
这题值得注意的点就是php://input 的用法以及它的使用条件 php://input需要用post请求的方式
四.远程包含
进入题目,首先看到源代码,然后下面有个phpinfo的链接,点开看一下
发现符合php://input的使用条件,所以本题可以使用php://input的方法来做
用bp抓包,做法和上一题一样的
首先访问/?file=php://input,然后抓包
抓到包以后,发送到repeater,把GET修改为POST,目标修改为/?file=php://input
并且在body部分执行 <?php system("ls");?> 查看根目录
然后查看上一级目录 <?php system("ls /");?>
最后执行 <?php system("cat /flag");?>
查找flag,并且得到了flag
五.读取源代码
这道题需要我们读取源代码
这里用php://input发现执行不了 就需要用到另外的一个伪协议 php://filter
先来认识一下它
使用的方法:
/?file=php://filter/read=convert.base64-encode/recource=index.php;
这句话的意思是我们用base64编码的方式来读文件index.php;这时页面会显示出源文件index.php经过base64编码后的内容,然后经过base64解码就可以看到flag;
convert.base64
convert.base64-encode和 convert.base64-decode使用这两个过滤器等同于分别用base64_encode()和base64_decode()函数处理所有的流数据。
convert.base64-encode支持以一个关联数组给出的参数。如果给出了line-length,base64 输出将被用line-length个字符为 长度而截成块。如果给出了line-break-chars,每块将被用给出的字符隔开。这些参数的效果和用base64_encode()再加上 chunk_split()相同。
进入题目,发现它已经给了我们flag的位置
我们直接执行命令:?file=php://filter/resource=/flag
得到flag
还可以:
执行命令/?file=php://filter/read=convert.base64-encode/resource=/flag
让flag以base64编码的方式呈现出来
然后解码
同样的,也可以得到flag