零、前言
在web界面登陆时,小程序和app传输数据时经常会碰到签名,会对请求的参数进行签名,如果自己修改了数据包就会校验失败非常麻烦。
本文编写的契机就是因为碰到了一个JeecgBoot的小程序, 想请求信息泄露的url但是显示“Sign签名校验失败”,让我非常无语,到手的漏洞飞了。所以打算研究一下签名,本文讲的是md5签名,以后再研究研究aes加密传输数据啥的。
一、环境准备
本文测试环境为JeecgBoot,代码链接:jeecgboot/Github
环境配置链接:IDEA启动项目 – JeecgBoot 文档中心
配置好依赖和数据库后启动后端:org.jeecg.JeecgSystemApplication
启动Vue3前端,点击dev,Jeecg启动!
二、阅读代码(后端)
关于签名函数的位置我不太会定位,是通过网络搜索找到的。
最终定位到SignAuthConfiguration
、SignAuthInterceptor
和SignUtil
等类。
1. SignAuthConfiguration
SignAuthConfiguration关键代码
boolean isSigned = SignUtil.verifySign(allParams,headerSign);
if (isSigned) {
log.debug("Sign 签名通过!Header Sign : {}",headerSign);
return true;
}
调用了verifySign进行校验签名,如果isSigned为true,签名通过。
2. SignUtil.verifySign
SignUtil.verifySign代码
public static boolean verifySign(SortedMap params,String headerSign) {
if (params == null || StringUtils.isEmpty(headerSign)) {
return false;
}
// 把参数加密
String paramsSign = getParamsSign(params);
log.info("Param Sign : {}", paramsSign);
return !StringUtils.isEmpty(paramsSign) && headerSign.equals(paramsSign);
}
经过调试得出params的内容是get和post请求参数的总和:
调用了getParamsSign来进行校验签名。
3. SignUtil.getParamsSign
SignUtil.getParamsSign关键代码
String signatureSecret = jeecgBaseConfig.getSignatureSecret();
return DigestUtils.md5DigestAsHex((paramsJsonStr + signatureSecret).getBytes("UTF-8")).toUpperCase();
对http请求参数paramsJsonStr加上signatureSecret的值,进行md5运算,最后对md5值大写处理。
signatureSecret的值在org/jeecg/config/JeecgBaseConfig.java
里:dd05f1c54d63749eda95f9fa6d49v442a
4. 最后
getParamsSign返回签名计算后的数据,verifySign对后端计算的sign和http请求头的X-Sign进行比较,如果相同则sngn校验通过,返回true。
实践一下
获取验证码处抓包,清除掉多余请求头。
POST /jeecgboot/sys/sms HTTP/1.1
Host: 192.168.171.1:3100
X-Sign: 1478A8A6639F1495342C603DC05BAEB7
X-TIMESTAMP: 1732282707313
Content-Type: application/json;charset=UTF-8
{"mobile":"13066668888","smsmode":"1"}
处理后,可以看到和X-Sign值一样。
所以JeecgBoot的签名逻辑就是把请求内容加上密钥,然后再进行md5计算,最后大写字符,就得到了X-Sign字符。
三、阅读代码(前端)
打开开发者工具,全局搜索secret,可以看到签名密钥
const signatureSecret = 'dd05f1c54d63749eda95f9fa6d49v442a';
文件位置:/src/utils/encryption/signMd5Utils.js
在signMd5Utils.js的第43行可以看到签名逻辑
return md5(JSON.stringify(requestBody) + signatureSecret).toUpperCase();
调试后可以看出签名逻辑和后端一样,都是将请求内容加上密钥,然后md5再大写处理。
四、关于参数顺序的问题
上面只测试了POST请求体的参数,如果通过url传参该怎么加密呢?
这里通过后端调试可以看出,参数是按照(数字,大写字母,小写字母)的顺序来排序的。
URL的参数为:1papam=0&Zparam=1&aparam=2&nparam=3
请求体为:{"mobile":"13066668888","smsmode":"1"}
最终整合成json,得到的数据为:
{"1papam":"0","Zparam":"1","aparam":"2","mobile":"13066668888","nparam":"3","smsmode":"1"}
请求
后端log:log.info("Param paramsJsonStr : {}", paramsJsonStr)
五、Yak
随便写了点yakit的热加载代码,现在才知道yaklang功能很强大,但还是不太熟练,所以实战用处不大。
func sign(mobile) {
return codec.Md5(f`{"mobile":"${mobile}","smsmode":"1"}dd05f1c54d63749eda95f9fa6d49v442a`).Upper()
}
func sign(param) {
return codec.Md5(f`${param}dd05f1c54d63749eda95f9fa6d49v442a`).Upper()
}
POST /jeecgboot/sys/sms HTTP/1.1
Host: 192.168.171.1:3100
X-Sign: {{yak(sign|{"mobile":"13066668888","smsmode":"1"})}}
X-TIMESTAMP: {{timestamp(ms)}}
Content-Type: application/json;charset=UTF-8
{"mobile":"13066668888","smsmode":"1"}
六、参考文章
jeecg 请求url签名_signauthconfiguration
1.本站内容仅供参考,不作为任何法律依据。用户在使用本站内容时,应自行判断其真实性、准确性和完整性,并承担相应风险。
2.本站部分内容来源于互联网,仅用于交流学习研究知识,若侵犯了您的合法权益,请及时邮件或站内私信与本站联系,我们将尽快予以处理。
3.本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
4.根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
5.本站是非经营性个人站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途
暂无评论内容