前两天在做例行钓鱼邮件样本分析时,我碰到一个差点让我“中招”的页面:弹窗提示“检测到异常登录,请先完成人机验证”,下面是一张字符扭曲、带噪点背景的验证码图片,角落里还配着和某常用邮箱官网几乎一致的logo和文案排版。我下意识想点“我不是机器人”,但地址栏的域名让我停住了——那是一个刚注册没几天、跟官方完全无关的地址。这种由AI批量生成的伪CAPTCHA,正在被大量塞进钓鱼网站,让原本用来证明“你是真人”的验证码,反过来变成了骗取信任的道具。这篇文章我从攻防两侧拆一拆:攻击者为什么盯上验证码,AI怎么做到批量伪造,完整钓鱼链路长什么样,以及普通人、安全人员分别怎样识别和处置。
1. 验证码为什么会成为“造假”目标
1.1 验证码的本质是一道信任闸门
CAPTCHA的全称很长,但不用记,你只需要理解它干的事:把人机校验变成一个“自动图灵测试”。正常网站用它挡住批量注册、撞库、爬虫和自动脚本,常见形态有扭曲字符、旋转文字、点击指定物体、滑块拼图等,核心目的是区分访问者是真人还是程序。
这类机制在安全上有一个非常微妙的地方:对普通用户而言,看到“验证码”三个字,大脑会自动触发“安全机制正在保护我”的信号。一个人一天可能遇到好几次验证码,每次都是正常的,于是“出现验证码”和“页面安全”之间就被悄悄画上了等号。攻击者真正看中的,正是这个等号,而不是验证码背后的技术复杂度。
打个比方,正常客服电话接通时会说“通话可能被录音”,这是流程需要;但诈骗电话也会放一句一模一样的语音,目的就是让你以为自己在跟真客服通话。伪CAPTCHA玩的是同一套逻辑,它不是在破解验证码的技术,而是在利用人们已经形成的信任习惯。
1.2 伪CAPTCHA对应的三种典型攻击场景
伪CAPTCHA并不单指一张假图片,它通常是一个完整的交互流程。我整理了一下,最常见的是下面三种:
场景一是伪造登录页里的“人机验证”。受害者点击邮箱、网银或办公系统的链接,看到登录框,输入账号密码前先弹出一个验证码,上面写着“检测到异常活动,请验证后继续”。实际上,用户输入的所有内容都会被提交到攻击者控制的服务器,而非真实系统。
场景二是恶意下载和升级提示。页面提示“您的文件已准备就绪,请完成验证后下载”,用户辛辛苦苦验证完之后,等来的不是文件,而是捆绑了木马的安装包或钓鱼表单。这个场景尤其容易出现在软件下载站、影视资源站等“下载刚需”环境里。
场景三是二次验证码套取OTP。用户已经输入账号密码后,页面又弹出一个“输入短信验证码完成验证”的窗口。正规服务确实经常这么干,攻击者利用的正是这种熟悉感,把动态口令也一并骗走。
单一伪验证码的成功率不一定高,但一旦做成多步交互,再配合“验证失败请重新加载”之类的假错误提示,用户往往会反复输入,甚至把多个账号的密码都填进去。这就是攻击者愿意费劲做假验证码的原因。
1.3 为什么以前没人批量做,现在却成了气候
如果只是想做一个简陋的假验证码弹窗,十多年前就有人做过。但那个年代的伪验证码基本都是手写HTML加静态图,字体一板一眼,背景色块饱和度严重超标,很多人第一眼就能发现“这不对”。更致命的是手工制造速度太慢,想要生成几百张不同样式的验证码成本极高,收益远不如直接群发钓鱼链接。
AI生成改变的是“成本与仿真度的比值”。现在攻击者可以采集少量真实验证码图片作为模板,再用图像生成模型批量制造风格一致的伪验证码;或者用小模型按目标站点的设计语言生成各种变体。算下来,一张批量伪验证码的成本可以低到忽略不计,仿真度却常常超过很多中小网站自己的验证码。这一变化让伪CAPTCHA从“偶尔遇到”升级成“批量出现”,防御压力陡增。
2. AI是怎么把“伪CAPTCHA”做到真假难辨的
2.1 仿的不是技术,是视觉风格
理解AI伪CAPTCHA,关键要明白一个问题:攻击者并不需要击败验证码的OCR识别,也不需要破解后端逻辑。真正验证码的安全性由服务端决定,可钓鱼页面里压根没有真正的服务端判定,它需要的只是让页面上出现一个“看起来像验证码”的组件,去骗过人的眼睛。
所以,他们模仿的是视觉风格,不是密码学。典型做法是收集目标站点或同类站点出现过的验证码图片,构建一个小型训练集,再用图像生成模型做风格模仿。字体倾斜角度、背景噪点密度、字符数量、干扰线走向、按钮圆角、阴影颜色,这些细节都会被模型吸收。生成的伪验证码,和真实验证码放在一起,很多时候连安全从业者第一眼也分辨不出来。
我先声明一下:这里聊的是原理和检测方法,不是给攻击者出教程。你可以把过去的伪验证码想象成塑料花,虽然有心模仿,但光泽和纹理都不自然;现在AI生成的伪验证码像鲜切花,连花瓣上的脉络都给你还原了。对抗的难度不在“做出来”,而在“看出来”。
2.2 批量化的关键在于“模板引擎”与变体流水线
光有逼真还不够。钓鱼活动需要让不同的人看到不同的验证码,否则同一个样本流传久了,识别率会断崖式下降。攻击者的解决方案不复杂:把验证码生成拆成“背景库”“字符库”“干扰层库”三套资源,然后用程序随机组合输出。
假设后台已经准备好几百张AI生成的背景纹理,再配上若干字符渲染器和干扰效果器,每次用户访问时,随机抽一个背景、随机选一组字符、随机套一套扭曲参数,就能立刻输出一张新图。整个过程有点像服装厂的流水线:同一个版型能生产出无数件颜色不同的衣服,但每一件都保持着统一的品牌调性。结果就是,用户很难找到两张一模一样的伪验证码,视觉上的新鲜感掩盖了内容的虚假性。
我注意到一个趋势:部分伪验证码甚至带上了“动态加载”效果,比如先显示一个进度条,再慢慢浮现验证码图片,模拟真实网站的异步请求。这种细节虽然不影响技术判定,但对人的心理暗示很强,会让用户觉得“这个页面很正规,它在认真做校验”。
2.3 对抗机器检测:让安全工具也会看走眼
伪CAPTCHA不仅骗人,也骗机器。安全团队常用无头浏览器或沙箱自动巡检钓鱼页面,攻击者就会在页面里做访问者身份判断。如果检测到请求特征不像正常浏览器,就直接返回404或空白页;相反,如果是真实用户访问,才展示钓鱼页面。这个逻辑和很多反爬机制一样,只是被反过来用在了恶意场景里。
更隐蔽的做法是引入对抗扰动。所谓对抗扰动,就是往图片里加一层人眼几乎看不出的细小噪声,但机器学习模型会对这张图产生完全不同的判断。比如,安全厂商的自动分类器把一段页面截图交给图像识别模型,正常情况下应该标出“这里有一个验证码组件”,加了噪声之后,模型可能把它识别成“普通背景图”。人眼看到的是验证码,机器看到的却是正常页面元素,这种双向欺骗,让传统基于图片特征库和URL信誉的检测方案变得力不从心。
3. 从展示到窃取:伪CAPTCHA钓鱼的完整攻击链路
3.1 先用“正规感”搭台
攻击者要做的第一件事,是让整个钓鱼页面看起来足够正规。常规做法是直接下载目标站点的登录页源码,替换关键域名和接口;或者用页面截图加HTML重绘的方式,把logo、排版、字体全部还原,再插入一个伪验证码组件,配上“安全检查”“请输入图片字符”之类的文案。
域名选择上,攻击者会刻意找那些容易混淆的近似名,比如在真实域名前后加一个短横线、多一个字母,或者换个后缀。链接再通过短链、二维码转发等方式扭曲一下,普通用户到达页面时,已经很难判断原始地址。这一步的核心目的,是让受害者来到页面时,默认认为“这就是官网”。
这里面最容易踩坑的是手机端。很多App内置浏览器会隐藏地址栏,用户根本看不到完整URL,页面上再弹一个伪验证码,视觉上几乎没有破绽。我处理过不少类似投诉,都是在手机浏览器里点链接中招的。
3.2 验证码是漏斗,表单才是目的
伪验证码在整个攻击链路中不是终点,它是一个分流漏斗。它的出现通常意味着引导用户完成以下操作:输入账号密码、输入短信验证码、点击“验证”后自动跳转到下一个仿冒表单。攻击者后台可以清楚看到哪一步流失最多,然后针对性地修改文案和交互。这和正常运营做转化率优化是一模一样的思路,只不过目标变成了窃取凭据。
我见过一个做得非常精细的案例:钓鱼页面先弹伪验证码,用户完成之后显示“验证成功,正在跳转”,跳转后的页面又是一份“账号信息确认”表单,要求填写注册手机号、备用邮箱,最后还要输入短信验证码。整个流程走完,受害者以为自己在配合安全审查,实际上把能泄露的信息全交出去了。
还有一个容易被忽视的细节:有些伪造页面会直接嵌入某第三方验证码服务的官方组件。验证码本身是真的,弹窗文案是攻击者自己加的,页面其余部分全是伪造的。这种情况下,单看验证码真假完全没用,必须看整个页面的URL和请求归属,才能识别。
3.3 反侦查设计:为什么追查时间窗口那么短
钓鱼页面不会存活太久,攻击者因此做了大量反侦查设计。有的页面检测到访问来源是安全厂商的扫描器时,会直接返回空页面;有的会限制每个IP只能访问一次;还有的会故意在正常搜索引擎爬虫访问时展示仿冒页面,让安全厂商“主动”去收录假样本,从而干扰威胁情报的准确性。
数据回传也不是简单地把内容POST到某个服务器。攻击者通常会通过多层中转、临时域名或公共文件存储服务来收集被盗数据,让溯源链路断在半路。我不打算展开讲具体手法,想强调的是:钓鱼页面上一旦发生输入行为,追踪和溯源的时间窗口非常短。所以无论你是普通用户还是安全人员,看到可疑伪验证码页面时,第一步永远是停止交互、采集样本,而不是继续点击看会发生什么。
4. 现代防御:人人能用的三层识别清单
4.1 普通用户版视觉检查清单
大部分受害者并不是技术小白,他们只是注意力不在安全审查上。如果养成“验证三步”的习惯,能挡下绝大多数伪CAPTCHA。
第一步看URL。验证码出现时,先看地址栏,尤其是登录框和验证码弹窗所在页面的域名。正规服务的登录与验证永远只在主域名下进行,而不是奇怪的子路径或近似域名。哪怕页面logo再像,只要域名对不上,立即关闭。
第二步看来路。如果验证码提示来自短信、邮件或聊天工具里的链接,需要格外小心。正规网站不会通过即时消息突然要求你“补做验证”。我经常跟朋友开玩笑说,这就好比你走在路上突然有人递给你一张“官方验证码”,你第一反应绝对不应该是扫。
第三步看下一步。正常验证码完成一次勾选或字符输入后,应该直接进入目标功能。如果完成验证后弹出新的表单,要求再输入手机号、备用邮箱或短信验证码,基本可以断定是钓鱼。
4.2 安全分析人员版:从请求与DOM判断
对于经常处理告警的安全人员,建议把视角从“看起来像不像”切换到“请求合不合理”。我排查伪CAPTCHA时,一般这么操作:
打开浏览器开发者工具,切到Network面板,勾选Preserve log,然后完整走一遍登录或验证流程。重点看验证码组件的加载方式。正规验证码会加载对应的脚本,并向第三方验证码服务发起请求和回调;伪验证码通常只是加载一张图片,或把数据提交到钓鱼服务器自己的接口。
再看iframe来源。如果验证码区域是一个iframe,但src指向的域名和目标站点毫无关系,甚至是个刚注册的域名,那基本可以判定恶意。反之,如果页面里直接嵌入了真实第三方验证码服务,则要回到最外层URL判断站点合法性。
我习惯再做一次“差异比对”:在真实目标网站上触发一次真验证码,记录页面元素和请求特征;再去可疑页面触发伪验证码,把两份数据放在一起比对。这个方法比单纯依靠经验可靠得多。
| 检查项 | 正常验证码 | 伪验证码 |
|---|---|---|
| 验证码脚本 | 加载独立验证码JS或第三方服务脚本 | 通常只加载图片,无独立脚本 |
| 回调地址 | 向验证码服务方发起校验请求 | 提交到钓鱼服务器自己的接口 |
| 弹窗次数 | 一般一次通过或失败后重试 | 常反复弹出不同表单,收集更多信息 |
| 后续页面 | 验证成功后进入目标功能页 | 跳转后出现新的“信息确认”表单 |
| 域名环境 | 与目标网站主域一致 | 近似域名或第三方子域名 |
4.3 企业侧的系统防护建议
企业邮箱和办公系统是伪CAPTCHA钓鱼的重灾区。单纯靠员工“仔细看”不现实,必须做系统层面的防护。
邮件网关要开启陌生域名链接重写或隔离,把所有外部链接先送进安全扫描沙箱,再决定是否放行。办公网络出口对已知钓鱼IP和恶意域名做阻断,能减少大部分误点风险。更重要的是全面推行多因素认证,并且建议使用硬件安全密钥,而不是只用短信动态口令。短信动态口令本身也可能被伪CAPTCHA钓鱼页面骗取,硬件密钥不会把敏感数据交给网页。
定期做模拟钓鱼演练也有用,但要注意方式。演练场景里专门加入“伪验证码”环节,让员工在安全受控的环境里见一次、点一次、错一次,真实遇到时才会产生警觉。演练之后不要处罚,而是用即时提醒告诉员工“刚才哪个环节露馅了”,效果比十次邮件宣传都好。
5. 踩坑实录与日常排错速查
5.1 这些“假验证码”真的都是攻击吗
我在分析样本时发现一个反常识的现象:有些看起来极假的验证码,反而是正规网站的;有些看起来极真的验证码,反而是钓鱼页面。原因不复杂,很多中小型站点还在用开发框架自带的验证码组件,样式确实是十几年前的审美,但它不是伪造的;而某些品牌预算充足的平台,验证码设计得过于精美,反倒成了攻击者克隆的首选对象。
有一次,某个合作伙伴发来一个可疑页面让我帮忙看,页面上的验证码图片模糊、字体歪斜、配色刺眼,怎么看怎么像假的。我翻完请求记录之后发现,那是他们内部老系统自带的验证码,只是生成库版本太旧,渲染效果差。如果我当时按“图片丑等于危险”的逻辑直接报警,反而会让业务受到无谓影响。所以判断真伪时,一定要先看环境,再看请求,最后才是视觉效果。
5.2 员工误点后的应急处置顺序
如果真的确认有人被伪CAPTCHA钓鱼页面骗走了凭据,建议按以下顺序处置:
- 立即改密,而且不要只改一个平台,要检查这个密码是否在其他站点重复使用过,重复使用的一并改掉。
- 登录账号后台,强制下线全部会话,查看最近登录记录,标记异常设备。
- 如果短信验证码或动态口令被套取,立刻重置绑定,并对绑定MFA的终端做安全检查。
- 把伪造页面URL、域名、截图、输入行为的时间线整理成完整样本,交给安全团队或上报威胁情报平台。
- 根据泄露范围,向全员发送简洁预警,直接点明“近期有针对某系统的伪造验证码钓鱼”,这比泛泛地让大家“小心钓鱼邮件”管用得多。
这里有一个常见错误:员工发现中招后,自己默默改了个密码就当没事发生。实际上,攻击者可能已经在后台拿到了账号权限,甚至已尝试横向登录其他系统。没有做会话撤销和终端排查,等于只锁了前门,窗户还是开的。
5.3 一个值得长期使用的判断习惯
我自己查这类问题时总结了一套“半信半疑”原则:对页面里的任何安全提示都保留一分怀疑,然后给证据链排序。第一位永远看域名和证书,第二位看请求归属,第三位才是页面的视觉设计。因为视觉是最容易伪造的部分,域名和网络请求相对难伪装。把这个顺序告诉身边同事和朋友,基本能挡住大多数套路。
还有一个小技巧特别适合手机场景:手机上看不到完整地址栏时,点开链接之前先长按,预览真实地址再决定是否访问。我见过太多钓鱼链接利用App内嵌浏览器隐藏地址栏的特性,用伪验证码在视觉上做文章。记住一个朴素的道理:真正的安全校验不会通过一条陌生链接突然出现。验证码本身不危险,危险的是它出现在你毫无防备的来路里。