背景
今天在刷朋友圈的时候看到有朋友通过使用一个第三方程序发起了一个默契挑战,挑战成功可以获得一张奶茶兑换券。很显然,作为从小一起长大的好朋友,那这个默契我是必须拿下的。
整体业务介绍
进入程序后(识别二维码),会进入一个答题界面,总共10道题,正确率>=80%则可以获得奖励。界面大概如下图,限制了仅能在微信环境内打开:
渗透思路
对于问答类的功能渗透,通常能够出现的逻辑问题是服务端将问题+答案一并传回给了前端,由前端校验后上传分数,最终导致的问题。这类问题引起的原因有多种,有时候是设计错误,有时候是业务需求:
- 问答类型:考虑前端用户的网络环境不稳定,业务提出将判断逻辑传回给前端给用户更好的体验
- 计分类型:实时的传输每一个步骤和分数,对于后端的架构挑战较大,前端计算完成后给后端一个整体分数记录即可
- 关卡类游戏:类似羊了个羊,用户重放上传的结果,导致可以刷取通关次数
实战
微信浏览器流量劫持
由于必须通过微信的浏览器打开,传统的通过浏览器设置代理的方式劫持流量已经无法执行,只能通过其他的方式进行,无非核心逻辑是能准确获取微信浏览器的流量,并使得相关的中间人CA证书能被系统信任。
互联网上相关的教程相当多,大多是通过proxifer+burp/fiddler的方式,这里就不再花更多的篇幅进行步骤介绍。我个人喜欢用Surge+Yakit的组合搭配,大概的设置方式如下:
Surge开启增强模式,微信浏览器访问相关网站,在Dashboard中找到对应的流量信息:
针对找到的进程设置规则,在本次的示例中是WechatAppEx Helper
这个进程,对于这个进程的流量使用Yakit这个策略:
Yakit的策略应当为对应的MITM的监听端口即可,我本地设置的是8083:
Yakit的MITM设置:
代码审计
以上的操作完成后,再次进入答题页面,你将能看到流量被正常的捕获并进入了Yakit软件:
接下来的操作就很简单了,和使用burp一样,通过页面上显示的题目中包含的字符,在流量中进行查询,看是否能找到相关的代码,通常而言,判断的逻辑会在js代码中,有时候需要注意的是如果是中文,需要考虑转义后的字符搜索。
在这次的案例中,由于项目比较简单,开发人员直接在页面内内嵌了script,也是直接发现了问题和答案的踪迹。根据如下的代码显示,数组从0开始,每一个问题的答案对应selected_option和options
即可得到。
最终的答案也是在意料之中….
成功收获今天的第一杯奶茶:
后续
对于问答/游戏类型的业务场景,多数情况下都是类似的解决方案,多去思考开发人员和业务人员在这个场景下的开发逻辑,再进行渗透测试可能就会有惊喜。
在完成答题后,发现在最终的界面,开发者还留了一个场景,说支付1.9元可以查看整体的答案和偷看其他人的答案…
同样的逻辑,在js中翻业务逻辑,虽然没有发现0元购的可能,但是发现开发者只是很简单的将支付是否成功做了一个unlock_status的标记:
在传统的pen-test中,可以直接在控制台通过控制unlock_status绕过这个限制即可,但是由于微信浏览器的限制,我们无法打开控制台,所以可以考虑通过Yakit修改返回包来绕过。修改字段值或者直接让条件永久成立都是可以的。
这里我们翻一下上面的代码,找到user_id,我们让这个值永久等于master_id即可绕过:
在Yakit中添加一个规则:
再次刷新页面,即可绕过支付:
MITIM的规则写的稍微有点宽泛也不太好理解,也可以通过交互插件或者自己写一个MITM插件进行更为精细化的控制,都可以:
发表回复