注:本文相关漏洞均已报告SRC 并完成修复
前言
近几年工作转型,已经很久没挖过漏洞,突然想检验一下自己当前是否还有挖洞能力。因此本次以挖到某个大型厂商一个中危级别以上漏洞作为目标,最终挖到了一个低危(存储 xss) + 一个高危 (任意文件读取),完成了本次目标。同时将整个过程较完整的思路记录下来,供大家参考。
前期思路
该企业有着多年的自身安全建设及SRC 运营,如果以渗透测试的思路拿机器权限绝非易事(渗透测试思路请参考此前发到乌云drops 的一篇文章:渗透中寻找突破口的那些事https://blog.csdn.net/hrayha/article/details/104887524),且常见的反射xss,sql注入等问题估计早已被内部扫描器、自身及外部安全人员挖的差不多,我就以逻辑类漏洞作为主要挖掘方向。
寻找目标
既然要寻找逻辑类漏洞,首先要寻找功能比较复杂的站点,通过搜索引擎搜索site:xxx.com,发现这么一个站点:
通过域名git.xxx.com 可初步判断为是一个类似gitlab的代码托管平台,此类平台一般会涉及到用户管理、文件管理、项目管理等功能,可测试的种类多样,因此将目标定在这个系统上,深入测试每一个功能,直到挖到中危以上漏洞完成目标。
登录系统后可看到左侧功能菜单如下:
可以看到功能还是比较丰富的,需要注意的一点是测试全程开启抓包工具,我这里使用的是fiddler,目的是可以抓取一些接口地址进行测试,以及方便改包重放。
我们顺着提示,先初始化git 账号,设置用户名时随便输入了test,提示用户名已存在,这里一定是调用了接口查询后端数据库或缓存,返回fiddler 看到如下请求:
此时我们可以做一个基本的sql注入测试,此处属于字符型,一般我会直接在后面加单引号,因为在数据库查询中,如果引号带入的话会触发语法错误而造成页面的异常响应,我们通过页面响应是否异常即可初步判断是否存在sql 注入,结果如下:
通过文案提示可发现后端对用户名格式做了判断,这里的返回结果,除了sql注入外,xss需要的引号,尖括号也无法带入,因此用户名的xss测试也省了,不过这也是符合预期的,如果这样就挖到漏洞,我估计一定是他们自身的扫描器挂了。后面对于大多数的接口测试思路基本如此,不做赘述。
来到"项目"功能,先创建项目,做如下填写:
这里简单说明下,前面的aaaaa、bbbbb主要是方便对返回结果搜索来定位过滤情况,不同的功能用不同字母主要是为区分不同功能点的过滤情况,">用来判断目标系统对敏感字符的过滤情况,标签作为大部分白名单标签可观察目标系统是否支持白名单标签。
提交后出现如下提示:
这里一般分为前端判断与后端判断两种情况:
1.前端判断的话我们可以通过改包重放来绕过限制;
2.后端判断可以忽略对相关功能点测试。
我这里看到了对应的请求包,所以可判断本处为后端判断,所以只进行描述字段的相关测试,提交请求后返回结果如下。
这里我发现一个比较可喜的现象,那就是虽然过滤了尖括号,但是img 标签被正常解析,说明此处支持白名单,在接下来我又分别做了一些测试,结果如下:
测试payload |
返回结果 |
说明情况 |
<img src=1 onerror1=alert(1)> |
<img src="HRay2/aaaa/1"> |
对onerror属性过滤 |
<img src=1 aaa=1> |
<img src="HRay2/aaaa/1"> |
对属性的过滤非黑名单而是白名单 |
<img/src=1/onerror=alert(1)> |
<img/src=1/onerror=alert(1)> |
以 / 分隔属性会直接转义尖括号 |
<bbbbbb> |
空 |
非白名单标签过滤为空 |
<bb<bbb>bbbb> |
<bbbbbb> |
执行对非白名单标签过滤后会转义尖括号 |
<img src=javascript:xxxxx> |
<img> |
白名单属性内依然有过滤 |
<img src=javas<aaaa>cript:xxxxx> |
<img src=javascript:xxxxx> |
执行对非白名单标签过滤后转义尖括号动作无视黑白标签 |
<img src=jAvascript:xxxxx> |
<img> |
过滤无视大小写 |
<img src=aaaa:xxxxx> |
<img> |
非基于黑名单的过滤 |
这里的输出点我们需要依赖尖括号,且目前看来只能使用白名单标签+白名单属性,暂时无法利用,所以我们继续看其他功能点。
经过一些类似测试后,我们来到了项目组功能,在项目组的描述文件功能处又遇到了与刚才相同的过滤,不过这个时候我比刚才多做了一个尝试。
目的是想深入看一下白名单属性内的过滤情况,结果如下:
我们输入的内容被完整的输入,说明白名单属性内,对尖括号是没有做过滤的。
在html中,有些标签是可以优先闭合的,比如下面这段代码
<html>
<title>
<ahref="1</title><script>alert(1)</script>"></a>
</html>
这段代码在实际解析中会把<ahref="1作为<title>标签中的部分,从而完成无双引号的闭合。
本处无法在上面插入有效的title标签,理论上不可利用,但是当我直接测试如下payload 时:
奇迹出现了:
经过后端的逻辑处理后插入的script 标签竟然直接跳出了a 标签,到了这里大家可能以为把script 标签内容改为alert(1) 就解除了,事实并非如此,我发现script 标签内的符号都会被url 编码处理,比如:
我们通过插入
aaaaaa<ahref="1<title><script>aa`~@#$%^&*()-+=_[]{}|/?</script>"> 来测试符号的url 编码情况,结果如下:
开始想通过<scriptsrc=xxx.js>的方法实现,且该站点本身就提供写文件的功能,可以天然绕过同源限制,不过被浏览器拦截
查了一下,大概是因为这里写入的js 以 raw格式查看返回的是 text格式,与 script标签内要求的 javascript类型不符导致,查找无url 编码符号的payload,最后找到这么一个:
aaaaaa<ahref="1<title><iframe/src=data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=>">
成功完成弹窗。
不过后来这个被评为低危,因为poc 是在data:text 下执行的,无法获取用户信息,后来我又找到这么一段poc
aaaaaa<ahref="1<title><script>throw/a/,Uncaught=1,g=alert,a=URL+0,onerror=eval,/1/g+a[12]+[1337]+a[13]</script>">
说明:后面读了测试规范,发现官网其实是严禁弹窗测试的,希望大家后面注意,尽量使用console.log 来做测试。
不过这样停止总觉得有点勉强,那就继续再挖一下看看吧。
因为xss的价值比较低,所以后面的测试着重去找一些偏逻辑、水平权限或者敏感接口类的问题,以下思路为测试后没成功,但是我觉得对web 安全测试来说还是需要关注的点。
1.我们随便打开一个页面的时候,查看网页源代码,会发现有这么一段内容:
这里面包含一个id,并且通过这段内容以及观察其他一些参数的格式,估计可能会存在一个参数名为user_id 的隐藏参数,之前发现过这么一个例子,就是站点本身的一系列操作都是解析session 内容来获取用户对应身份进行操作,但是当你主动去传递一个类似user_id 这么一个参数时,程序会去执行传递的user_id 对应用户的操作,这就导致了水平权限的问题,这种问题的成因有可能是早期程序逻辑就是根据传参的userid 去执行操作,后期改成session,但只是去掉了默认的参数传递,并没有完全从后端去掉这部分逻辑。
2.在cookie 中存在这么一个字段:
熟悉的小伙伴可能一眼就能认出这是一段base64 的密文。
这段密文解密后的内容格式为:
Username:毫秒级时间戳:32位md5。
其中md5 没有解密成功,不多做猜测,前面讲到程序一般从session 获取用户身份信息执行对应操作,当然也可能是从cookie 中某个字段去取值,所以可尝试将username 部分替换为其他用户信息(这里替换为自己小号用户名),替换后使用base64 加密并替换对应字段内容,同时也可以尝试将用户名后面加单引号,用来测试一些隐藏的sql 注入。
3.测试过程中抓到这么一个接口:
https://git.xxx.com/search/autocomplete/users/1xxxx.json
看起来可以获取一些基本信息,中间的users 这里,有可能会存在一些类似的隐藏接口可以获取一些敏感信息,比如把users 换成tokens 等。
经过一系列失败的测试后,我看到了一个让我眼前一亮的功能,在我们使用客户端提交commit 的时候,可以选择调用一个bash 脚本来检查commit 描述是否符合特定规范,比如必须要使用--bug=xxx类似的格式(由于很多图都是提交报告后补截的,这个功能在我报告后很快就下掉了,所以此处只能靠文字描述)。开始想着此处可能要出rce ,不过这个bash 脚本是官方写死的,无法更改。最后在查看fiddler 时被我抓到了一个读脚本内容的接口。
本能的尝试读取/etc/passwd。
哈哈,运气不错,抓到了一个文件读取,并且是root 权限,从root 的 history文件里读到了 log文件路径。
到这里足以证明危害,所以马上报告给了官方src,响应也很快,周末的时候也可以及时完成止损,下掉了对应功能,这个漏洞被官方评定为高危级别,因此本次测试目标达成,至此告一段落。
刚开始工作的时候,有幸跟0x557 的la0wang 在一起工作,当时做项目感觉老王总是能用很短的时间挖到可以getshell的漏洞,并且很多漏洞并没不复杂,自己也能看懂,就是挖不到,当时感觉是运气不好,随着工作年头的增加逐渐明白那是因为常年的积累,对各种系统、各种程序的逻辑了解的足够深刻,了解哪里容易出现问题才做到的。漏洞本身源于对外部可控因素的过滤或校验不严格,我们需要通过不断积累各种知识来深入理解哪些是我们可控的,可控的因素会带入到哪里,可能经过哪些地方,才能更多的挖掘到别人挖不到的漏洞。人工测试过程中,我们要多去思考程序可能的逻辑是怎样的,而不应该机械化的看到id=xx这种就加个单引号,看到输入框就往里加标签,这样人的效率自然拼不过机器。所以本文尽可能比较完整的描述了整个测试的思考流程,希望可以给大家带来参考价值。最后打个小广告,C轮融资的互联网企业,招一枚渗透测试工程师,大家可以把简历发送至[email protected]感谢大家的阅读。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论