先来给出几个定义,什么是cookie,session 和验证码。
Cookie(复数形态Cookies),中文名称为“小型文本文件”或“小甜饼”,指某些网站为了辨别用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)。
一个访问者访问你的 web 网站将被分配一个唯一的 id, 就是所谓的会话 id. 这个 id 可以存储在用户端的一个 cookie 中,也可以通过 URL 进行传递.
全自动区分计算机和人类的公开图灵测试(英语:Completely Automated Public Turing test to tell Computers and Humans Apart,简称CAPTCHA),俗称验证码,是一种区分用户是计算机或人的公共全自动程序。在CAPTCHA测试中,作为服务器的计算机会自动生成一个问题由用户来解答。这个问题可以由计算机生成并评判,但是必须只有人类才能解答。由于计算机无法解答CAPTCHA的问题,所以回答出问题的用户就可以被认为是人类。
简单地说, cookie和session是用来识别用户身份的数据, cookie又可以分为保存在内存中的和保存在硬盘中的cookie, 保存在内存中的cookie在标签页关闭的时候会自动销毁, 而如果设定了cookie的过期时间, 那么cookie则会保存在硬盘中一段时间. 而且在同一浏览器中, cookie是可以共享的.
cookie的格式:
Set-Cookie:键1=值1;键2=值2;过期时间;作用域;作用路径;[secure]
作用域和作用路径是用来区分cookie的, 过期时间是告诉浏览器这个cookie在什么时候过期; 而 secure 标志则是当一个请求通过 SSL 或 HTTPS 创建时,包含 secure 选项的 cookie 才能被发送至服务器.
服务器端通过用户提供的cookie确认用户身份, 这就造成一个问题, 如果我知道你的cookie, 在cookie未过期的情况下, 那么我就可以伪造你, 而且一些敏感信息如果存放在cookie里, 就有可能通过一定的技术手段得到那些敏感信息. 因为cookie的存在是单向的. 而HTTP协议又是无状态的.
引入了session解决的也是HTTP协议无状态的问题, 不过他比浏览器cookie的好的地方在于, session在用户端只有一个值, 服务器 端存放着确认用户的信息, 理论上讲, 我如果知道了某个人的session, 则也可以伪造这个人, 不过我获取不到那些敏感信息. 比如cookie里存放着用户的密码的md5, 或着用户名, 或者id, 或者乱七八糟的东西. 其实session的存在也是借助于cookie的, 不过区别是原本的浏览器存放数据, 变成了服务器存放数据.
session在php里可以通过session_start()
函数生成, 生成的文件一般存放在/var/lib/php5/sessions
里面, 这个文件夹可以从phpinfo()
(session.savepath)中找到.
生成验证码的开源库已经有不少了, 我们没有必要自己造新的轮子. 这里我用的是Gautam kumar写的phptext.
2.1 表单 这是一个index.php文件:
<!DOCTYPE html>
<html>
<head>
<title>Test PHP captcha</title>
</head>
<body>
<form action="check.php" method="POST">
<img src="captcha.php?rand=<?php echo rand();?>">
<input type="text" style="display:inline;width:11%" name="captcha_code" placeholder="验证码"/>
</form>
</body>
</html>
然后, check.php里的是:
<?php
//phpcaptchasession_start();
// code for check server side validationif(empty($_SESSION['captcha_code'] ) || strcasecmp($_SESSION['captcha_code'], $_POST['captcha_code']) != 0){
echo "Wrong";
}else {
echo "Success";
}
?>
我本地的文件也打包放在这里了->代码文件
2.2 过程
打开主页面会有验证码和输入框:
然后我们故意输入一个错误的验证码提交过去:
输入正确的验证码:
大体流程就是这样.
为什么会这样呢?
首先我们看到, 在captcha.php
里面:
<?php
session_start();
include("./phptextClass.php");
/*create class object*/
$phptextObj = new phptextClass();
/*phptext function to genrate image with text*/
$phptextObj->phpcaptcha('#162453','#fff',120,40,5,10);
?>
开启了一个session, 然后服务器就会分给我们一个唯一的php session, 并且会在/var/lib/php5/sessions
文件夹下创建一个session文件. 在追查类文件, 会发现这样一段代码:
if(isset($_SESSION)){
$_SESSION['captcha_code'] = $text;/* set random text in session for captcha validation*/
}
这样就在session文件里写入了captcha_code,内容为验证码:
然后当你输入验证码的时候, check.php 就会比较你输入的验证码和服务器中你对应的session文件存放的验证码, 如果相同, 则返回成功, 否则返回错误.
对于上述的验证码, 破解的办法无非就是识别图形中的文字. 上一篇文章中提到过识别验证码的方法, 在这里就不多说了.
需要提的是, 有一些古老的站点还在用数字或者字母的文字验证码, 不是图片的那种的, 可以说一点安全性都没有… 直接抓出来就好了…
还有的是在服务端存放了一些验证码的图片, 把他们都抓出来然后基于哈希表就可以搞定. 在这个镜像里有一些验证码的题目, 感兴趣的可以做一下, 里面不仅仅是验证码呢~
除了上述这种最基本的验证码, 还有一些别的验证码, 比入基于行为的验证码, 让鼠标点几下, 或者拖动滑块的验证码. 对于这些验证码, 就没有什么很好的破解方法了, 除非模拟鼠标的动作, 还要点击拖动, 判断图片的正确位置, 好像挺麻烦的…