代码审计思路

1、说明

你要问我审计过什么项目发现过什么漏洞,那还真没有。记得第一家公司的老板娘问我“你会代码审记吗”,我不懂该怎么回答。要说懂我不愿定代码审计的具体定义是什么;要说不懂我看懂了ecshop和公司的代码框架,在我认为中看懂代码和源代码审计没什么区别嘛。如今说的话,真要说区别我以为和渗透测试是测试的子集同样,代码审计也是“看懂代码”的子集。php

子集换意思,就是基本能力和基本思想是能够通用的,但由于注意的点更集中,因此通用方法能够简化、优化出专门的方法。具体到看懂代码和代码审计上,看懂代码讲究从总体上弄清数据流向和各模块功能,代码审计则能够只追究局部,好比只要我看到char strdst[9];strcpy(strdst,"0123456789"),我不用明白程序功能是什么就能够判定这里必然溢出。前端

 

2、代码审计的思路

2.1 思路来源

如开头所说我没搞懂“代码审计”和“看懂源代码”的区别,因此买了本书,是尹毅的《代码审计:企业级Web代码安全架构》(名字很牛逼书却很薄,我常常想少于300页的书质量都不太行的。。),具体内容基本忘了,只记得其中提到代码审计大概有两种思路:第一种是正向追踪数据流,第二种是逆向溯源数据流。java

前不久看王炜的《揭秘家用路由器0day漏洞挖掘技术》,其中也说代码审计大概有正向追踪和逆向溯源两种方式,另外进一步指出对于fgets/read/recv等输入函数适合正向追踪,对于strcpy/system等操做函数适合逆向溯源。mysql

最后再回头去看Marcus Pinto的《黑客攻防技术宝典:Web实战篇》,其在第19章中说查找源代码中的源洞分三步:第一步是肯定接收用户输入的位置,第二步是查找漏洞签名,第三步是详细分析漏洞签名的上下文看有没有漏洞。所谓漏洞签名就是漏洞常常出现的特征代码,更简单点说就是漏洞常常伴随出现的函数,好比缓冲区溢出的strcpy,再好比命令注入的sehll_exec等。sql

 

2.2 思路总结

我看遍了全部理论,感受说得都看有道理,但要我进行代码审计,仍是彻底不懂该怎么操做。最主要的问题就是正向追踪,从什么位置开始追?追到什么位置算结束?逆向溯源,从什么位置开始溯?溯到什么位置算结束?shell

直到我反复琢磨以上三本书的说法,发现获取用户输入的函数与漏洞签名函数互为起止点。代码审计思路总结为如下四个步骤:安全

1. 肯定要审计的代码是什么语言(好比是java仍是.net)、什么框架(好比是ssh仍是其余)。cookie

2. 肯定该语言及框架,从get/post中获取用户输入的函数或形式(好比java的getParameter,php的$_GET和$_POST);肯定该语言各种漏洞的签名函数(好比JAVA和SQL漏洞相关的的是execute、executeQuery、createStatement,和命令执行漏洞相关的是getRuntime和exec等等)。session

3. 使用Source Insight打开要审计的项目。架构

4. 使用search project在整个项目中查找获取用户输入函数和漏洞签名函数,对获取用户输入的函数使用正向追踪数据流看用户能控制的数据有没有进入漏洞签名函数,对漏洞签名函数使用逆向溯源数据流看数据来源是否是源于获取用户输入的函数。

其实咱们去看代码审计工具,第一步都是查找获取用户输入函数和漏洞签名函数,第二步则是或正向或逆向追踪一下函数的变量(追踪能力的强弱差异则是审计工具能力强弱的差异)。好比下边两图是VCG(VisualCodeGrepper)和Seay对dvwa的审计结果:

通常而言,正向追踪能含盖更多的数据流分支,但有可能大多数数据都不会进入漏洞签名函数因此效率可能会低一点;逆向溯源从漏洞签名函数出来发现漏洞的几率会大一点,可是容易漏掉一些没有漏洞签名的函数(好比后门密码等)。

 

2.3 各语言获取用户输入及漏洞签名函数汇总

如下表格整理自《黑客攻防技术宝典Web实战篇》(第二版),并不全只是作个参考,增强所谓漏洞签名函数的意思(不少实际上是类可是类仍是函数并非重点)。

语言 获取用户输入 会话交互 sql注入 系统命令注入 动态代码执行 路径遍历 url重定向
Java

getParameter

getHeader等

getAttribute

setAttribute等

executeQuery

executeUpdate

getRuntime

exec

readObject

writeObject

FileInputStream

FileReader

sendRedirect

addHeader

.Net

Params

QueryString

Add

SqlCommand

SqlDataAdapter

Process

ProcessStartInfo

Execute

ExecuteGlobal

File.Open

FileStream

Redirect

Addheader

PHP

$_GET

$_POST

$_SESSION

session_register

mysql_query

mssql_query

exec

shell_exec

eval

call_user_func

fopen

include等

http_redirect

header

Perl

param

cookie

pm selectall_arrayref

system

exec

eval

open

sysopen

redirect

 

 

 

 

 

 

 

 

 

 

 

 

 

3、具体操做演示

下面以从之前帮妹子写的一个毕业设计中经过逆向溯源查找sql注入来进行演示上一点所说的思路具休操做是怎么个样子(说来妹子最终都没是本身的妹子实在是悲剧)。

第一步----使用的语言和框架----java、struts2。

第二步----获取用户输入函数和漏洞签名函数-----struts2获取用户输入是经过继承ActionSupport实现getter/setter方法来获取的,java中sql注入的漏洞签名函数是executeQuery、executeUpdate。

第三步----使用Source Insight打开要审计的项目----结果以下图所示

 

第四步----使用search project查找executeUpdate并溯源其变量是否源于用户输入----操做过程以下

列出来的那些就是使用executeUpdate函数的位置,点击红色连接按钮便可跳转过去,在审计中咱们将逐个审计这些位置。

咱们点击连接按钮进入第一处,往前看executeUpdate执行的sql语句,能够看到语句中对大多数变量使用了预编译形式(ps.setString)但对user.getLoginPwd()使用了拼接方式

咱们要追踪user.getLoginPwd()的来源,看是否是来自于获取用户输入的函数。user是register函数的参数,咱们要回溯哪里调用了register。在register上右键,点击“Jump To Caller”

以下图所示即进入调用位置,咱们往前看到user.setLoginPwd(),将光标置于其loginPwd参数上,在下方的定义窗口能够看到loginPwd是本类定义的一个变量

双击下方定义窗口的中“loginPwd”主窗口即跳转到该位置,观察上下文loginPwd正是继承ActionSupport类后实现的getter方法(getLoginPwd)从前端表单中获取的

因此,sql漏洞签名函数中,拼接的loginPwd变量来源于,用户输入;因此该处存在sql注入。

相关文章
相关标签/搜索