验证码的认识和简单验证码的攻防

  验证码(CAPTCHA)一词,几乎是上网的人都接触过。通俗地将,验证码就是一种把坐在电脑前的人类与机器区分开来的测试,也算是一种最常见反图灵测试。一般来说,验证码由计算机生成,服务器端的计算机知道答案,但在网线这端,应该只有用户(即真正的人)知道答案,而计算机不知道。

  从上面的定义里,易得:

  • 验证码应该是不易被计算机识别或破解出来的,如果用简单的算法,也能得到极高的破解率(大于或接近于75%),则这个验证码不算一个合格的验证码。
  • 要攻破验证码,最好的方法应该是机器学习,因为这个方法能让计算机模拟人类的行为。通过一定的样本训练后,机器的识别度会接近人类。
  • 当然,要攻破验证码,找到一些没事干的人进行分布式验证码人肉识别(俗称“打码”),也是一个不错的方法,只不过这种方法需要投入金钱。
  • 要防御破解验证码的攻击,应该从其源头想起——验证码不就是区别人和机器么?那么,鼠标的细微移动,键盘的键入速度,用户(可有可能是电脑)看见验证码后的反应等等,都可以作为识别机器和人的证据。当然,对于验证码,添加一些机器能识别得到,而人类反而看不见的东西,也能很好地揪出那些干坏事的人。
  • 时刻记住,验证码是给人看的,所以要从人的角度破解、防御验证码(攻击)。

破解篇:

  当下,最流行的还是图形验证码。让我们来看几个简单的图形验证码,然后分析一下它们的共同点和弱点。

验证码 弱点
①有背景,但是色调很淡,干扰点的色调也很单一。
②最弱的验证码,没有任何杂点、背景等。但很久以前,很多论坛都盛行这种验证码。
③同样是没有背景,但是有了颜色随意的干扰点,略微提高了识别难度。
④有杂点,有背景,而且杂点还不少。只是验证码主题颜色单调。

  很显然,②是最简单的。识别这个验证码,只有一个步骤:匹配字模——直接循环匹配已有的所有的同字体的数据,找出最高的相似度(算法见附录0x01)。但是不是所有的验证码程序编写者都这么不负责。像①③④,虽然还是很简单,但至少可以难到新手们。

  但仔细观察可以发现,搅局者只是那些各色的背景和一些干扰点而已。要识别,还是很容易,只是要在②的基础上加上以下几步:

  1、图像预处理:遍历所有像素点,去除背景。由于验证码不像国宝熊猫那么黑白分明,其彩色的信息量极大,不便于处理,所以要二值化,是整张图片变成只含有0与1的矩阵。得到一个W*H的二维数组(矩阵)。

  2、去除干扰:删除干扰的点、线。干扰像素的特点是不连续,占用的像素点与主题有固定的差值(或许不固定,但大小关系一般固定),可以很容易地设计算法容易过滤。而如果干扰像素采用了和验证码正文明显不同的颜色,则可以在第一步二值化中直接去掉。对于干扰线,则有其它的算法(见附录0x00)。

  3、字符分割:把数组里连续的字符切割成一个个独立的字符。算法很简单,按照列遍历,找到一列没有数据1的,就记录。如果字符有旋转的,还得根据边缘把它再给摆直。

  以④为例,这是HUSTOJ(一个著名的在线评测系统)的验证码,给出识别的源码:点击下载

  以上种种,都是极为简单的图形验证码。但谷歌这种大公司,就搞出了整我们的验证码,上图如下:

  

  这种人都难以辨认的验证码,机器自然很难攻破(前者识别率约为30%,后者为5%)。其实其问题出在“字符分割”这一步。由于扭曲的验证码都粘连在一起,所以不能很好地分割。对于这种字符的分割,最好的方法是“滴水算法”,其原理是模仿水滴从高处向低处自然滴落的过程来对字符串进行切分。具体算法可以参考:http://www.docin.com/p-891657169.html

防御篇:

  攻击验证码,其实也比较容易。那么,如果没有相应的防御措施,各大网站上就会充斥着“xxx001”、“xxx002”、“xxx003”等ID,在评论里发着各种广告。这不能被容忍!还记得上面那个让人抓狂,让电脑“爆炸” 的变态验证码么?要从验证码识别的角度防御验证码破解,可以通过字符扭曲与字符粘连做到。还有一个有效的建议:不要使用普通字符,让验证码的各个部分使用不同比例的缩放或者旋转。

  跳出这个思维惯性的圈,我们是不是可以用其他的方法干掉侵略者?Google已经想出了一个很创新的想法。它们想抛弃验证码,使用一个“I AM NOT A ROBOT”的复选框来代替。据说,区分人类和机器之间的微妙差异,在于他/她/它在单击之前移动鼠标的那一瞬间

  但我们没有大公司,更不会研究出这种算法。所以,我们可以在CSS文件中加一些花招,例如翻转图形。真正的用户会看见翻转后的图形,而计算机则只能看见原本的图形。类似这样的方法其实还有很多。

