导读:科学技术是第一辈子产力,技术的演进会很大程度上推进业务的升级,同时业务的演进进一步促进技术往更高的层面发展,智能验证码的技术发展一样相似。css
首先,很是高兴和你们来分享下我在验证码攻防方面的一些实践和探索。我主要从事反欺诈服务的相关工做,最近一段时间接触到OpenCV、Tensorflow、Tesseract、ThreeJS等相关技术,在一次分享会上听到Puppeteer的介绍,通过半年研究将这些技术整合起来,在Node中对市面主流验证码作了一轮攻防演练。html
全自动区分计算机和人类的公开图灵测试(英语:Completely Automated Public Turing test to tell Computers and Humans Apart,简称CAPTCHA),俗称验证码,是一种区分用户是计算机或人的公共全自动程序。在CAPTCHA测试中,做为服务器的计算机会自动生成一个问题由用户来解答。这个问题能够由计算机生成并评判,可是必须只有人类才能解答。因为计算机没法解答CAPTCHA的问题,因此回答出问题的用户就能够被认为是人类。前端
CAPTCHA这个词最先是在2002年由卡内基梅隆大学的路易斯·冯·安、Manuel Blum、Nicholas J.Hopper以及IBM的John Langford所提出。卡内基梅隆大学曾试图申请此词使其成为注册商标, 但该申请于2008年4月21日被拒绝。一种经常使用的CAPTCHA测试是让用户输入一个扭曲变形的图片上所显示的文字或数字,扭曲变形是为了不被光学字符识别(OCR, Optical Character Recognition)之类的计算机程序自动识别出图片上的文数字而失去效果。因为这个测试是由计算机来考人类,而不是标准图灵测试中那样由人类来考计算机,人们有时称CAPTCHA是一种反向图灵测试。node
为了没法看到图像的身心障碍者,替代的方法是改用语音读出文数字,为了防止语音识别分析声音,声音的内容会有杂音或仍能够被人类接受的变声。python
根据CAPTCHA测试的定义,产生验证码图片的算法必须公开,即便该算法可能有专利保护。这样作是证实想破解就须要解决一个不一样的人工智能难题,而非仅靠发现原来的(秘密)算法,然后者能够用逆向工程等途径获得。jquery
防止恶意破解密码、刷票、论坛灌水、刷页。有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试,实际上使用验证码是如今不少网站通行的方式(好比招商银行的网上我的银行,百度社区),咱们利用比较简易的方式实现了这个功能。虽然登陆麻烦一点,可是对网友的密码安全来讲这个功能仍是颇有必要,也很重要。但咱们仍是 提醒你们要保护好本身的密码 ,尽可能使用混杂了数字、字母、符号在内的6位以上密码,不要使用诸如1234之类的简单密码或者与用户名相同、相似的密码 ,省得你的帐号被人盗用给本身带来没必要要的麻烦。git
验证码一般使用一些线条和一些不规则的字符组成,主要做用是为了防止一些黑客把密码数据化盗取。github
典型应用场景:web
网站安全:垃圾注册、恶意登陆、帐号盗用算法
数据安全:数据爬取、数据破坏
运营安全:恶意刷单、虚假秒杀、虚假评论
交易安全:虚假交易、恶意套现、盗卡支付
同盾智能验证产品主要针对企业不一样业务场景,利用生物行为与机器学习方式提供人机验证服务,防范非真实人类流量和恶意程序攻击,帮您下降业务风险。
使用同盾智能验证码,告别烦躁脆弱的验证码,提高用户体验的同时加强安全防护能力。远离垃圾帖、恶意注册、垃圾短信、刷票等交互安全烦恼。
其工做流程以下图所示:
字符型图片验证码
字符型图片验证码是由阿拉伯数字,英文字母,中文汉字按照必定规律排列,加入干扰噪点以后生产的一张图片。
行为式验证码
行为式验证码是一种较为流行的验证码。从字面来理解,就是经过用户的操做行为来完成验证,而无需去读懂扭曲的图片文字。常见的有两种:拖动式与点触式。
智能验证码
智能验证码是一种基于语言认知的人机区分,考验机器语言认知能力的智能验证码,会是将来一段时间内的重要选择。典型表明有语序点选和空间推理。
图像二值化( Image Binarization)就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。
在数字图像处理中,二值图像占有很是重要的地位,图像的二值化使图像中数据量大为减小,从而能凸显出目标的轮廓。
主要是去掉图像里的全部干扰信息,好比背景的点,线等。
/**
* 对图片进行阈值处理(默认55%)
* thresholdValue,降噪值
*/
async function disposeImg(imgPath, newPath, thresholdValue) {
return new Promise((resolve, reject) => {
gm(imgPath).threshold(thresholdValue || '55%').write(newPath, (err) => {
if (err) return reject(err);
resolve(newPath);
});
});
}
复制代码
Tesseract(/‘tesərækt/) 这个词的意思是”超立方体”,指的是几何学里的四维标准方体,又称”正八胞体”,是一款被普遍使用的开源 OCR 工具。
Tesseract 已经有 30 年历史,开始它是惠普实验室于1985年开始研发的一款专利软件,到1995年一件成为OCR业界内最准确的识别引擎之一。然而,HP不久便决定放弃OCR业务Tesseract今后尘封。数年以后,HP意识到与其将Tesseract束之高阁,还不如贡献给开源,让其重焕新生。在 2005 年,Tesseract由美国内华达州信息技术研究所得到,并求助于Google对Tesseract进行改进、消除Bug、优化工做,并开源,其后一直由 Google 赞助进行后续的开发和维护。由于其免费与较好的效果,许多的我的开发者以及一些较小的团队在使用着 Tesseract ,诸如验证码识别、车牌号识别等应用中,不难见到 Tesseract 的身影。
如今Tesseract托管在Github上,你们有兴趣能够上Github上Star或Frok该项目。
所谓 OCR(Optical Character Recognition)是指对文本资料进行扫描,而后对图像文件进行分析处理,获取文字和版面信息的过程。OCR是图像识别领域中的一个子领域,该领域专一于对图片中的文字信息进行识别并转换成能被常规文本编辑器编辑的文本。
使用Tesseract对降噪后的图片进行OCR识别,Tesseract支持107种语言,能够经过node-tesseract代理调用,也能够直接经过node-cmd执行Tesseract命令进行调用。 node做为中间层,能够直接调用封装好的node包,或者直接执行底层命令,或者调用Python脚本均可以。
经过node-tesseract进行OCR识别
async function recognizeImg(imgPath, options) {
//tesseract --list-langs,语言选项
options = Object.assign({
psm: 7, //-psm 7 表示告诉tesseract code.jpg图片是一行文本,这个参数能够减小识别错误率,默认为3
}, options);
//console.log(options);
return new Promise((resolve, reject) => {
tesseract.process(imgPath, options, (err, text) => {
if (err) return reject(err);
resolve(text.replace(/[\r\n\s]/gm, '')); // 去掉识别结果中的换行回车空格
});
});
}
复制代码
async function execute(imgPath) {
return new Promise((resolve, reject) => {
NodeCmd.get(`tesseract ${imgPath} stdout -l chi_sim`,
function (err, data) {
if (!err) {
resolve(data);
} else {
reject(err);
}
},
);
});
}
复制代码
机器自动识别图片验证码,对简单的状况能有较高的准确率,但对干扰多,变形复杂的图片验证码,其准确率会不好。因为图片验证码重要度增长,复杂的图片验证码被大量使用,致使近年来出现了利用众包力量实现的人工验证码识别平台。 其工做原理图下所示:
字符型图片验证码基本沦陷,验证码进入行为式验证时代。
行为式验证的核心思想是利用用户的“行为特征”来作验证安全判别。整个验证框架采用高效的“行为沙盒”主动框架, 这个框架会引导用户在“行为沙盒”内产生特定的行为数据,利用“多重复合行为判别”算法从特指、视觉、思考等多重行为信息中辨识出生物个体的特征, 从而准确快速的提供验证结果。
可是随着puppeteer的出现,行为式验证码的防护不在奏效。Puppeteer 的 Logo 很形象,顾名思义像是一个被操控的傀儡、提线木偶。
Puppeteer 是一个 Node 库,它提供了高级的 API 并经过 DevTools 协议来控制 Chrome(或Chromium)。通俗来讲就是一个 headless chrome 浏览器 (也能够配置成有 UI 的,默认是没有的)
经过puppetter的page.screenshot进行指定区域截屏,若是页面上未引入jQuery经过page.addScriptTag引入,后面截屏处理须要使用到。利用resemblejs/compareImages进行图片比对取得滑动距离的图片,经过canvas将图片读入内存,取得最终滑动距离,调用puppetter加入人的行为模拟,并最终验证经过。
const browser = await puppeteer.launch({
args: ['--start-maximized'],//讓開啟來的瀏覽器預設最大
executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
//executablePath: '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
//executablePath: '/Applications/Chromium.app/Contents/MacOS/Chromium',
//devtools: true,
headless: false, //这里我设置成false主要是为了让你们看到效果,设置为true就不会打开浏览器
});
复制代码
// 设置浏览器信息
const UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko)' +
' Chrome/69.0.3497.100 Safari/537.36';
await Promise.all([
page.setUserAgent(UA),
// 容许运行js
page.setJavaScriptEnabled(true),
// 设置浏览器视窗
page.setViewport({
width: 1280,
height: 748,
}),
]);
复制代码
await page.evaluateOnNewDocument(() => {
Object.defineProperty(navigator, 'webdriver', {
get: () => false,
});
Object.defineProperty(navigator, 'plugins', {
get: () => [1, 2, 3, 4, 5],
});
const originalQuery = window.navigator.permissions.query;
return window.navigator.permissions.query = (parameters) => (
parameters.name === 'notifications' ?
Promise.resolve({state: Notification.permission}) :
originalQuery(parameters)
);
});
复制代码
await page.addScriptTag({url: 'https://cdn.bootcss.com/jquery/3.2.0/jquery.min.js'});
复制代码
注入jQuery主要是为了方便Dom操做,在滑动验证的时候进行图片截取处理。
// 截屏
await screenshot(captionPosition, './screenshots/xxx.png');
await cropImage('./screenshots/xxx.png', './screenshots/xxx.png');
复制代码
最终经过Puppetter开启一个浏览器,实现自动截屏,自动模拟点击,自动登陆功能。
行为式验证码基本沦陷,验证码进入AI时代。
基于语言认知和结构化知识图谱的验证码,能够有效效避免攻击,提升人机识别的准确率。这里引入OpenCV和Tensorflow两个工具,主要用于图片识别和深度学习。
GoogLeNet首次出如今2014年ILSVRC 比赛中得到冠军。此次的版本一般称其为Inception V1。Inception V1有22层深,参数量为5M。同一时期的VGGNet性能和Inception V1差很少,可是参数量也是远大于Inception V1。
Inception Module是GoogLeNet的核心组成单元,Inception Module基本组成结构有四个成分。1 1卷积,3 3卷积,5 5卷积,3 3最大池化。最后对四个成分运算结果进行通道上组合。这就是Inception Module的核心思想。经过多个卷积核提取图像不一样尺度的信息,最后进行融合,能够获得图像更好的表征。结构以下图:
最新的Inception V5训练好的模型大概可与识别1000种类别的图片,经过opencv4nodejs能够调用训练好的模型进行图片分类打标,人脸检测等各类图片识别功能。
Google提供的inception5h模型介绍
const cv = require('opencv4nodejs');
const fs = require('fs');
const path = require('path');
const gm = require('gm');
const imageMagick = gm.subClass({imageMagick: true});
const DIRECTION = {
NorthWest: 'NorthWest',
North: 'North',
NorthEast: 'NorthEast',
West: 'West',
Center: 'Center',
East: 'East',
SouthWest: 'SouthWest',
South: 'South',
SouthEast: 'SouthEast',
};
if (!cv.xmodules.dnn) {
throw new Error('exiting: opencv4nodejs compiled without dnn module');
}
// 载入模型
const inceptionModelPath = './models/tf-inception';
const modelFile = path.resolve(inceptionModelPath, 'tensorflow_inception_graph.pb');
const classNamesFile = path.resolve(inceptionModelPath, 'imagenet_comp_graph_label_strings_cn.txt');
/*const inceptionModelPath = './models/flower';
const modelFile = path.resolve(inceptionModelPath, 'retrained_graph.pb');
const classNamesFile = path.resolve(inceptionModelPath, 'retrained_labels.txt');*/
if (!fs.existsSync(modelFile) || !fs.existsSync(classNamesFile)) {
console.log('exiting: could not find inception model');
console.log('download the model from: https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip');
return;
}
console.log('load models:' + inceptionModelPath);
// 模型和分类标签
const classNames = fs.readFileSync(classNamesFile).toString().split('\n');
//const net = cv.readNetFromTensorflow(modelFile);
const net = cv.readNetFromTensorflow(modelFile);
const classifyImg = (img) => {
// inception model works with 224 x 224 images, so we resize
// our input images and pad the image with white pixels to
// make the images have the same width and height
const maxImgDim = 224;
const white = new cv.Vec(255, 255, 255);
const imgResized = img.resizeToMax(maxImgDim).padToSquare(white);
// network accepts blobs as input
const inputBlob = cv.blobFromImage(imgResized);
net.setInput(inputBlob);
// forward pass input through entire network, will return
// classification result as 1xN Mat with confidences of each class
const outputBlob = net.forward();
// find all labels with a minimum confidence
const minConfidence = 0.05;
const locations = outputBlob.threshold(minConfidence, 1, cv.THRESH_BINARY).convertTo(cv.CV_8U).findNonZero();
const result =
locations.map(pt => ({
confidence: parseInt(outputBlob.at(0, pt.x) * 100) / 100,
className: classNames[pt.x],
}))
// sort result by confidence
.sort((r0, r1) => r1.confidence - r0.confidence).map(res => {
return `标签:${res.className}、几率:${res.confidence}、百分比:${res.confidence * 100}%`;
});
return result;
};
const testData = [];
/**
* 文件遍历方法
* @param filePath 须要遍历的文件路径
*/
function fileDisplay(filePath) {
//根据文件路径读取文件,返回文件列表
const tempFileDir = fs.readdirSync(filePath);
tempFileDir.forEach(function (filename) {
//获取当前文件的绝对路径
const filedir = path.join(filePath, filename);
//根据文件路径获取文件信息,返回一个fs.Stats对象
let tempFile = fs.statSync(filedir);
if (tempFile.isFile()) {
let tempObj = {};
tempObj['image'] = filedir;
tempObj['label'] = filename;
testData.push(tempObj);
}
if (tempFile.isDirectory()) {
fileDisplay(filedir);//递归,若是是文件夹,就继续遍历该文件夹下面的文件
}
});
}
fileDisplay(path.resolve('./data'));
testData.forEach((data) => {
const img = cv.imread(data.image);
//console.log('%s,%s: ', data.image, data.label);
//console.log('%s: ', data.image);
const predictions = classifyImg(img);
let tempText = '';
predictions.forEach(p => {
//console.log(JSON.stringify(p));
tempText += p + '\n';
});
console.log(tempText);
imageMagick(data.image).gravity(DIRECTION['NorthWest']) //水印的位置
.geometry('+10+10') //距离右下角右边10px下边10px
//.fontSize(24)
.fill('red')
.pointSize(18)
//.font('/Library/Fonts/Songti.ttc')
.font('./font/msyh.ttf')//字体必须正确,不然乱码或者不显示中文
.stroke('red')//文字颜色
.drawText(15, 10, tempText) //15和10是位置信息 最后一个参数是文字信息
.write(data.image.replace('/data/', '/process/'), function (err) {
if (err) {
return console.error('err--------', err);
}
console.log('%s:', data.image, tempText, '打标处理完成!');
});
//cv.imshowWait('img', img);
console.log('---------finish---------');
});
复制代码
基于Google Inception-V3 模型,在Windows平台经过TensorFlow 利用GTX1080进行并行计算学习,获得本身想要的模型结果。
python训练脚本
python retrain.py --bottleneck_dir=C:\Users\***\PycharmProjects\flower_photos\bottlenecks --how_many_training_steps=500 --model_dir=C:\Users\***\PycharmProjects\flower_photos\inception --summaries_dir=C:\Users\***\PycharmProjects\flower_photos\training_summaries\basic --output_graph=C:\Users\***\PycharmProjects\flower_photos\retrained_graph.pb --output_labels=C:\Users\***\PycharmProjects\flower_photos\retrained_labels.txt --image_dir=C:\Users\***\PycharmProjects\flower_photos
复制代码
使用训练脚本完成图片识别
const Promise = require('bluebird');
const childProcess = require('child_process');
(async () => new Promise(((resolve, reject) => {
/**
* child.stdin 获取标准输入
* child.stdout 获取标准输出
* child.stderr 获取标准错误输出
*/
childProcess.exec('python3 /Users/***/Downloads/python/label_image.py --image /Users/***/Downloads/python/232831_44935.jpg --graph /Users/***/Downloads/python/retrained_graph.pb --labels /Users/***/Downloads/python/retrained_labels.txt', (error, stdout, stderr) => {
// console.log('error', JSON.stringify(error));
// console.log('stdout', stdout);
// console.log('stderr', JSON.stringify(stderr));
if (stdout.length > 0) {
console.log(stdout);
resolve(stdout);
}
if (error) {
console.info(stderr);
reject(error);
}
});
})))();
复制代码
一、经过Puppetter对目标网站进行数据样本爬取,爬取问题和答案,创建语序点选,图标点选,空间推理的样本库。基于图片学习和深度学习,完成样本库的模型训练以后获得对应的模型数据供后续破解使用。
二、Puppetter访问对应的网站,唤醒拉起验证码,经过Puppetter截图获取问题图片。经过Node服务执行Python脚本完成识图功能,取得对应的答案。基于获得的答案经过Puppetter完成验证,实现目标网站的验证破解。
至此,智能验证码进入AI对抗时代。
传统验证码大部分基于二位空间,答案就在当前面,这使得Puppetter模拟线性的路径相对容易。重新颖性和趣味性安全性三个方面出发,咱们研究了在二维空间模拟三维空间,实现答案的隐藏和解空间难度升级,大大提高了验证码的趣味性和安全性。
3D旋转验证产品特色:
3D验证码主要技术点:
空间推理验证的安全性高于传统的滑动和字符型验证码,为了丰富产品线。咱们基于ThreeJS和Java 3D协同完成先后端的验证识别。
空间推理验证产品特色:
空间推理验证技术点:
随着互联网技术的进步,黑灰产也逐渐造成了团体化、工具化,对企业形成的危害也愈加严重。在与黑产的对抗中,同盾科技反欺诈服务,依托大数据分析技术,提供内容安全,业务安全,云安全,人机验证,行为验证码,营销反做弊,注册保护,登陆保护,图像鉴黄,文本过滤,敏感词过滤,黑产情报等产品用于黑产对抗,为企业提供安全解决方案。
同盾智能验证码已由单点对抗演进到体系对抗,多维度的混编一体对抗,采用新型的验证形式,提高用户体验的同时加强安全防护能力。安全是互联网公司的生命,同盾验证码将协助用户共同筑起这道安全篱笆。