代码审计

     补充一个,之前在说XSS的输入检查的时候,这种方式是有局限性的,因为输入的XSSfilter无法理解输出的语境,对一些符号的处理可能会改变用户数据的原意,并且,针对一些特定输出点可能起不到正确的防御作用。然后这篇的内容是想把代码审计的一个大体思路和一些注意的地方记录一下。

目录



代码审计思路

首先,我们在对一个系统进行审计过程之前,最好在本地搭建一个应用,然后对功能有个大体上的了解。然后接下来会描述一下几种不同的审计思路。

从功能方向上的审计思路

从index、webxml等入口页面开始
寻找加载的配置文件,如conf、inc、ini、敏感xml文件等
寻找功能实现点
从功能点中找到参与实现的函数
函数中是否含有敏感方法的调用
调用过程中参数是否可控,参数是否通过安全函数,以及安全函数对应此功能点是否合适
数据有无二次使用,在二次使用中是否做了相应的安全措施

从数据流向上的审计思路

用户可控变量在应用的什么位置被获取
该变量参与了什么功能的实现,将涉及变量的所有函数找全
参与的函数中是否含有敏感方法
如为敏感方法对应数据是否做了安全措施
注意普遍验证过程中参数的生成规律,考虑验证过程中参数是否存在泄露或加密规则的失误或导致触发某些漏洞(hash扩展之类

自动化审计思路

在人工审计过程中,我们主要是根据函数关键字,手动去追踪数据的流向。而在自动化审计中,我认为主要的思路还是去追踪数据的流向和来源。针对PHP代码的审计的话,可以使用PHP-Parser生成语法树。以下为代码审计的思路


初始化载入文件,定义入口位置
语法分析,抽象生成AST
根据AST构建控制流图CFG
根据之前的信息对代码的类,函数,参数,代码块进行信息搜集分类
数据追踪部分,对敏感函数中的数据进行追踪,将敏感函数数据进行追踪分析汇总
对敏感函数中调用的数据进行回溯追踪和流向追踪,根据权重判断是否为漏洞。考虑不同函数本身调用不同的安全函数有不同的权重+函数本身危险程度+数据涉及到的操作权重作为判断

PHP审计相关漏洞

文件包含漏洞

对采用了include()、require()这类函数的使用,要注意是否存在文件包含漏洞(PS:include和require的不同点在于对错误的处理上,require更加严格且无返回值)。
这里就涉及到本地文件包含和远程文件包含的区别,远程文件的包含需要开启allow_url_include和allow_url_fopen,
fopen是配置以支持的fopen扩展协议去打开一个url对象,include配置允许include等函数的参数是以fopen封装的打开对象是一个url的形式,需要fopen开启,但是伪协议的使用也受限于这个的开启,所以如果要用伪协议来构造文件包含还是需要这个配置的开启。
本地文件包含:容易泄露敏感数据和业务源代码,审计中需要注意是否限制了可包含目录(日志、环境Session文件,其他缓存或数据库文件等),是否存在目录遍历漏洞,以及对可控参数的限制是否完善。本地文件包含是可以结合文件上传漏洞联合使用达到命令执行的目的(需要物理路径)。
远程文件包含:在远程文件包含中,可以通过问号截断后部分内容,还有伪协议的使用,需要注意限制措施是否完善。

变量覆盖漏洞

在很多早期CMS中,在register_globals为ON的情况下没初始化变量,或者对伪全局变量使用不当,或使用extract、parse_str函数不当,都易造成变量覆盖漏洞的产生。织梦CMS的这个漏洞比较出名= =。
解决办法是在关闭register_globals、对伪全局变量从外部来的变量进行递归过滤或转义,对使用的函数检查用户是否可控变量来源。

代码执行漏洞

代码执行漏洞的产生一个方面是其他漏洞,比如文件上传、变量覆盖等漏洞造成的,一个是在执行危险函数中变量用户可控或者安全措施不完善导致的,还有就是反序列化漏洞也可以造成代码执行。具体的危险函数和利用方法参考红书。
防御手段一个是禁用危险函数,一个是在这些函数的使用过程中检查参数是否可控或做过滤转义。对于其他漏洞结合使用造成的代码执行漏洞,要根据具体的不同情况做相应的防御。

SQL注入

因为一般针对排序后的注入是不采用预编译的,所以要检查参数中用户可控点做了相应的安全措施。如果没有采用预编译,看语句拼接的变量是否做了相应的过滤转义。

sprintf

%会吃掉后面的一个特殊符号字符,或者吃%后面三个字节的其他字符,$会吃掉其后一个特殊符号字符,可以用来绕过转义。

逻辑漏洞

根据业务功能的代码看是否存在业务逻辑漏洞,业务相关的安全会在之后总结。





补充一下,书里也提到了PHP环境的安全,我们可以做一个相对安全的配置来对某些漏洞做防御。


发表评论 暂无评论

*