由网站验证码而想到的……。
网站验证码的作用是防止暴力破解用户名密码或用机器人灌水。
主流的写法都是在服务器生成一个随机串,然后将随机数生成图片,发至客户端,然后再将随机数加密用Cookies传到客户端。
在用户提交回来的信息中检查用户输入数的加密值是否与Cookies中的值相同来验证的。
不过我发现这种写法有相当大的漏洞。其结果是即麻烦了客户而又没有达到目地。
因为:
客户端可以重复发送一个相同的post/cookies验证串来达到目地。
举个例子,
第一步,正常访问
可以得到一个验证码和一个存在cookies中的验证串。
第二步,将二个值放入暴破/灌水机器人中。
这样,机器人就可以每次请求都使用这对正确的值。而验证码系统将失效。
为什么会出现这种情况呢?
一、因为Web的任意二次请求/响应没有必要的因果关系。所以即使请求需要凭证也无法验证凭证是何时发布的,是发给哪个客户端的。(实际上,这会引起更大的问题,我会在后面讲到)
二、凭证与校验两个值同是发送至各户端;这样就给了客户端伪造的机会。客户端不需要知道凭证与校验之间的转换算法。只需拥有一对正确的凭证/校验数据就够了。
以上二点是所有网络应用都应当注意的问题,可见,如果要相使你的验证码有效,就必须将校验串留在服务器端,而向客户端发送凭证和一个校验串的编号,凭证/校验串使用一次后立即过期。不过随之而来的是你要如何保存校验串和校验串编号。用内存?用数据库?开销都是不小的。
然后我们再来看我说的第一点问题。如果你认为验证码的问题你可以忍受的话,那么我下面要说的可能会让你精心构建的网站安全系统有一种崩溃的意像。
我们都知道HTTP是一种非加密协议,所有HTTP的请求/响应都是在TCP通路上飞速“裸奔”。很早以前就出现过截取Web密码的软件,那时的网络大多基于HUB或是总线网络使得只要在网内的一台机器上使用截取软件就可以得到整个网络内所有的Web密码。而现在大多数网络基于交换机,这种方法显然失去了一部份市场。
有点跑题,回到我们的问题上来,我们知道ASP/ASP.NET和其它的WEB服务器技术的Session都是依据cookies换句话来说,现在所有Web技术的服务器验证都是将凭据发送到客户机这就出现了我刚才所讲的第二个问题:“凭证可以伪造”!掌握了相应SessionID就得到了服务器权限。
不过还好,SessionID的值都是随机的并且很长。不太可能被人猜解到,不过不要大意。如果你好心的为了方便你的访客访问你的网站而将其的Id/Key加密后放入cookies后那么问题就出现了。在客户机上是很容易得到访客的Id/Key所计算出的“凭证”的。这样即使不知道具体的密码,也可以在其它地点以这个用户登陆。而且这几个访问的SessionID和Id/Key完全相同,这会出现什么样的后果?你的网站的操作日志完全失效!因为所有的访问凭证都是相同的。你没办法区别哪些请求是真正访客的,哪些请求是攻击者的!
综上所述我总结了以下几点:
一、需要权限的访问一定需要凭证,而凭证一定需要校验。
二、校验一定需要保存在服务器上。并且,凭证与校验必须是一次性的。使用后立即过期。
三、不要相信任何客户端发来的结果,它们都可能是假的!
四、不要在cookies中长期保存任何凭证。它们只会增加风险。
五、如果你使用的是Asp/Asp.net请不要在网页上体现访客的SessionID。它们会造成伪造的机会。如果你使用的是其它技术,也一样。
六、对于需要高度安全的访问验证,请劝告你们的访客,不要在局域网内或使用不安全的代理访问你的网站。
一家之言仅供参考。