代码审计
通常是白盒测试时使用的方法,检查源代码中的缺点和错误信息,分析并找到这些问题引发的安全漏洞,并提供代码修订措施和建议
为何进行代码审计
项目规模越来越庞大,业务复杂度越来越高
开发人员水平参差不齐,而且不懂安全
开发工作外包,大量使用第三方工具,第三方库,代码安全不能保障
破坏永远比建设容易,很可能一个小的疏忽导致难以估计的损失
审计方法
人工
对审计工作的要求很高
- 有编程基础
- 掌握目标程序语言的语法语义
- 学习常见的代码缺陷
- 经验很重要
工具
notepad++、sublime只是辅助工具
seay代码审计工具(exe程序)
rips(将文件夹放到www目录下,访问网站即可)
fortify(商业版的软件,要收费,且收费不菲)
firefox(有很多插件很实用,FoxyProxy、Hackbar、ModifyHeaders、User Agent Switcher、Firebug)
Burp Suite(只能说这是不可缺少的神器)
审计步骤
基础准备
- 获得源码,大多数php程序都是开源的,去官网可以直接下载,站长之家,A5源码也可以下载
- 安装网站,本地搭建网站,一边审计一边调试,实时跟踪各种动态变化
把握大局
- 网站结构,浏览源码文件夹,了解网站大致目录
- 入口文件,index.php文件一般是网站门户,在这个文件中可以知道网站的架构、运行流程、包含哪些配置文件,包含哪些过滤文件及包含哪些安全过滤文件,了解网站的业务逻辑
- 配置文件,一般类似config.php等文件,保存一些数据库相关信息、网站的一些信息。如果是gbk则可能存在宽字节注入。如果变量的值用双引号、则可能存在双引号解析代码执行的问题。
- 过滤功能,通过详读 公共函数文件 和 安全过滤文件 等文件,清晰掌握用户输入的数据,哪些被过滤,哪些无过滤,在哪里被过滤了,如何过滤的,能否绕过过滤的数据。过滤的方式是替换还是正则?有没有GPC?有没有使用
addslasher()处理?
审计方法
通读全文法
这种方法一般是企业对自身产品的审计,对于小型应用,可以尝试读一下,大型应用不太现实
刚刚的把握大局也可以应用通读全文法,根据入口文件进入各个功能进行审计
敏感函数参数回溯法
这个方法是最高效,最常用的方法
大多数漏洞的产生是因为函数的使用不当导致的。我们只要找到这样的一些使用不当的函数,就可以快速挖掘想要的漏洞。
seay代码审计工具,可以帮助我们快速匹配高危函数、关键函数、敏感关键字
分析判断敏感函数的上下文,追踪参数源头,尝试控制可控的参数变量
定向功能分析法
主要是根据程序的业务逻辑来说审计的
首先是用浏览器逐个访问浏览,看看这套程序有那些功能。根据相关功能,大概推测可能存在那些漏洞
常见功能漏洞:
程序初始安装、
站点信息泄漏、
文件上传、
文件管理、
登陆认证、
数据库备份恢复、
找回密码、
验证码
方法总结
把握大局-定向功能-敏感函数参数的回溯
php配置文件php.ini
启用全局变量
register_globals = on
有些程序例如OSC需要启用全局变量.
这个设置的作用是关闭自动注册的全局变量
在设置为On的时候,php会将POST,_GET,COOKIE,_ENV,SESSION数组中的key=>value直接注册为变量,比如_POST[‘username’]就会被注册为$username。
虽然方便了调用,但是会有三个问题:
- 不知道变量是哪里来的,POST来的还是_SESSION来的呢?非常不方便别人阅读代码。
- 变量之间互相覆盖,引起不必要的麻烦。
- 安全问题。所以要设置为Off。
register_globals 为 on 的情况,PHP4 之前默认开启,PHP5 以后默认关闭。
短标签
short_open_tag = On
可以使用短标签变形一句话绕过检测
安全模式
safe_mode = off
php的安全模式是个非常重要的内嵌的安全机制,能够控制一些php中的函数,比如system(),同时把很多文件操作函数进行了权限控制,也不允许对某些关键文件的文件,比如/etc/passwd,但是默认的php.ini是没有打开安全模式的
禁用类/函数
disable_classes = , disable_functions = , disable_functions = opendir,readdir,scandir,fopen,unlink
禁用某些类,禁止某些函数。接受逗号分隔的函数名列表作为参数。只能设置在 php.ini 中。
设置上传文件大小
file_uploads = on
upload_max_filesize = 8M
文件上传临时目录
upload_tmp_dir =
上传临时文件保存的目录,需要可写,如果不设置,则采用系统临时目录。(/tmp,c:\windows\temp)
用户访问目录限制
open_basedir = .:/tmp/
使用open_basedir选项能够控制PHP脚本只能访问指定的目录,这样能够避免PHP脚本访问不应该访问的文件,一定程度上限制了phpshell的危害.我们一般可以设置为只能访问网站目录,表示允许访问当前目录(即PHP脚本文件所在之目录)和/tmp/目录,有效防止php木马跨站运行。
linux用冒号分隔,windows下用分号分隔
错误信息控制
display_error = On
是否将错误信息作为输出的一部分,站点发布后应该关闭这项功能,以免暴露信息。调试的时候当然是要On的,不然就什么错误信息也看不到了。
设置错误报告级别
error_reporting = E_ALL
这个设置的作用是将错误级别设置为最高,可以显示所有的问题,方便查错,也有利于写出高质量的代码。日志级别是一些常量,在php.ini中有写,推荐使用 E_ALL | E_STRICT,即所有级别。
错误日志
error_log =
错误日志的位置,必须对web用户可写入,如果不定义则默认写入到web服务器的错误日志中去 。
log_errors = on
如上所说,建议将错误日志输出到文件,而不是直接输出到前端。
log_errors_max_length = 1024
错误日志关联信息的最大长度,设为0表示无限长度
魔术引号
本特性已自 PHP 5.3.0 起废弃并将自 PHP 5.4.0 起移除。
magic_quotes_gpc = On
为 GPC (Get/Post/Cookie) 操作设置 magic_quotes 状态。 当 magic_quotes 为 on,所有的 ’ (单引号)、” (双引号)、\(反斜杠)和 NULL 被一个反斜杠自动转义。
转义耗时,浪费资源
是否允许打开远程文件
allow_url_fopen = on
本选项激活了 URL 形式的 fopen 封装协议使得可以访问 URL 对象例如文件。默认的封装协议提供用 ftp 和http 协议来访问远程文件,一些扩展库例如 zlib 可能会注册更多的封装协议。
是否允许包含远程文件
allow_url_include = off
本选项激活允许 include, include_once, require, require_once等函数使用 URL 形式的 fopen 封装协议。简单来说就是可以包含远程文件