nonce和timestamp在Http安全协议中的做用

前段时间给客户网站作新浪微博帐号登陆功能,对OAuth协议以及相关的一些安全协议作了一些研究,顺便就记录一下学习心得吧。在这里就不打算具体讲OAuth的协议流程了,而是针对OAuth请求头里的nonce(随机数)、timestamp(时间戳)、signatrue(签名)这些参数的做用作一下总结。html

 

首先看一下HTTP规范里定义的Basic认证。算法

Basic认证及其安全问题数据库

Basic认证是一个流程比较简单的协议,整个过程能够分为如下三个步骤:浏览器

a) 客户端使用GET方法向服务器请求资源。安全

b) 服务器返回401响应码和WWW-Authentication:Basic realm=”Family”响应头要求客户端进行身份验证。其中realm声明了资源所在的域。服务器

c) 浏览器接收到以上HTTP响应头后,弹出登陆框要求用户输入用户名和密码;用户提交的用户名和密码经过冒号串联起来并对其进行BASE64编码后再提交到服务器;服务器对提交上来的BASE64字符串进行验证,若是验证经过则返回200响应码。网络

 

 

 

 

Basic认证虽然简单、方便,但它只能做为对非敏感资源的访问认证,由于它并不安全,主要表如今如下几个方面:工具

一、 客户端提交的用户名和密码只通过简单的编码,攻击者只要窃听到该数据包,即可很容易的将其反编码为原始用户名和密码。性能

二、 即便客户端使用了一种比BASE64更复杂的编码方式使得攻击者没法对其反编码,攻击者也可使用fiddler等工具将拦截到的HTTP报文从新提交给服务器,服务器只对编码的字符串进行验证,因此验证一样能经过。这种攻击方法称之为重放攻击(Replay-Attack)。学习

以上两个问题也是各类身份认证协议须要考虑到的安全问题,包括OAuth、Digest认证、NTLM认证等等认证机制都使用了nonce和timestamp来解决这些问题。

Nonce、Timestamp——解决Replay-Attack问题

Nonce是由服务器生成的一个随机数,在客户端第一次请求页面时将其发回客户端;客户端拿到这个Nonce,将其与用户密码串联在一块儿并进行非可逆加密(MD五、SHA1等等),而后将这个加密后的字符串和用户名、Nonce、加密算法名称一块儿发回服务器;服务器使用接收到的用户名到数据库搜索密码,而后跟客户端使用一样的算法对其进行加密,接着将其与客户端提交上来的加密字符串进行比较,若是两个字符串一致就表示用户身份有效。这样就解决了用户密码明文被窃取的问题,攻击者就算知道了算法名和nonce也没法解密出密码。

 

每一个nonce只能供一个用户使用一次,这样就能够防止攻击者使用重放攻击,由于该Http报文已经无效。可选的实现方式是把每一次请求的Nonce保存到数据库,客户端再一次提交请求时将请求头中得Nonce与数据库中得数据做比较,若是已存在该Nonce,则证实该请求有多是恶意的。然而这种解决方案也有个问题,颇有可能在两次正常的资源请求中,产生的随机数是同样的,这样就形成正常的请求也被当成了攻击,随着数据库中保存的随机数不断增多,这个问题就会变得很明显。因此,还须要加上另一个参数Timestamp(时间戳)。

 

Timestamp是根据服务器当前时间生成的一个字符串,与nonce放在一块儿,能够表示服务器在某个时间点生成的随机数。这样就算生成的随机数相同,但由于它们生成的时间点不同,因此也算有效的随机数。

 

问题又来了,随着用户访问的增长,数据库中保存的nonce/timestamp/username数据量会变得很是大。对于这个问题,可选的解决方案是对数据设定一个“过时时间”,好比说在数据库中保存超过一天的数据将会被清除。若是是这样的,攻击者能够等待一天后,再将拦截到的HTTP报文提交到服务器,这时候由于nonce/timestamp/username数据已被服务器清除,请求将会被认为是有效的。要解决这个问题,就须要给时间戳设置一个超时时间,好比说将时间戳与服务器当前时间比较,若是相差一天则认为该时间戳是无效的。

HTTP消息体的加密

         很不幸的是,通过上面这些复杂的处理后,咱们的数据传输仍然是不安全的。咱们都知道,http报文是以明文的方式在网络中传输的,包括Basic认证、Digest认证、OAuth、NTLM等等验证这一些认证机制都只是对HTTP头的信息做保护,而对于Http消息体的数据却没有做加密。以新浪首页的登陆为例,它的帐号就是以明文的方式传送的,以下图所示:

 

 

 

这样的方式是很不安全的,用户名和密码彻底以明文的方式提交了。一样是新浪的网站——新浪微博就在登陆前做了加密过的,以下图所示:

 

 

 

 

 

加密的方法能够参考前面讲到的nonce+timestamp的方案。不过这只解决了登陆的问题,在注册时就不能提交使用nonce和timestamp非可逆加密了,这个时候要使用非对称加密。在用户打开注册页时,服务器生成一个公钥/私钥对并将公钥返回给客户端,客户端使用该公钥将密码加密后提交到服务器,服务器使用私钥解密后再保存到数据库。非对称加密算法的特色是每个公钥和私钥都是一一对应的,使用公钥加密后只有拥有私钥的人才能进行解密,因此攻击者截取到http报文也毫无用处。

         固然,在条件容许的状况下,可使用SSL来实现HTTP报文的加密,这种方案是在应用层和传输层中间添加一个SSL层,该层使用对称加密的方法将HTTP报文加密后再传递到传输层,以下图所示:

 

 

 

在这以前,客户端与服务器须要使用非对称加密的方法来协商用于对称加密的公钥,对称加密要求加密者和解密者拥有同一个密钥(即公钥)。当客户端首次访问页面时,须要生成一个公钥给服务器,而这个公钥不是不能够给第三方知道的(知道了这个公钥就可对数据进行解密了),因此须要服务器首先生成一个公钥/密钥对,并使用生成的公钥加密客户端生成的公钥(非对称加密),这一个过程与前面讲到的注册密码加密的方式相似。

正由于在正式数据传输以前须要在服务器跟客户端之间进行几轮的协商,因此HTTPS相比HTTP来讲安全性会高些、而性能会差些。

转自:http://www.cnblogs.com/bestzrz/archive/2011/09/03/2164620.html

相关文章
相关标签/搜索