Web代码安全漏洞深度剖析
上QQ阅读APP看书,第一时间看更新

3.1 代码审计的思路与流程

在代码审计工作中,最重要的是思路。每个人的思路不一样,经验不一样,直观感觉与理解也自然不同。下面笔者将介绍从实践中总结出来的经验,包括代码审计的难点、思路和流程。

3.1.1 代码审计的难点

代码审计的难点如下。

●代码看不懂,如缺乏编程语言基础、数据库基础、操作系统基础等。

●URL链接不会构造,如缺乏框架使用基础、网站运行基础等。

●方法的调用看不懂,如函数的作用、函数如何调用等。

●代码追踪复杂,如函数在各个文件的调用、各个方法的调用等。

●漏洞类型原理不熟悉,如Web前端漏洞基础、Web后端漏洞基础等。

●不会绕过各种障碍,如限制绕过基础、参数突破基础等。

以上问题导致了即使从其他渠道获取了漏洞POC(即验证代码),也不知道如何写出来的。本书将漏洞原理进行层次化的剖析,以达到快速进行代码审计的目的。

主要通过以下几点进行详解。

●目录结构。通过目录结构可以知道是什么开源程序,这对熟悉程序调用是必不可少的。

●URL链接构造。通过了解URL构造技巧,可以很方便地构造POC。

●漏洞位置定位。

●代码追踪。

●POC构造。

对于一些新手来说,建议从审计简单的漏洞开始,例如先通过直接搜索关键词、进行逆向追踪、使代码审计工具辅助(例如seay源代码审计工具)筛选出可能存在的漏洞点,然后再追踪代码来分析和验证漏洞触发条件。

3.1.2 代码审计流程

代码审计需要一个流程化的步骤来发现安全问题,可以参考以下流程来进行漏洞挖掘,即漏洞挖掘五步走。

1)寻找漏洞。

2)URL构造,访问到漏洞发生点的URL地址。

3)漏洞挖掘查询可控参数到漏洞发生点经过了哪些转换(可采用phpStorm+Xdebug进行调试分析,厘清可控参数到漏洞发生点的数据处理过程)。

4)防御突破。

5)构造Payload,验证漏洞真实性。

这种代码审计方式属于关键词定位结合逆向追踪参数溯源类型,通过以上步骤进行安全问题的探索,可以探索出更多安全漏洞。下面详细讲解这五步。

1.寻找漏洞

寻找漏洞一般有以下几种方法。

●全文通读结合功能点审计。

●关键词定位结合逆向追踪参数溯源。

●预测功能点漏洞结合功能点定向审计。

●灰盒测试结合代码审计。

对于一些新手来说,想要尝试挖掘应用系统源代码存在的漏洞,最快的方式就是搜索关键词。比如,要寻找代码执行的漏洞,就搜索可以触发代码执行的函数关键词。这里的函数关键词就是指代码当中所使用的一些编程语言自身所提供的功能函数,例如assert。

假设想要挖掘包含漏洞(包含漏洞会在第7章中介绍),可尝试在该源代码中搜索带有包含引用的函数,如关键词include。找到引用的函数之后,再从该代码功能实现的逻辑顺序从下往上推。如果这个功能或某个参数不可控的话,那么在外面复现或挖掘该漏洞时就会出现很多问题,最终可能会导致漏洞无法复现。

若参数可控且无任何安全机制或有效安全机制检查,可通过URL构造链接编写POC,以证明存在漏洞。

这里的难点在于对各种函数的调用,新手容易找不到调试思路,想要突破这个难点首先要熟悉URL路由、构造URL链接,再结合前面介绍的调试工具phpStorm+Xdebug去调试。

对于有经验的读者来说,常见的代码审计方式有两种。

(1)功能点审计

可以先对程序代码结构及功能逻辑进行了解,通过代码侧观察目录结构,知道哪些是核心目录,哪些是配置目录,哪些是逻辑功能代码,再结合该程序运行时的如下各种功能进行审计。

●个人中心(其中包含头像上传、密码修改……)。

●登录注册(其中包含信息注册、登录验证……)。

●文本留言(其中包含留言管理、留言内容……)。

●文本搜索(其中包含模糊查询、搜索拼接……)。

●消息发送(其中包含内容发送、附件发送……)。

功能越多,安全问题也可能越多。从正常研发的角度来讲,每一种功能的设计都是根据每个公司产品部门的需求来进行设定和调试的,外加部分用户的反馈进行修缮和版本更新。从攻击者的角度来讲,功能上的每一个交互点,每一个传输过去的参数,每一个交互过去的文本内容都可能会带来攻击的可能。

比如对于ThinkPHP5(TP框架5.0版本),若没有代码审计经验或者不去关注Think-PHP3版本与ThinkPHP5版本的更新状态,那么就可能会错过assign方法和display方法中产生的漏洞。ThinkPHP5与ThinkPHP3相比,封装得更强大,便利性更高,这样就更容易出现意想不到的漏洞。