附录:

  0x00——干扰线去除算法:

    这个算法有一个要求,就是验证码的干扰线与主体的颜色不同。

    给出思路,代码很容易实现。统计每种颜色出现的最左上的地方、最右下的地方。如果这两个坐标的差值大于某个阀值,就把这种颜色去除。

  0x01——字模比对算法(编辑距离):

    

  def editpath(s1,s2):
      m, n = len(s1), len(s2)
      colsize, v1, v2 = m + 1, [], []
      for i in range((n + 1)):
          v1.append(i)
          v2.append(i)
      for i in range(m + 1)[1:m + 1]:
          for j in range(n + 1)[1:n + 1]:
              cost = 0
              if s1[i - 1] == s2[j - 1]:
                  cost = 0
              else:
                  cost = 1
              minValue = v1[j] + 1
              if minValue > v2[j - 1] + 1:
                  minValue = v2[j - 1] + 1
              if minValue > v1[j - 1] + cost:
                  minValue = v1[j - 1] + cost
              v2[j] = minValue
          for j in range(n + 1):
              v1[j] = v2[j]
      return v2[n]

    这就是一个经典的编辑距离算法,时间复杂度为O(len(str1)*len(str2)),在大常数的python下跑算法,实在很慢。考虑到我们并不是严格地计算编辑距离是几,只是在一些字模中取出最值罢了、所以可以加一个优化:

  

     while (data[k1]==(vchash[i])[k1])and(k1<len(data)-1):
            k1+=1;
        while (data[k2]==(vchash[i])[k2])and(k2>0):
            k2-=1;
        if k1-k2>=0:
            return i
        tmps=editpath((vchash[i])[k1:k2],data[k1:k2])

    代码中的tmps可以与min进行比对。经测试,这种优化可以减少时间至原来的1/6甚至更少!

时间: 2024-10-19 21:23:50

验证码的认识和简单验证码的攻防的相关文章

php基础之gd图像生成、缩放、logo水印和简单验证码实现

php基础之gd图像生成.缩放.logo水印和简单验证码实现 阅读目录 图像生成 缩略图 水印生成 验证码 gd 库是php最常用的图片处理库之一(另外一个是imagemagick),可以生成图片.验证码.水印.缩略图等等.要使用gd库首先需要开启gd库扩 展,windows系统下需要在php.ini中将extension=php_gd2.dll 前边的分号去掉然后重启web服务器,linux系统下一般在编译php时已经开启gd库扩展,要是没有开启gd库扩展则需要先编译安装freetype ,j

简单 验证码 功能

在贴代码之前首先简述一下验证验证码原理:随机获取验证码的值,把这个值存到session中,其作用可想而知就是要拿来跟前台数据作比较,通过Graphics将值进行模糊处理之后传到前台页面展示. 1 package com.skss.util; 2 3 4 import java.awt.Color; 5 import java.awt.Font; 6 import java.awt.Graphics; 7 import java.awt.image.BufferedImage; 8 import

C#简单验证码码识别

写在最前 最近做一个小玩意需要识别验证码,之前从来没接触过验证码识别这块,这可难到了我.所以,只有三番五次的麻烦度娘帮我找找验证码识别这块的资料.所幸,许多前辈分享的博文帮到了我.最终,完美的把问题解决. 我要识别的验证码属于非常简单的一种,如下图: 1.图片灰度化(把彩色的验证码图片转换成灰色图片) for(int i = 0; i < bmp.Width; i++) { for(int j = 0; j < bmp.Height; j++) { Color color = bmp.GetP

简单验证码的识别

验证码图片均取自于国内某知名信息安全网站,通过图像处理.模板对比识别等步骤,实现了该类简单验证码图片的识别功能.同时对程序实现了可视化界面,并集成了(验证码)图片下载.(灰度值)门限手动调节等扩展功能.代码存在github,传送门请戳我. 一.程序内容及原理 本程序以Python实现,主要借助了PIL(Python Image Library,实现读取图片.读取灰度值等图像处理相关功能)及tkinter(实现界面设计相关功能)两个库.图像处理及识别的主程序的总体流程如下:导入(读取)验证码图片,

php笔记之GD库图片创建/简单验证码

燕十八 公益PHP培训 课堂地址:YY频道88354001 学习社区:www.zixue.it php画图:比如说验证码,缩略图,加水印都要用到GD库,所以要开启gd2库,才能用 首先找到php.ini中extension=php_gd2.dll  去掉前边的分号,然后重启apache,创建图片就可以用了 /* 画图的一般步骤: 1.创建画布 2.创建颜料 3.画图或者写字 4.保存 5.销毁资源 */ //创建画布 $img=imagecreatetruecolor(300,200); //创

C# 生成简单验证码

网站登录总是会用到验证码,生成验证码对于C#来说很简单.因为有专门封装好的GDI+类可以直接调用使用具体代码如下 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.UI; 6 using System.Web.UI.WebControls; 7 using System.Drawing; 8 9 namespace Ajax

JFinal框架——简单验证码

JFinal很强大,验证码的实现也很简单,在此记录一下. HTML 1 <form action="/jfinal_verification/user/login1" method="post"> 2 用户名:<input type="text" name="name"/></br> </br> 3 密码:       <input type="password&

验证码识别与生成类API调用的代码示例合集:六位图片验证码生成、四位图片验证码生成、简单验证码识别等

以下示例代码适用于 www.apishop.net 网站下的API,使用本文提及的接口调用代码示例前,您需要先申请相应的API服务. 六位图片验证码生成:包括纯数字.小写字母.大写字母.大小写混合.数字+小写.数字+大写.数字+大小写等情况. 四位图片验证码生成:包括纯数字.小写字母.大写字母.大小写混合.数字+小写.数字+大写.数字+大小写等情况. 简单验证码识别:验证码类型 : 数字+字母, 纯英文, 纯数字,计算题 英数_验证码识别:纯数字,纯英文,数字+英文 中英数_验证码识别:英文.数

python+selenium进行简单验证码获取

# _*_ coding:utf-8 _*_from PIL import Imagefrom selenium import webdriverimport pytesseractimport time url = 'https://ec.ayyywl.com/login'driver = webdriver.Chrome()driver.maximize_window() # 将浏览器最大化driver.get(url)# 截取当前网页并放到E盘下命名为printscreen,该网页有我们需