目录
一. 命令执行漏洞
程序员使用脚本语言(比如PHP )开发应用程序过程中,脚本语言开发十分快速、简介,方便,但是也伴随着一些问题。比如说速度慢,或者无法接触系统底层,如果我们开发的应用特别是企业级的一些应用需要去调用一些外部程序。当应用需要调用一些外部程序时就会用到一些系统命令的函数。 应用在调用这些函数执行系统命令的时候,如果将用户的输入作为系统命令的参数拼接到命令行中,在没有过滤用户的输入的情况下,就会造成命令执行漏洞 。
也就是说命令执行即直接调用操作系统的命令。其原理是,在操作系统中,“&、|、||”都可以作为命令连接符使用,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,将用户的输入作为系统命令的参数拼接到命令行中,在没有过滤用户输入的情况下,造成命令执行漏洞。
command1&command2 两个命令同时执行,前面执行不成功后面也执行
command1&&command2 只有前面命令执行成功,后面命令才继续执行
command1;command2 不管前面命令执行成功没有,后面的命令继续执行(Linux)
command1||command2 将一个命令的标准输出作为另外一个命令的标准输入。当第一条命令失败时,它仍然会执行第二条命令
command1||command2 顺序执行多条命令,当碰到执行正确的命令后将不执行后面的命令
1. PHP中常见的命令执行函数
- system(): 将字符串作为OS 命令执行,自带输出功能,不需要打印
- exec(): 将字符串作为OS 命令执行,需要输出执行结果
- shell_exec(): 执行shell命令并返回输出的结果的字符串
- passthru(): 将字符串作为OS 命令执行,自带输出功能,不需要打印
- `` (反引号): 与shell_exec函数的功能相同
- popen()
命令执行案例,传送门 -》DVWA之命令注入漏洞(Command injection)
2. 命令执行漏洞防御
1. 尽量减少命令执行函数的使用,并在disable_functions 中禁用
2. 在进入命令执行的函数或方法之前,对参数进行过滤
3. 参数的值尽量使用引号包裹,并在拼接前调用addslashes 进行转义
二. 代码执行漏洞
应用程序在调用一些能够将字符串转换为代码的函数(如PHP中的eval(),eval可以将字符串当做函数进行执行)时,没有考虑用户是否控制这个字符串,将造成代码执行漏洞。一般很难通过黑盒查找漏洞,大部分都是根据源代码判断代码执行漏洞。
代码执行(注入)类似于SQL 注入漏洞,SQLi 是将SQL 语句注入到数据库中执行,而代码执行则是可以把代码注入到应用中最终由服务器运行它。这样的漏洞如果没有特殊的过滤,相当于直接有一个Web 后门的存在。
1. 漏洞危害
可以通过代码执行漏洞继承Web 用户权限,执行任意代码。如果服务器没有正确配置,Web 用户权限比较高的话,我们可以读写目标服务器任意文件内容,甚至控制整个网站以及服务器。
2. PHP中的代码执行函数
- eval() 将字符串当作php 代码执行
- assert() 同样会作为PHP 代码执行
- call_user_func() 回调函数,可以使用is_callable查看是否可以进行调用
- call_user_fuc_array() 回调函数,参数为数组
- create_function() 创建匿名函数
- preg_replace() 当php版本小于7时,当为 /e 时代码会执行
- array_map() 为数组的每个元素应用回调函数
- array_filter() 依次将 array 数组中的每个值传递到 callback 函数。如果 callback 函数返回 true,则 array 数组的当前值会被包含,在返回的结果数组中。数组的键名保留不变。
- usort() 使用自定义函数对数组进行排序
一句话木马就是利用的代码执行漏洞:
<?php @eval($_POST[cmd]);?>
3. 代码执行漏洞防御
- 保证用户不能轻易接触 eval()函数 的参数或者用正则严格判断输入的数据格式
- 字符串使用单引号包裹,并在插入前进行 addslashes()
- 对preg_replace()放弃使用e修饰符,保证第二个参数中对于正则匹配出的对象,用单引号包裹