作者:闵杰
来源:携程技术中心(ID:ctriptech)
编辑:Juvae
从互联网行业出现自动化工具开始,验证码就作为对抗这些自动化尝试的主要手段登场了,在羊毛党,扫号情况层出不穷的今天,验证码服务的水平也直接决定一家互联网企业的安全系数。作为WEB看门人,它不仅仅要做到安全,也要兼顾体验。
本文将分享携程信息业务安全团队在这几年里,对图形验证码服务所做的一些大大小小的改变。各位可以将本文作为自身网站图形验证码搭建的小攻略,减少重复踩坑的情况。
1.0时代
过去携程曾经使用了一套基于.NET的图形验证码作为控制登录,注册,发送手机短信,点评,重置密码以及其他相关场景的主要手段,目的也很简单,就是防止非实人的请求。
在这个阶段,设计时仅仅是满足了防御异常请求,并没有考虑太多用户体验以及产品上线后,运营数据收集再分析改造的需求。
主要实现的功能点为:
图片验证一次失效
图片生成超时失效
支持生成4位和6位验证码,字符以英文和数字组成
支持简单的字符粘连,干扰线,干扰点,字体,字符大小,字体扭曲等配置。
验证码图示:
流程图如图所示:
事后来看,这套验证码系统由于架构简单,接入简便,在很长一段时间内,担当了携程门户主要的看门人的角色,尽管各大BU并不是非常情愿地使用了这套服务,但是在防范撞库,恶意请求短信,批量获取优惠卷等场景下,还是体现出了一个验证码服务所应该起到的作用。
当时这套验证码服务上线后,遇到了不少的问题:
1、服务并没有对接入方做场景,事务等区别,整个携程的验证码难度都是统一的(除了部分BU自己开发了验证码),经常发生在A页面出现被扫号情况,需要增强验证码难度,但是B页面随之反馈,验证码太难,收到用户投诉,需要降低难度,无法兼顾。
2、服务记录的字段仅仅能支撑服务正常运行,业务数据没有进行记录。导致了验证码有时候调用和验证异常升高,完全无法知晓是谁在进行恶意尝试并进行拦截(比如封停恶意IP)。
3、只有英文数字,并且字体单一,设置的扭曲干扰线简单点,极易被OCR识别,假如设置的太难,就会造成连正常用户都无法识别的窘境,在很长的一段时间内,只能将难度设置在简单-中等这种难度,谈不上对于批量OCR有任何的防御。
而说到这类验证码的破解,业内目前通用的方案,我了解下来有这么几种:
1、通过各种手段,绕过风控,或者绕过验证码,比如某些验证码是本地校验,有些验证码的关键参数会下发至前端,用户可以修改参数达到控制验证码的目的,有些业务方接入了验证码,但是没有把校验和业务接口绑在一起,导致人家可以直接请求业务接口,验证码形同虚设。也有业务方在接入验证码的时候,登录动作先于验证码校验,也导致了验证码毫无意义。这些在过往的接入过程中,都是实际发生过的情况。
2、ORC,从二值化,去除干扰线/点,确定字体区域,到最后识别,会根据验证码本身难度的不同,显著的影响其识别率。
3、人工打码平台。目前打码平台针对图片验证码已经很成熟了,针对数字,英文,汉字,智能问答都有不同的价格。
4、CNN神经网络识别。通过大量的样本进行机器学习,对于某些OCR比较难识别的粘连字符字体,可能会有一个较好的识别结果。
随着各类攻击越来越多,穿透性也日益增强,业务部门对于验证码难度需求不一致,以及自身对于验证码数据收集再改造的这些情况下,改造这个服务已经成为了摆在眼前的事情。
1.5时代
在总结了上述提到的这些问题以后,新需求就自然而然的产生了:
英文和字母模型太过单一,极易破解,需要加入中文字库。
业务数据保留,至少得知道威胁是哪些地方过来的。
能够在面对大量的OCR或者暴力尝试场景下,自动变化难度,降低对方的识别率。
区分接入的业务方,难度可以根据业务方做不同的调整。
在产品开发测试的一轮轮投入后,新的需求完成了,并且又花了将近一年的时间推广了各个BU接入了这个新的验证码。
(在这里说一个实际的情况,就是在第一版验证码开发的时候,并不重视保留接入方的信息,导致了在进行第二轮验证码重新接入的时候,发现老的接入方有3位数,但是要找谁,完全不清楚,以至于有些验证码到目前都没有进行更新,这个服务接入注册其实是一个很小的功能,但是在版本更迭,重大事务通知上,能起到非常重要的作用)。
新版本验证码比较好的解决了下面这几个实际场景面对的问题:
1、再也不会出现某个应用发现异常请求,刚刚调高难度没多久,就接到投诉电话,需要把难度降低这种场景,可以根据各自应用手动或者自动调节难度。(原先是整个公司都是统一的难度耦合在了一起)。
2、可以知道威胁是来自于哪个IP或者设备的,针对性的做出响应,比如封停请求。
3、在面对扫号配合OCR工具的情况下,这套验证码会自动不停的变换难度,干扰点/线,字体,背景色,粘连度等,经过实际对比观察,防御效果比老版本提高了2倍,这里我们的策略分为全局难度提高和针对纬度进行提高,比如假设只有一个IP或者设备的验证码请求发现异常,我们只会提高来自于这个IP或设备请求的验证码难度,对于其他正常请求是无感知的,但是在某些情况下,比如大规模的分布式扫号,可能你需要使用的就是全局难度提高。
4、支持了中文验证码,实际测试,英文数字在成熟的OCR工具面前,哪怕做了混淆,解析成功率也接近50%,假设换成中文配合一定的混淆,解析成功率一般不高于20%,这也是很多团队初期,假设没有风控和其他的辅助服务,最直接,成本最低的提高防御力度的方案。
这套方案,作为主流的验证码方案在携程应用了很久,但是在去年,团队也终于意识到,还有很多问题是这套验证码方案所无法解决的:
1、用户的体验问题,这个问题被公司内部诟病很久,并偶尔会收到来自于外部用户的投诉。其实也很好理解,一个四个字的随机中文验证码,手机输入一次大约耗时15-20秒,这个在活动营销拉新场景下,是一个致命的转化率杀手。在很多力度不是非常大的活动面前,这个验证码会直接打消一部分正常用户去尝试的念头(尽管中文验证码在防御恶意请求接口上有着巨大的安全优势),作为业务方产品不得不考虑,假设恶意用户的比例是5%,牺牲剩下95%用户的体验是否值得,即便也只有5%的正常用户放弃了尝试(比如一些年纪大的客户),和恶意用户的比例相仿,但是剩下的用户还是需要输入这些验证码,在用户体验成本上的让步是巨大的,这样就会让安全和业务陷入一种零和博弈的局面,这往往也是安全部门不受欢迎的主要原因。
2、接入繁琐,验证码和风控作为2个服务,需要业务方去耦合,分别接入,听起来就很繁琐,实际接入也确实很繁琐,大量的时间花费在接入服务上。
3、无法应对国际化,中文验证码国外用户不认识,英文数字过于简单压根没办法防御主流扫号攻击。实际发生过的案例就是携程海外站点被大规模扫号,但是束手无策的局面,分布式IP和设备,无法采用中文,几万个IP手动封不谈累不累,CFX都装不下,只能看着他扫。
4、丑,验证码图片由于需要防破解的关系,往往和整体页面UI的风格完全没有一个搭配感,让人很出戏。
和各大竞品比起来,我们的验证码确实就像是石器时代在和工业时代比较,也被公司内部一次次吐槽实在太影响体验了。在这种内忧外患的局面下,验证码服务更新又一次被放到了台面上。
2.0时代
需求又一次的被明确:
接入要简便,不要让业务方再需要自己对风控结果和验证码来处理相关逻辑。
体验要好,移动端时代,尤其要考虑移动端输入的习惯。
安全性和国际化问题,至少不能让有些用户投诉自己无法输入中文字。
美观,和页面UI尽量融合,也需要可以让业务方自行美化。
又是一轮一轮的测试开发,大约在半年前,完成了本次验证码重构的第一版,他主要实现了如下功能:
1、体验问题被解决了,在对比多种竞品以后,我们采取的方案为“滑块+选字”,在安全认为请求有风险的情况下,会出现滑块,假设在你滑动滑块期间采集的数据不足以认为请求是可信的情况下,会出现选字或者直接禁止请求访问,根据实际数据,用户滑动滑块的时间耗时一般平均在0.5秒一次,仅有很少的一部分用户会出现选字,选字一般的耗时在7秒左右,平均下来,整体耗时目前在携程实践下来,在1.7秒左右。
2、接入问题也得到了改进,业务方目前接入仅仅需要在页面上引入一个JS(APP为一个SDK),然后在监听到JS的一个事件提示,可以获取token后,获取token,由业务方服务端获取token以后到安全这里的校验服务校验,校验完成以后,整个流程就结束了,中间的判断风险,出现滑块,滑块校验,出现选字,选字校验这些步骤业务方都无需干涉以及传送数据,安全已经把后端的风控,风险仓库和验证码前端全部打通,业务方在无感知的情况下,相当于接入及使用了3个服务。
3、国际化问题,目前已经支持东南亚多国语言的选字和提示语服务,常用国家再也不会有无法看懂和无法输入的诟病。
新版验证码服务如图所示:
流程图如图:
这个版本作为目前携程验证码的主流应用版本,将在各个场景下代替过去的填字验证码,在体验和安全性上,大幅度超越之前的服务。
按照目前携程的每日验证情况来计算,新验证码对比老验证码能每天给用户节约500小时的验证时间。
填字验证码在H5端,通过大量实践,在保证安全性的前提下,输入正确率一般在88%-90%,存在了一个天花板,在新验证码上线后,整体通过率已经提高到了96%,接近了我们认为的实际异常比例。
同时我们对于前端采集的大量数据做了模型训练,对于某些规则难以发现的问题,会采用模型的结果来进行处理。
在某些公共登录注册场景下,我们会采用BI画像+特定活动物料的模式,给特定的用户进行验证码渠道的推广服务,如图:
但是这套服务,也存在一定的问题:
1、滑块服务存在被破解的可能,据一些外部专业测试机构报告,目前外部主流的一些SAAS滑块服务,被破解的概率在60%(他能让滑块认为他是安全的请求,选字就不会出现了)
2、选字的OCR识别依然存在,虽然存在要识别两套并点选的难度,但是有些外部专业团队已经实现了一定程度的破解。
3、体验上,在IOS系统,滑块容易造成页面的回退,对于一些指甲长的用户尤其容易造成这个问题,目前的解决方案只能是加大滑动条的大小,尽量远离屏幕边缘。
结语
没有一种验证码可以通吃所有场景,也没有绝对安全无法破解的验证码,只有在业务和安全不停权衡的前提下,找到一个属于体验和安全平衡的点,这才是验证码正确的打开方式。在和各种黑产团队不停斗争的过程中,验证码服务只有不停的改变,创新,才可以适应当前复杂的黑产现状以及业务多变的场景。
作者简介:闵杰, 携程信息安全部产品经理。2015年加入携程,主要负责黑产防刷,验证码,反爬以及UGC方面的产品设计,关注在低成本的前提下,解决以上场景的实际问题。
投稿邮箱:[email protected]
本文由作者授权早读课发表,转载请联系作者。