马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?注册帐号
×
一、代码审计命令注入
PHP自带的函数中提供了几个可以执行系统命令的函数,在web项目的开发中一般是不会用到的,但有些程序员为了更简洁的操作,使用了这些函数就会导致一些安全问题的发生。
可以执行系统命令的常见函数有:system、exec、passthru、shell_exec、popen、proc_open、pcntl_exec。下面将分别进行介绍:
string system(string $command [, int &$return_var ]):执行外部程序,并且显示输出.含有两个参数,command为要执行的命令。return_var为可选,如果提供此参数,则外部命令执行后的返回状态将会被设置到此变量中。
string exec(string command, string [array], int [return_var]):执行外部程序,但不直接输出结果。返回字符串只是外部程序执行后返回的最后一行。
string passthru(string command, int [return_var]):本函数类似exec()用来执行 command 指令,并输出结果。
string shell_exec ( string $cmd ):执行命令并返回完整的输出为一个字符串,功能跟反引号类似。
resource popen ( string $command , string $mode ):打开进程文件指针,command 为要执行的命令,mode为规定连接模式。与proc_open类似。
bool pcntl_exec ( string $path [, array $args [, array $envs ]] )以指定的参数执行程序,当发生错误时返回 FALSE ,没有错误时没有返回。
因此在不需要的web项目中应禁用掉这些危险函数,可以通过php.ini配置文件的disable_functions项来禁用。如果确实需要使用,可以根据情况使用escapeshellarg和escapeshellcmd来过滤一些元字符来,配合保证安全。
二、代码执行注入
代码执行注入不同于命令注入,它是把用户请求的参数注入到应用中最终到webserver去执行的。一个执行的是系统命令,一个执行的是PHP命令。
容易出现此类问题的函数有eval()、assert()、preg_replace()、call_user_func()、call_user_func_array()、array_map()等。
eval和assert函数都是把变量中的值当成PHP代码执行。因此当传递给此函数的变量可控,并且未做严格处理,就可能导致代码执行。
call_user_func和call_user_func_array函数本来的功能是调用函数,比如框架开发中动态的调用函数处理传递的值等。
array_map函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组。
preg_replace函数通过正则进行字符串处理,但当正则包含了修饰符e并且存在可控参数时可造成代码执行。
因此当使用这些函数的时候应尽量不使用可控参数,如需要使用应根据业务场景严格限制可控参数。代码执行示例如图:
三、xss漏洞
xss漏洞及跨站脚本攻击,相信大家都不陌生,都是因为外部提交的参数中含有恶意的js代码。后端接收后并未严格的处理就返回给了客户端、输出到页面或存入数据库中造成的。利用场景主要还是在获取用户cookie上,其实前端能做的事,xss都能做。(经常xss漏洞,开发人员都会问,你谈个框出来有什么危害,有没有!~~)
在用框架开发PHP项目中,大多数人都会写一个统一的过滤函数,然后在每次取参数时进行调用后,再赋值给变量。一些没有太多复杂交互的网站也会用全局过滤配置。这样取出来的值就是已经被过滤了的。
下面以ThinkPHP为例,说一说全局过滤,如图,当我们访问一个ThinkPHP开发的web时,会先执行index.php中的代码,index.php中引入了ThinkPHP.php文件,我们找到此文件。
在ThinkPHP文件加载了系统常量定义等等之后,最后一行初始化了我们的应用。
Start()静态方法会加载一些应用配置文件中的信息之后,在最后一行,开始运行应用。
在run方法的开头,首先调用了init()初始方法。
然后在init方法中,有如下一段代码,它会首先判断REQUEST_VARS_FILTER配置是否为真,为真的情况下,就会把所有接收的参数一个一个取出来用think_filter函数来进行过滤。
think_filter是写在ThinkPHP/Common目录下的function.php文件中的。
因此在做全局过滤的时候,大多会在此单独写一个方法来做全局过滤。
在ThinkPHP中还有如下几种常用过滤方式,第一、二种都是调用的框架函数来获取传递的参数值,不同的是一个是指定函数进行过滤,一个是读取配置文件中指定的函数来过滤,如果没有就不过滤,第三种就是常规过滤了。
其中框架I方法能过滤的原因就在于ThinkPHP/Common目录下的function.php文件中定义了一个I方法,并且在获取前端传递的值时,判断是否传递了过滤函数名,如果有就取此函数名,如果没有就取配置文件中函数名来进行过滤。
在了解了这些之后,我们才能更好的定位是否存在参数未过滤的情况,至于怎么才算完整过滤,和各种绕过技巧之类的网上已有很丰富的文章~~~~就不再献丑了。
四、本系列后续文章
1、代码审计之SQL注入
2、其他待
|