(2)全代码通读

全代码通读并非代码全读,属于正向追踪。所谓正向追踪可以简单地理解为从源代码的程序执行入口开始,逐一进行功能点审计,包括所用到的开发框架、程序设计模式等。例如在审计框架级的程序时,可以先找出开发手册熟悉一下,然后根据手册挑出可控点函数并追踪代码,如可控参数带入了哪个方法,调用了哪个函数,一直追到此功能不能再持续跟进下去或者跟进到有漏洞点的位置。这样做的好处是查找漏洞时覆盖率高,容易追踪,URL链接好构造。采用全代码通读方法进行代码审计,需要熟悉各种漏洞类型原理以及常见函数可能造成的漏洞及利用技巧,最重要的是要有耐心。

一般功能点审计方式与全文通读代码审计方式是结合使用的,这样可以使效率更高。

2.URL构造

要想通过URL构造过程访问到漏洞发生的位置,必须知晓URL路由映射原理。下面通过实例演示如何通过分析学会构造漏洞URL。可在搭建环境后随便点击程序的几个链接,查看如下部分:

●目录结构

●目录命名

●代码分析

需要观察是单入口文件模式还是多入口文件访问模式。知名的ThinkPHP就是单入口文件模式框架。

多入口文件模式,从字面意思来讲就是通过多个入口文件访问不同的功能模块,例如常见的链接http://localhost//login.php、http://localhost//artcle.php?id=123等。

单入口文件模式的链接类型是http://localhost//index.php?m=artcle&a=index&id=123,就是在域名的后面总有一个index.php(或其他入口文件名),这个入口文件名可以在URL中通过配置隐藏。

我们在审计单入口文件模式的程序时,要先看一下入口文件的代码,比如常见的入口文件index.php(或其他命名的入口文件),还要查看是否有入口过滤文件的调用。基于个人的研发经验和安全经验,笔者一般会看一下目录结构,找到功能模块目录,结合目录名和在运行的程序中随便点击的几个链接,就可以构造URL,找到URL链接映射到的代码段,比如URL地址里的某个目录、文件名或参数对应了代码段里的哪些功能、变量或函数的使用等信息,基于这些信息去尝试定位漏洞发生位置。当然这时漏洞发生点在可通过URL链接直接访问到的自定义方法中,如果漏洞发生点存在于不可直接访问的类、方法中,那么可寻找通过URL链接访问到的方法的代码中,是否有可直接或间接调用这个漏洞发生点的代码。

3.漏洞挖掘

要想发现漏洞,必须掌握漏洞产生的原理,本书在后面介绍每种类型漏洞的时候做了详细的讲解与分析,比如,每一种漏洞类型的产生原理是什么,产生漏洞威胁的函数有哪些,PHP配置文件中哪些不当配置会造成安全隐患等问题,并与案例结合进行实战解析。

了解了程序本身的缺陷,再结合系统缺陷(如命令执行,上传漏洞的解析漏洞,截断问题等),就可以尝试对一些Web安全漏洞进行审计分析了。后续也可以通过多浏览行业大佬的博客,参加线下的沙龙与安全会议,看一看小型分享圈(如知识星球)来学习各种审计分析技巧。

4.防御突破

防御突破是攻击者喜欢挑战的一件事情。对方总是喜欢不动声色地打开你的“门锁”,发现里面的各类秘密。对于安全审计人员而言,就是站在攻击者视角去思考和尝试突破一些常用的防御代码、通用防御模块等,由此掌握一些代码审计的方法和技巧。

对于防御方法的绕过,比如XSS(跨站脚本攻击漏洞,是一个针对Web前端的漏洞)主要利用了前端JavaScript脚本的配合进行触发,比如开发者过滤了所有on事件,你也可以通过编码对o或者n进行编码来尝试绕过。关于绕过各种防御,可以通过在网上搜索引擎搜索关键词,如“waf绕过”来学习各种知识与思路,通过此手段可以尝试来提升自己的绕过手法。

5.构造Payload

构造Payload时,需要具备一定的编程基础,要理解漏洞原理,还需要掌握程序中的转码、序列化、类型转换等。在构造Payload时,可以尝试反着写代码。比如,如果外部传参的参数在程序中被编码了,你的Payload就应是解码后的形式;如果提交的数据被序列化了,你的Payload就应是反序列化后的形式。

从客户端传递参数到漏洞发生点,经过了哪些防御?怎么被转码?如何处理类型转换?需要把这些内容用流程图画出来,首先在漏洞发生处明确输出或执行的代码是怎么样的,然后拿着这些最终执行的代码往前推,该转码时就转码,该反序列化时则反序列化,最终推到客户端请求的参数值时,Payload就构造出来了。