从开发者角度看,Web开发如何进行代码安全审计

刚毕业时进了一家技术团队有200多人的公司,在第一周熟悉代码时,顺便做了下审计,轻松发现了4个高危漏洞,以及若干中危漏洞,这篇文章用来总结一下当时的一些经验和做法

前期准备(踩点)

看文档

要审计一个应用,起码要熟悉这个应用的功能模块以及底层实现,有现成文档的话是最快的,作为开发人员,应该第一时间把项目文档和依赖的框架文档都过一遍,这个对审计带来的收益是持续的

看提交历史

提交历史直接反映了项目近期的状况,根据近期代码提交来观察是否每一个开发都遵循了编码规范,编码规范不好的人,写出来的代码bug数也会很高

还可以搜索,比如按fix/修复/修正/解决等关键字搜索commit message,看下都修复过哪些问题,以及修复的手法,可以对该项目的健康程度以及开发人员水平有一个了解

搭建项目并用扫描器扫一遍

这样可以对这个项目的目录结构和安全性等有一个大致的了解,该花精力着重审计的功能模块和优先级心里也有数了

开始审计

搜索原始而落后的代码

我对原始而落后的代码的定义,就是明明框架都封装好的函数不去用,非要自己用最原始的方式去调用,或者造了个渣轮子

比如一个PHP框架,如CodeIgniter,已经对获取GET或者POST过来的变量有封装如:

$this->input->post()

$this->input->get()

如果仍然出现直接取$_GET,$_POST,$_REQUEST这几个全局变量的代码,就证明开发人员不讲规范,不讲规范的原因是开发水平低,水平低就容易写出漏洞,可以从这些位置开始分析

CodeIgniter框架的自带的函数

$this->input->post()

$this->input->get()

第二个参数是可选的,用于过滤xss,但是默认false,也就是不过滤…所以写个正则去找一下这些代码的第二个参数不填或者是 false 的,然后去追踪看后续有没有进行防御过滤,以此类推

搜索sql语句

当一个项目用了框架之后,一般都会用框架提供的api去操作数据库,不会直接拼接sql语句,如果代码里有sql语句,那么很可能是不讲规范的人员写出来的,同理,不讲规范的人员水平通常不行,当然很容易忘记过滤

而且大部分开发人员如果要手工拼接sql语句了,变量名通常会叫sql,或者XXXsql

所以搜索的区域是业务代码里包含sql字样的代码,去回溯这些sql拼接的部分是不是用参数化查询,如果不是的话是不是用户可控的,有没有进行防御过滤

寻找富文本输入框

富文本过滤,无论是经验多丰富的程序员,总会百密一疏,从富文本中可以挖掘的漏洞太多了,如界面劫持

针对富文本的过滤,PHP里做得屌的是HTML Purifier,其它语言的富文本过滤,也有相对比较优秀的库

ruby: sanitize

javascript: js-xss DOMPurify

java jsoup

显然,如果上面的库一个都没见在项目里使用,而且项目里又有富文本编辑器的,还没有开启CSP,要么是没过滤,要么是从其它安全性不高的框架里一份过来,出漏洞的概率非常高

要知道过滤富文本,最正确的方式是把HTML转成DOM树,接着便利树的节点,白名单和黑名单相结合,一一剔除问题属性,整个编码过程工作量繁复,而且容易出错,不是随便抄就能抄好的.

检查api语义和规范

根据语义以及约定俗成的规范,读操作的接口都是用GET请求的,写操作都是用POST请求的

而市面上成熟的框架,都会带有全局的csrf防御,不过一般只针对POST操作

如果分析出有GET的接口实现了写操作,肯定是不看规范的人写的,这类接口通常就会有csrf以及其它的问题

复杂的功能先无脑改http数据包,再看代码

业务复杂的功能,通常交互步骤也多,代码也很复杂,直接看的话很容易头晕,还不如把所有提交的参数和返回值都改一编,看看有无报错等信息,一切正常的话再去看代码

其实这类功能,逻辑问题是最多的,比如越权

危险函数

这个先要看自身对项目所用语言的了解程度,项目的整体架构,项目的规模,危险函数出现的位置。函数放在那里就是让人用的,但是你用的位置不对,还是用户输入可控,那就是问题了

就拿系统命令执行来说,不是不能用,但是如果一个电商的抢购功能,用的又是传统的Web框架,你跟我说在里面加个exec开定时任务之类的,不说别的,我肯定让你滚回去重做

要知道开启新进程的开销很大,并发一上来cpu占用就够你喝一壶.而且能想出这种方案的,大部分连阻塞是什么都不懂,而执行系统命令默认在很多语言环境下都是阻塞的,影响系统性能,如果开多线程去处理,又要加入线程池,因为线程不是你想开多少就能开多少的

一般危险函数是针对PHP而言的,因为PHP的函数行为太丰富,特性太多,一般根据一些危险函数名单去审计,也会有一些发现

检查依赖的组件是否已经升级到最新版

这块没什么好说的,最怕是线上依赖的版本和测试环境的不一致,或者线上不是所有的服务器依赖的都一致

与开发人员进行交流,看看深浅

其实这不在代码审计的范围,但是如果你知道了开发人员的深浅,那么根据他的弱点去审计他负责的代码,也算是一个精准打击

比如

  • 并下并发场景下,如何保证商品库存的一致性

  • MySQL的锁机制是怎么样的

  • Redis你都用了哪些特性

  • 项目用了哪些队列组件,在什么场景下用的

一个不懂锁机制,不知道队列的人,写出来的代码的并发性肯定有问题,如果让他开发什么,,这种有次数限制的写操作场景功能,绝逼会有脏读或者脏写的漏洞,导致一个人可以领多次,抢多次的漏洞

最后

其实作为开发人员,自身技术实力过硬,对于整个项目的熟悉程度(如系统的环境,所依赖的组件的特性和源码等)越高,审计起来也就越方便

评论