<导航

接口安全设计

一、重放攻击

  入侵者从网络上截取主机A发送给主机B的报文,并把由A加密的报文发送给B,使主机B误以为入侵者就是主机A,然后主机B向伪装成A的入侵者发送应当发送给A的报文。

  它是一种攻击类型,这种攻击会不断恶意或欺诈性地重复一个有效的数据传输,重放攻击可以由发起者,也可以由拦截并重发该数据的敌方进行。攻击者利用网络监听或者其他方式盗取认证凭据,之后再把它重新发给认证服务器。从这个解释上理解,加密可以有效防止会话劫持,但是却防止不了重放攻击。重放攻击任何网络通讯过程中都可能发生。重放攻击是计算机世界黑客常用的攻击方式之一。

1、防御手段

防止重放攻击的方法是使用不重数。

1. 加随机数
该方法优点是认证双方不需要时间同步,双方记住使用过的随机数,如发现报文中有以前使用过的随机数,就认为是重放攻击。缺点是需要额外保存使用过的随机数,若记录的时间段较长,则保存和查询的开销较大。

2. 加时间戳
该方法优点是不用额外保存其他信息。缺点是认证双方需要准确的时间同步,同步越好,受攻击的可能性就越小。但当系统很庞大,跨越的区域较广时,要做到精确的时间同步并不是很容易。

3. 加流水号
就是双方在报文中添加一个逐步递增的整数,只要接收到一个不连续的流水号报文(太大或太小),就认定有重放威胁。该方法优点是不需要时间同步,保存的信息量比随机数方式小。缺点是一旦攻击者对报文解密成功,就可以获得流水号,从而每次将流水号递增欺骗认证端。

在实际中,常将方法(1)和方法(2)组合使用,这样就只需保存某个很短时间段内的所有随机数,而且时间戳的同步也不需要太精确。
对付重放攻击除了使用本以上方法外,还可以使用挑战一应答机制和一次性口令机制,而且似乎后面两种方法在实际中使用得更广泛。

提问与应答

“现时”──与当前事件有关的一次性随机数N(互不重复即可)

基本做法──期望从B获得消息的A 事先发给B一个现时N,并要求B应答的消息中包含N或f(N),f是A、B预先约定的简单函数

原理──A通过B回复的N或f(N)与自己发出是否一致来判定本次消息是不是重放的。类似一次性口令机制,也适用于接口幂等处理。

2、HTTPS数据加密是否可以防止重放攻击?

  否,加密可以有效防止明文数据被监听,但是却防止不了重放攻击。

3、防御处理实现

timestamp+nonce

  我们常用的防止重放的机制是使用timestamp和nonce来做的重放机制。
  timestamp用来表示请求的当前时间戳,这个时间戳当然要和服务器时间戳进行校正过的。我们预期正常请求带的timestamp参数会是不同的(预期是正常的人每秒至多只会做一个操作)。每个请求带的时间戳不能和当前时间超过一定规定的时间。比如60s。这样,这个请求即使被截取了,你也只能在60s内进行重放攻击。过期失效。
但是这样也是不够的,还有给攻击者60s的时间。所以我们就需要使用一个nonce,随机数。
nonce是由客户端根据足够随机的情况生成的,比如 md5(timestamp+rand(0, 1000)); 也可以使用UUID, 它就有一个要求,正常情况下,在短时间内(比如60s)连续生成两个相同nonce的情况几乎为0。

服务端

  服务端第一次在接收到这个nonce的时候做下面行为:
1 去redis中查找是否有key为nonce:{nonce}的string
2 如果没有,则创建这个key,把这个key失效的时间和验证timestamp失效的时间一致,比如是60s。
3 如果有,说明这个key在60s内已经被使用了,那么这个请求就可以判断为重放请求。
示例
那么比如,下面这个请求:
http://a.com?uid=123&timestam...
这个请求中的uid是我们真正需要传递的有意义的参数
timestamp,nonce,sign都是为了签名和防重放使用。
timestamp是发送接口的时间,nonce是随机串,sign是对uid,timestamp,nonce(对于一些rest风格的api,我建议也把url放入sign签名)。签名的方法可以是md5({秘要}key1=val1&key2=val2&key3=val3...)
服务端接到这个请求:
1 先验证sign签名是否合理,证明请求参数没有被中途篡改
2 再验证timestamp是否过期,证明请求是在最近60s被发出的
3 最后验证nonce是否已经有了,证明这个请求不是60s内的重放请求

