Web安全-命令执行漏洞

概述

命令执行漏洞概念:当应用需要调用一些外部程序去处理内容的情况下,就会用到一些执行系统命令的函数。如PHP中的system,exec,shell_exec等,当用户可以控制命令执行函数中的参数时,将可注入恶意系统命令到正常命令中,造成命令执行攻击。

漏洞成因:脚本语言优点是简洁,方便,但也伴随着一些问题,如速度慢,无法解除系统底层,如果我们开发的应用需要一些除去web的特殊功能时,就需要调用一些外部程序。

敲黑板!敲黑板!敲黑板!提到命令执行漏洞,大家难免会想到代码执行漏洞,两者确实很像,没有太大的区别,提交漏洞时可能没有分的那么详细,不过我们在学习时还是要学会区分不同的概念。

(1)命令执行漏洞:直接调用操作系统命令。

其原理为:在操作系统中,“&、|、||”都可以作为命令连接符使用,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令。

(2)代码执行漏洞:靠执行脚本代码调用操作系统命令。

其原理为:应用有时需要调用一些执行系统命令的函数,如PHP中的system、exec、shell_exec、passthru、popen、proc_popen等,当用户能控制这些函数中的参数时,就可以将恶意系统命令拼接到正常命令中,从而造成命令执行攻击,这就是命令执行漏洞。

漏洞示例

入门示例

命令执行漏洞是指攻击者可以随意执行系统命令。
Web安全-命令执行漏洞Web安全-命令执行漏洞

进阶示例

注意:下面的例子可能需要通读全文后才能更好的理解。

使用phpstudy搭建环境,新建一个test.php文件,其中输入代码:

 <?php
     $arg =$_GET['cmd'];
     if ($arg) {
        system($arg);
     }
 ?>

在浏览器中访问:
Web安全-命令执行漏洞
我们没有加任何东西,当然会报错啦。接下来我们给它加上参数:
Web安全-命令执行漏洞
这样的操作就是相当于我们在命令行(cmd)下进行ipconfig的查询:
Web安全-命令执行漏洞
同样我们来做一个代码执行的页面。新建hetian.php,输入代码:
Web安全-命令执行漏洞
在浏览器中打开:
Web安全-命令执行漏洞

接下来我们加入自己的参数,在挖掘漏洞时我们最常见的就是使用phpinfo()
Web安全-命令执行漏洞
我们这里也使用phpinfo();这样执行的效果和我们直接去phpinfo.php查看是一样的:
Web安全-命令执行漏洞

命令执行模型

任何脚本语言都可以调用操作系统命令,而各个脚本语言的实现方式都不一样,接下来以PHP和Java两种程序语言为例分析。当程序员明白了这写函数存在的问题后,才能真正做到安全开发。

PHP命令执行

实例1、命令执行
Web安全-命令执行漏洞实例2、代码执行
Web安全-命令执行漏洞注意:phpinfo()函数用于显示PHP的版本信息页面。
Web安全-命令执行漏洞
实例3、动态函数调用

PHP支持动态函数调用,代码如下:
Web安全-命令执行漏洞

Java命令执行

在JavaSE中,存在Runtime类,在该类中提供了exec方法用以在单独的进程中执行指定的字符串命令。像JSP、Servlet、Spring、Hibernate等技术一般执行外部程序都会调用此方法。下面以Runtime类为例进行说明,模型代码如下:
Web安全-命令执行漏洞

框架执行漏洞

至今,框架技术已经被广泛应用,框架让开发变得更简单、更省时、更高效,越来越多的开发者喜欢用框架。使用框架对开发者来说是好事,但是一旦出现了安全漏洞,则是致命的。框架的用户群体越多,危害就越大。像之前爆出的Struts2代码执行漏洞,就让国内的网站消失了一大批。

Struts2代码执行漏洞

Web安全-命令执行漏洞Web安全-命令执行漏洞
这就是Struts2<2.2.0的命令执行漏洞,让国内外的一些金融、教育、电子商城网站死了一大批,罪魁祸首不是网站自身的漏洞,而是Struts2框架。

ThinkPHP命令执行漏洞

Web安全-命令执行漏洞

防范命令执行漏洞

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

(1)尽量不要使用系统执行命令;
(2)在进入执行命令函数/方法之前,变量一定要做好过滤,对敏感字符进行转义;
(3)在使用动态函数之前,确保使用的函数是制定函数之一;
(4)对PHP语言来说,不能完全控制的危险函数最好不要使用。

在进行防范之前,确保输入是否可控,如果外部不可输入,代码只有程序开发人员可以控制,这样,即使你写的代码漏洞百出,也不会有危害。这一点适用于所有的安全漏洞的防范。当然,不建议你这么做,隐藏起来并不是真的安全,要永远假定攻击者知晓系统内情,这样才能做到代码阶段的漏洞防范。

相对而言,只要输入可控,就可能存在安全漏洞,这也验证了一句老话:有输入的地方就有可能存在漏洞!