首届“虎符网络安全赛道”已告一段落,本次比赛Web赛题为一道php、两道NodeJS,考虑到官方公布的writeup过程过于简洁,本着分享及进步为原则,特对web赛题做一次详细解析,以供各位CTF爱好者解读涨知识;
第一题:easy_login
知识填充
Node.js即运行在服务端的 JavaScript;
Node.js的框架目录结构:(注:一般NodeJS的项目,访问app.js即可访问主文件的代码,而主要的逻辑代码在controllers/api.js中)
JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案,由三段信息构成的,将这三段信息文本用.
链接一起就构成了Jwt字符串。JWT=header+payload+signature(以.相隔):
初探题目
发现注册账号名为:admin,会报错:
注册用户名:test 密码:test ,使用账号进行登录:
点击“GET FLAG”,提示:
发现登录请求会带一个jwt token,根据题目提示依赖库出错,大胆联想跟jwt 库有关,因为js依赖库与官方对比无差异,而且admin不允许注册为线索,Getflag思路是token伪造为admin权限进而获取flag。
Token解析如下:
jwt token的攻击方式大概三种思路:
-
算法改成none,不要添加签名值;
-
原来加密算法为RSA256,尝试把加密散发改成HS256;
-
弱密钥暴力破解;
源码分析
查看目录结构发现有app.js文件:
尝试NodeJS文件包含,可以看到app.js源码:
http://a2cccfd1-3e79-4b73-9218-7cce979059e0.node3.buuoj.cn/app.js
继续利用文件包含,即:
http://a2cccfd1-3e79-4b73-9218-7cce979059e0.node3.buuoj.cn/controllers/api.js
注册代码片段
通过代码审计,发现注册就会生成一个jwt token;secret(密钥)随机生成,并有对应的secretid(索引号);
登录代码片段
经过分析源码,得到两个信息:
1.要求 sid 不能为 undefined,null,并且必须小于全局变量 secrets 数组的长度和大于等于0,sid是secret的索引号;
2.尝试构造加密算法为none,没有签名值的token进行伪造,结果失败,猜测原因跟secret有关,即跟sid(在token中为secretid)有关;
综上,想让secret为空,就需修改secretid,使其无法作为全局变量 secrets 数组的索引,那么 secret 就为空。另外,JS是一门弱语言,只要将sid=[],就可以满足以上全部条件;
构造payload获取flag
生成一个 secretid 为空数组的token,username 设置为admin,加密方式为 none,即可绕过验证,使得最后登录时验证的用户名为 admin,成功获取flag。
运行生成如上格式的token脚本:
运行结果:
eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJzZWNyZXRpZCI6W10sInVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6InRlc3QiLCJpYXQiOjE1ODcyOTc2NzZ9.
使用token解析工具确认一下:
使用该token进行替换原来的token进行登录(注:用户名跟密码要跟token中的值保持一致):
成功获取到flag:
总结反思
本次赛题中,有两道新兴语言nodejs,预示着我们要扩宽知识面技能树;第一题的突破口需要掌握nodejs的常见目录结构,才能通过文件包含读取源码,审计出token效验绕过规则进而执行jwt token伪造攻击最终获取flag。
扫码关注
工具开发等安全领域,致力于分享精品原创文章、漏洞复现、工具靶场、CTF等技术干货。
原文始发于微信公众号(SK安全实验室):虎符杯(HFCTF)writeup超详解-Web篇(上)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论