web层面也可以采用在页面中加入token方式,手机验证码,滑动验证码等方式来防止攻击。


接口安全问题

  • 请求身份是否合法?
  • 请求参数是否被篡改?
  • 请求是否唯一?

二、AccessKey&SecretKey (开放平台)

1、请求身份

  为开发者分配AccessKey(开发者标识,确保唯一)和SecretKey(用于接口加密,确保不易被穷举,生成算法不易被猜测)。

2、防止篡改

参数签名

  1. 按照请求参数名的字母ascii码升序排列非空请求参数(包含AccessKey),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA;
  2. 在stringA最后拼接上Secretkey得到字符串stringSignTemp;
  3. 对stringSignTemp进行MD5运算,并将得到的字符串所有字符转换为大写,得到sign值。

  请求携带参数AccessKeySign,只有拥有合法的身份AccessKey和正确的签名Sign才能放行。这样就解决了身份验证和参数篡改问题,即使请求参数被劫持,由于获取不到SecretKey(仅作本地加密使用,不参与网络传输),无法伪造合法的请求。

3、重放攻击

  虽然解决了请求参数被篡改的隐患,但是还存在着重复使用请求参数伪造二次请求的隐患。

timestamp+nonce方案

  nonce指唯一的随机字符串,用来标识每个被签名的请求。通过为每个请求提供一个唯一的标识符,服务器能够防止请求被多次使用(记录所有用过的nonce以阻止它们被二次使用)。

  然而,对服务器来说永久存储所有接收到的nonce的代价是非常大的。可以使用timestamp来优化nonce的存储

  假设允许客户端和服务端最多能存在15分钟的时间差,同时追踪记录在服务端的nonce集合。当有新的请求进入时,首先检查携带的timestamp是否在15分钟内,如超出时间范围,则拒绝,然后查询携带的nonce,如存在已有集合,则拒绝。否则,记录该nonce,并删除集合内时间戳大于15分钟的nonce(可以使用redis的expire,新增nonce的同时设置它的超时失效时间为15分钟)。

实现


请求接口:http://api.test.com/test?name=hello&home=world&work=java

客户端

1、生成当前时间戳timestamp=now和唯一随机字符串nonce=random

2、按照请求参数名的字母升序排列非空请求参数(包含AccessKey)

  stringA="AccessKey=access&home=world&name=hello&work=java&timestamp=now&nonce=random";
3、拼接密钥SecretKey
  stringSignTemp="AccessKey=access&home=world&name=hello&work=java&timestamp=now&nonce=random&SecretKey=secret";
4、MD5并转换为大写
  sign=MD5(stringSignTemp).toUpperCase();
5、最终请求
  http://api.test.com/test?name=hello&home=world&work=java&timestamp=now&nonce=nonce&sign=sign;
服务端

 

三、Token&AppKey(APP)

  在APP开放API接口的设计中,由于大多数接口涉及到用户的个人信息以及产品的敏感数据,所以要对这些接口进行身份验证,为了安全起见让用户暴露的明文密码次数越少越好,然而客户端与服务器的交互在请求之间是无状态的,也就是说,当涉及到用户状态时,每次请求都要带上身份验证信息。

1、Token身份验证

  1. 用户登录向服务器提供认证信息(如账号和密码),服务器验证成功后返回Token给客户端;
  2. 客户端将Token保存在本地,后续发起请求时,携带此Token
  3. 服务器检查Token的有效性,有效则放行,无效(Token错误或过期)则拒绝。

安全隐患:Token被劫持,伪造请求和篡改参数。

2、Token+AppKey签名验证

  与上面开发平台的验证方式类似,为客户端分配AppKey(密钥,用于接口加密,不参与传输),将AppKey和所有请求参数组合成源串,根据签名算法生成签名值,发送请求时将签名值一起发送给服务器验证。这样,即使Token被劫持,对方不知道AppKey和签名算法,就无法伪造请求和篡改参数。再结合上述的重放攻击解决方案,即使请求参数被劫持也无法伪造二次重复请求。

实现

登陆和退出请求

后续请求

    • 客户端
      和上述开放平台的客户端行为类似,把AccessKey改为token即可。

    • 服务端

 

 

 

参考文章:

https://www.jianshu.com/p/7887f16581c0

https://segmentfault.com/a/1190000014821815

https://blog.csdn.net/qq_18495465/article/details/79248608

 

posted @ 2020-01-16 16:36  字节悦动  阅读(1296)  评论(0编辑  收藏  举报