文章目录
- 一、问题描述
- 1、什么是重放攻击、篡改攻击?
- 2、如何模拟重放攻击、篡改攻击?
- 2.1、重放攻击模拟方式
- 2.2、篡改攻击模拟方式
- 二、解决方案
- 三、在项目中使用
- 1、项目简介
- 2、项目实践
一、问题描述
1、什么是重放攻击、篡改攻击?
1、重放攻击:请求被攻击者获取,并重新发送给认证服务器,从而达到认证通过的目的。
2、篡改攻击:请求被攻击者获取,修改请求数据后,并重新发送给认证服务器,从而达到认证通过的目的。
2、如何模拟重放攻击、篡改攻击?
2.1、重放攻击模拟方式
1、使用谷歌浏览器的F12工具,在“网络”中任意找一个已经发送过的请求,鼠标右键这个请求,就可以看到“重放XHR”选项了,这个就是请求重放,即:重新发送一次该请求。如下图所示:
2、借助抓包工具,例如:Fiddler。这里以Fiddler为例,打开Fiddler找到刚刚的请求,鼠标右键可以看到“Replay->Reissue Requests”选项,这个就是重放请求。如下图所示:
2.2、篡改攻击模拟方式
由于浏览器的局限性,并不是所有浏览器都提供修改请求的工具的。这里就以Fiddler为例,打开Fiddler找到刚刚的请求,鼠标右键可以看到“Replay->Reissue and Edit”选项,这个就是篡改请求。如下图所示:
二、解决方案
常见的技术方案有timestamp、nonce、timstamp+nonce、公钥+私钥等方式,这里就不展开聊了,因为这块资料实在太多了,如果需要了解的,可以参考以下资料:
1、防重放攻击方案介绍
2、RSA 加密,解密,签名,验签
三、在项目中使用
1、项目简介
由于项目比较老,使用的技术框架也相对落后,framework7+Spring+SpringMVC+Ibatis,根据现有项目的情况,进行技术选型,初步决定使用客户端使用私钥签名,服务端使用公钥验签,校验数据的有效性的方案。
2、项目实践
1、在framework7.js中,将所有ajax请求(POST类型)的data(即业务数据)进行MD5加密,并将加密后的签名放入header中传给服务端。
2、服务端在拦截器中接收到该请求后,将原始(未加密)的业务数据进行加密(注意:需要和客户端使用相同的加密算法和KEY),将加密后的内容与header中的签名进行比对,若一致,表示该请求有效,若不一致,则表示该请求为非法请求。
注:上面这种方案,在验证过程中有很多弊端,例如:
1、前后端参数顺序不一致导致的生成签名不一致。
产生原因:前端组装的参数传到后端时,参数的顺序大概率不一致。
解决办法:统一将前端参数按ASCII进行重排后再加密,后端也是如此,即可解决。
2、前后端自带json序列化API导致参数顺序错乱。
产生原因:参数重排后,在加密前,需要将参数转换为字符串后进行加密,就是这里转换出现的问题。
解决办法:进一步解析参数中的对象/数组,并进行ASCII重排,即可解决。
3、参数中空对象字符串转义后变成‘%7B%7D’。
产生原因:前端会将空对象进行转义,但是后端接收到空对象时并不会显示转义后的结果。
解决办法:在后端过滤掉空对象的情况。
4、数据中前后空格,导致前后端加密结果不同。
产生原因:参数中某些字符串类型的值前后面会有空格的情况,前端也会对空格进行转义。
解决办法:前后端都是用trim处理有空格的情况。
5、字符串存在"null"、字符串中间存在空格、特殊字符’\n’等情况。
产生原因:历史代码原因,有这种特殊的情况。
解决办法:前后端分别进行特殊处理。
6、参数中存在~!*()_.'等特殊符号不会被转义。
产生原因:前端特殊字符转义规则与后端有所不用,双方不一致,导致加密后的结果不一样。
解决办法:前后端分别将特殊字符进行过滤,过滤后的内容保持一致,保证加密的结果一致。
注:以上的问题都是在代码实现过程中遇到的,并且都找到解决办法了,但是这个改造的成本太大了,而且特殊情况太多,也是一个不稳定的因素,最终决定弃用这个方案。