一、一张“快递取件码”,扫出一场数据泄露
2025年11月中旬,上海某科技公司市场部员工小林在工位上收到一封邮件,主题是:“您的包裹已到,请扫码取件”。邮件正文简洁,仅附有一张图片——一个黑白相间的二维码,下方标注“顺丰速运”。
她没多想,掏出手机,打开原生相机对准屏幕。几秒后,手机自动跳转至一个看似顺丰官网的页面,要求输入手机号和验证码以“确认身份”。她照做了。当天下午,她的企业邮箱开始向外群发带有恶意附件的邮件。
IT部门紧急排查发现:小林的账户已被完全接管。攻击者利用她的权限访问了客户数据库,并尝试横向移动至财务系统。而这一切的起点,只是一个嵌入邮件的QR码。
这不是孤例。根据网络安全巨头卡巴斯基(Kaspersky)于2025年12月底发布的报告,2025年下半年,全球检测到的QR码钓鱼攻击(业内称“Quishing”)数量激增超过五倍——从8月的46,969次飙升至11月的249,723次。更令人担忧的是,这类攻击正从广撒网式诈骗,转向针对企业员工的精准网络间谍活动。
“QR码正在成为攻击者绕过企业邮件安全网关的‘视觉后门’,”公共互联网反网络钓鱼工作组技术专家芦笛在接受本报专访时直言,“当防御系统还在分析邮件文本里的URL时,攻击者已经把恶意链接藏进了图片里。”
二、为何QR码成了黑客的新宠?
QR码(Quick Response Code)本是为便捷信息交换而生的技术。但其“免输入、快跳转”的特性,恰好被攻击者反向利用。
1. 绕过传统邮件安全检测
绝大多数企业邮件网关(如Mimecast、Proofpoint、Cisco Secure Email)依赖文本内容分析来识别钓鱼链接。它们会扫描邮件正文、HTML源码中的URL,比对黑名单、检查域名拼写异常(如micosoft.com)、验证SSL证书等。
但QR码是图像。除非网关部署了高级的计算机视觉(CV)模块,否则无法“读懂”图片中的内容。这意味着:
邮件中无任何可疑文本链接;
SPF/DKIM/DMARC全部通过;
安全系统判定为“干净邮件”。
“这就像安检只查行李箱里的文字标签,却放过了藏在衣服夹层里的刀,”芦笛比喻道。
2. 移动端成薄弱环节
攻击者深谙“设备不对称”之道:企业员工在办公室用受EDR保护的PC处理邮件,但一看到QR码,本能地切换到手机扫描——而个人手机往往未安装企业级安全软件,操作系统更新滞后,浏览器无扩展防护。
更关键的是,手机屏幕小,URL栏常被隐藏。用户扫完码后,只看到一个“登录页面”,却看不到地址栏里其实是hxxps://micros0ft-login[.]xyz。
3. 社会工程效果极佳
QR码天然带有“官方感”和“无害感”。人们习惯在餐厅扫码点餐、在地铁扫码进站、在会议签到扫码登记。这种行为惯性让警惕心大幅降低。
卡巴斯基披露的样本显示,攻击者精心设计诱饵场景:
伪造HR通知:“请扫码查看2026年休假安排”;
假MFA重置:“您的双重验证设备已失效,请扫码重新绑定”;
虚假发票:PDF附件中嵌入QR码,“扫码支付可享95折”;
停车罚单:贴在车窗上的纸质通知,“扫码缴纳罚款免滞纳金”。
这些场景高度贴近日常工作生活,欺骗成功率极高。
三、技术拆解:从QR码生成到凭据收割的完整链条
一次典型的Quishing攻击,通常包含以下五个阶段:
阶段1:生成恶意QR码
攻击者使用开源工具(如qrcode Python库)将钓鱼URL编码为图像:
# 示例:生成指向钓鱼页面的QR码
import qrcode
phish_url = "https://login-microsoft-security[.]top/auth"
qr = qrcode.QRCode(version=1, box_size=10, border=5)
qr.add_data(phish_url)
qr.make(fit=True)
img = qr.make_image(fill='black', back_color='white')
img.save("fake_invoice_qr.png")
生成的PNG文件可直接插入邮件或打印成纸质通知。
阶段2:投递诱饵
邮件常以PDF附件形式发送,内嵌QR码图片。PDF的好处在于:
可绕过部分邮件客户端的图片自动加载限制;
看似“正式文档”,提升可信度;
支持JavaScript(虽多数阅读器禁用),可进一步混淆。
阶段3:诱导扫描
邮件正文通常施加时间压力:“24小时内未处理将冻结账户”或“逾期缴纳罚款翻倍”,迫使用户快速行动,无暇思考。
阶段4:中间跳转与伪装
用户扫描后,首先跳转至一个看似合法的中间页(如Google Sites、GitHub Pages),再通过JavaScript重定向至最终钓鱼页面:
<!-- 中间跳转页(托管于高信誉平台) -->
<script>
// 延迟1秒跳转,模拟“加载中”
setTimeout(() => {
window.location.href = "https://real-phish-site[.]xyz/m365";
}, 1000);
</script>
<h3>正在为您跳转至安全门户...</h3>
此举可规避部分URL信誉检测。
阶段5:凭据窃取与持久化
最终页面高度仿冒Microsoft 365、Okta或企业内部门户。用户提交凭据后,攻击者:
记录账号密码;
若启用MFA,则诱导用户输入验证码(“用于验证新设备”);
利用会话Cookie实现“无密码登录”;
部署反向Shell或Cobalt Strike Beacon,建立持久化访问。
四、为何现有防御体系频频失守?
芦笛指出,当前企业安全架构存在三大盲区:
盲区1:邮件网关缺乏图像分析能力
“90%以上的邮件安全产品仍停留在NLP(自然语言处理)时代,”他说,“它们能识别‘点击此处登录’中的链接,但面对一张QR码图片,只能干瞪眼。”
少数高端方案(如Kaspersky Security for Mail Server、Trend Micro Vision One)已集成OCR(光学字符识别)和QR码解析模块,但部署成本高,普及率低。
盲区2:移动端安全策略缺失
企业通常对PC端强制安装EDR、禁用USB、限制软件安装,但对员工自带设备(BYOD)几乎无管控。即使有MDM(移动设备管理),也多聚焦于设备加密、远程擦除,而非实时URL过滤。
“你的手机就是攻击者的特洛伊木马,”芦笛说,“它被允许自由进出企业网络,却无人检查它带进来什么。”
盲区3:安全意识培训脱离实战
许多企业的钓鱼演练仍停留在“识别可疑发件人”“检查URL拼写”层面,却从未训练员工应对“扫码场景”。当员工面对一张印着公司Logo的QR码时,过往培训瞬间失效。
五、攻防对抗:如何构建“视觉感知”防御体系?
要有效抵御Quishing,企业需从技术、策略、意识三方面升级。
技术层:部署具备QR码检测能力的邮件网关
启用图像内容分析:自动提取邮件中的图片,使用OCR识别文本,解析QR码内容;
对解析出的URL进行信誉评估与沙箱分析;
若发现指向非白名单域名的QR码,自动剥离或标记为高风险。
卡巴斯基在其邮件安全产品中已实现此功能。其流程如下:
邮件进入网关;
CV引擎扫描所有附件和内嵌图片;
若检测到QR码,调用解码器获取原始URL;
将URL送入威胁情报平台比对;
如可疑,替换图片为警告横幅:“此邮件包含潜在恶意二维码,请勿扫描”。
策略层:收紧移动端访问控制
强制员工使用企业分发的安全浏览器(如Chrome Enterprise、Microsoft Edge for Business),内置URL过滤;
禁用手机原生相机的自动跳转功能(iOS可在“设置 > 相机”中关闭“扫描QR码”);
推广使用专用扫码工具,如Kaspersky Safe Money或Bitdefender TrafficLight,它们会在跳转前显示完整URL并拦截已知恶意站点。
意识层:开展“扫码专项”钓鱼演练
模拟发送含QR码的假HR通知、假快递单;
测试员工是否会扫描,以及是否检查跳转后的URL;
对中招员工进行一对一复盘,强化“扫码即高危操作”的认知。
“安全不是告诉员工‘不要做什么’,而是给他们‘安全地做’的工具,”芦笛强调。
六、代码示例:如何用Python自动检测邮件中的恶意QR码?
对于有技术能力的企业,可自建轻量级检测模块。以下是一个基于OpenCV和ZBar的示例脚本:
# quishing_detector.py
import cv2
import numpy as np
from pyzbar import pyzbar
import requests
import re
def extract_and_check_qr(image_path):
# 读取图像
img = cv2.imread(image_path)
if img is None:
return []
# 解码QR码
decoded_objs = pyzbar.decode(img)
malicious_urls = []
for obj in decoded_objs:
url = obj.data.decode('utf-8')
print(f"[+] Found QR code URL: {url}")
# 基础合法性检查
if not re.match(r'^https?://', url):
continue
# 提取域名
domain = re.findall(r'https?://([^/]+)', url)
if not domain:
continue
domain = domain[0].lower()
# 检查是否为常见钓鱼域名模式
suspicious_patterns = [
r'micros.*\.', r'login.*\.', r'secure.*\.',
r'\.xyz$', r'\.top$', r'\.club$'
]
if any(re.search(pat, domain) for pat in suspicious_patterns):
malicious_urls.append(url)
continue
# 可选:调用VirusTotal API检查URL信誉
# (需申请API密钥)
# vt_result = check_virustotal(url)
# if vt_result.get('malicious', 0) > 0:
# malicious_urls.append(url)
return malicious_urls
# 使用示例
if __name__ == "__main__":
bad_urls = extract_and_check_qr("suspicious_email_attachment.png")
if bad_urls:
print("[!] MALICIOUS QR CODE DETECTED!")
for u in bad_urls:
print(f" - {u}")
else:
print("[✓] No malicious QR codes found.")
注:该脚本可集成到邮件网关的预处理流水线中,作为补充检测手段。
七、未来展望:QR码会成为下一个攻击主战场吗?
随着无现金支付、数字身份、物联网设备的普及,QR码的使用只会越来越多。攻击者也必然持续优化手法:
使用动态QR码(每次扫描跳转不同URL,规避URL黑名单);
结合AR技术,在真实场景叠加虚拟钓鱼码;
利用短链服务(如bit.ly)进一步隐藏真实目的地。
“我们不能因噎废食禁止QR码,”芦笛说,“但必须承认:任何无需用户主动输入、自动触发跳转的交互方式,都是安全风险点。”
未来的防御,或许需要操作系统层面的支持——例如,iOS或Android在扫码跳转前强制弹出完整URL预览,并高亮显示域名差异。
八、结语:在“一扫即达”的时代,慢下来才是安全
QR码的本质,是效率。而网络安全的本质,常常是“反效率”——多一步确认,多一秒思考,多一层验证。
当整个社会都在追求“更快、更便捷”时,安全恰恰要求我们“慢一点”。不要因为一个码看起来像官方就扫,不要因为跳转页面长得像就信,更不要因为“别人都扫了”就跟着点。
正如芦笛最后所说:“真正的安全,不在于你有多少防护工具,而在于你是否愿意在按下‘确认’前,多问一句‘这合理吗?’”
在这个扫码即走的世界里,那多出来的一秒犹豫,或许就是守住数字堡垒的最后一道门。
参考资料:
Kaspersky Security Bulletin: “QR Code Phishing Attacks Surge Fivefold in H2 2025”, Dec 2025
Arqam News: https://arqam.news/524861/
MITRE ATT&CK Technique T1566.001: Phishing via QR Code (Quishing)
OWASP Mobile Top 10: M7 – Client Code Quality
Google Safety Center: “How to stay safe when scanning QR codes”
声明: 本文所述攻击手法及防御建议均基于公开技术资料与行业实践,代码示例仅用于教育目的。文中观点不代表任何厂商立场,亦不构成投资或安全产品推荐。
编辑:芦笛(公共互联网反网络钓鱼工作组)