01 · 混淆攻击的科学原理
同形异义(Homograph)攻击的本质是书写系统的历史偶然:西里尔字母а(U+0430)与拉丁字母a(U+0061)源自不同演变路径,却在绝大多数无衬线字体中逐像素一致。Unicode收录了15万余字符,跨文字种的视觉冲突对数以千计,且随字体族、字号、渲染环境(抗锯齿、低分辨率屏幕)变化。因此:
- 混淆是"代码点—字体—渲染环境"三元组的函数,不存在与渲染无关的绝对混淆表——任何混淆数据集都是特定字体条件下的近似;
- UTS #39的confusables数据是业界最权威的近似:它给出跨文字种的"易混淆集",并提供skeleton算法(将字符映射到其代表字符后比较)作为标准操作;
- 检测目标不是"判断是否恶意",而是"计算混淆度并给出证据链":解码形式、替换的字符对、与哪个品牌冲突、视觉差异截图——四条证据缺一不可,供人工裁决与投诉举证复用。
| 拉丁字符 | 易混淆字符 | 码位 | 所属文字种 |
|---|---|---|---|
| a | а | U+0061 / U+0430 | Latin / Cyrillic |
| e | е | U+0065 / U+0435 | Latin / Cyrillic |
| o | о | U+006F / U+043E | Latin / Cyrillic |
| p | р | U+0070 / U+0440 | Latin / Cyrillic |
| c | с | U+0063 / U+0441 | Latin / Cyrillic |
| x | х | U+0078 / U+0445 | Latin / Cyrillic |
| A | A | U+0041 / U+FF21 | Latin半角 / 全角 |
| 银行(示例) | 形近汉字对 | CJK统一表意文字内部 | Han内部(需专用形近字库) |
2017年引发全球关注的Zheng概念验证(详见第6页)即利用"аpple.com"全西里尔拼写:11个字符全部来自西里尔文字种,不触发任何浏览器的混合文字种回退规则,地址栏直接显示为"apple.com"。这一定理级事实决定了检测必须下沉到字符语义层,而非字符串层。
02 · 四层检测方法体系
本课题提出"字符—字形—域名—行为"四层检测模型,各层独立可算、联合可判,任一层触发即升级人工复核:
| 层级 | 处理对象 | 核心方法 | 输出 | 典型时延 |
|---|---|---|---|---|
| L1 字符层 | A-label原始串 | Punycode本地解码 → UTS #46归一化 → NFKC全角归一 → Script属性分析 → UTS #39 skeleton比对品牌库 | 混淆度评分 + 替换字符对证据 | 毫秒级/域名 |
| L2 字形层 | U-label渲染结果 | 无头浏览器截图 → pHash/dHash/SSIM与官方品牌页视觉比对(承接课题一的视觉检测管线) | 视觉相似度 + 差异区域标注 | 秒级/域名 |
| L3 域名层 | 标签序列 | 变体生成(同形替换×拼写错误×简繁转换×拼音谐音)→ 与品牌保护清单全量匹配 → 未命中项进入相似度召回 | 候选仿冒列表 + 变体类型标签 | 分钟级/批 |
| L4 行为层 | 注册与解析行为 | 注册邮箱/NS/IP聚类、证书透明度日志比对、解析突变监测、建站内容抓取分类 | 风险行为标签(批量注册/快速建站/高危ASN) | 分钟—小时级 |
03 · 核心算法与参考实现
3.1 字符层:Script检测与skeleton
L1层的两个关键操作均可离线完成。混合文字种检测对应浏览器回退规则的等价物,但检测系统应对其取补集——浏览器不告警的全西里尔域名,正是检测系统必须报警的对象:
import unicodedata
# UTS #39思想的最小实现:按Script属性粗分文字种,检测"混合文字种"
def script_of(ch):
cp = ord(ch)
if 0x0400 <= cp <= 0x04FF: return "Cyrillic"
if 0x0370 <= cp <= 0x03FF: return "Greek"
if 0x4E00 <= cp <= 0x9FFF: return "Han"
if ch.isascii() and ch.isalpha(): return "Latin"
if 0xFF01 <= cp <= 0xFF5E: return "Fullwidth" # 全角形式
return unicodedata.name(ch, "Unknown").split()[0]
def mixed_script(label):
scripts = {script_of(c) for c in label if c.isalpha()}
# 全角归一化后再参与判断(NFKC)
scripts |= {script_of(c) for c in unicodedata.normalize("NFKC", label) if c.isalpha()}
return len(scripts) > 1, sorted(scripts)
print(mixed_script("аррӏе")) # 全西里尔:单文字种,多数浏览器不会回退 Punycode
# (False, ['Cyrillic'])
print(mixed_script("appӏе")) # 拉丁+西里尔混合:浏览器回退,检测系统应立即告警
# (True, ['Cyrillic', 'Latin'])3.2 skeleton:与字体无关的字符串层近似
skeleton算法将字符串中每个字符映射到UTS #39定义的"原型字符"(representative),映射后比较。其价值在于把"视觉问题"转化为"查表问题",是域名层全量扫描的可行基础。工程上原型表应直接采用Unicode官方发布的confusables.txt并固定版本,禁止自行手工造表:
# Unicode码位层面可精确区分的"双胞胎"字符(节选,完整数据见UTS #39 confusables)
CONFUSABLE_PAIRS = [
("a", "\u0430"), # LATIN a vs CYRILLIC а (U+0430)
("e", "\u0435"), # LATIN e vs CYRILLIC е (U+0435)
("o", "\u043E"), # LATIN o vs CYRILLIC о (U+043E)
("p", "\u0440"), # LATIN p vs CYRILLIC р (U+0440)
("c", "\u0441"), # LATIN c vs CYRILLIC с (U+0441)
("x", "\u0445"), # LATIN x vs CYRILLIC х (U+0445)
("A", "\uFF21"), # LATIN A vs 全角A (U+FF21)
]
# skeleton:把域名中每个字符替换为其"原型字符"(UTS #39定义的代表字符),
# 再与品牌名比对。原型表应以官方confusables.txt为准,此处仅示意思想:
def skeleton(label, prototype_map):
return "".join(prototype_map.get(c, c) for c in label)
# 与品牌库比对:skeleton("аррӏе") == "apple" → 命中同形异义仿冒3.3 中文场景的三项特化处理
- 简繁转换:采用OpenCC等成熟开源库做双向转换("简→繁"存在一对多,需以"繁→简"归一化比对),与skeleton结果做并集召回;
- 全角归一:NFKC(U+FF01—U+FF5E全角区)必须在UTS #46映射之后执行,避免"ICBC"逃逸品牌匹配;
- 汉字形近字库:汉字形近关系无官方confusables数据覆盖,需维护专用字库(建议来源:公开学术数据集 + 字体渲染聚类自举),并明确标注其"特定字体条件下成立"的适用范围,禁止无证据扩展。
3.4 开源工具链
| 工具 | 用途 | 说明 |
|---|---|---|
| dnstwist | 变体生成+解析探测 | 支持IDN变体、fuzzy hash、字典模式,是本课题L3层的基线工具(github.com/elceef/dnstwist) |
| confusable_homoglyphs_check等 | confusable检测 | 基于UTS #39数据的Python库,可实现skeleton比对 |
| OpenCC | 简繁转换 | 业界标准开源简繁转换引擎 |
| 无头浏览器+感知哈希 | L2视觉层 | pHash/dHash/SSIM管线见课题一"网页视觉仿冒检测" |
| crt.sh / CT日志 | 证书侧佐证 | 检索品牌关键词证书,发现未公开解析的仿冒基础设施 |
04 · 防御矩阵:客户端之外的多层防线
| 防线 | 主体 | 机制 | 局限 |
|---|---|---|---|
| 注册层 | 注册局/注册商 | LGR与IDN表限制合法码位;高风险字符组合人工审核;批量注册风控 | 审核成本与注册量的矛盾;跨注册商逃逸 |
| 解析层 | DNS运营方/安全厂商 | Sinkhole、DNS防火墙下发阻断、RPZ | 仅对已识别域名生效,属事后 |
| 内容层 | 托管商/CDN | 钓鱼页面识别与下架 | 黑产可自助建站,下架后快速迁移 |
| 浏览器层 | 浏览器厂商 | 混合文字种回退、HSTS、安全浏览黑名单 | 策略不一、随版本漂移、移动端弱(见第3页§05) |
| 投递层 | 邮件/IM/短信平台 | 链接信誉库、域名前置拦截 | 对首发域名有天然时延 |
| 情报层 | 威胁情报生态 | IOC共享(GB/T 36643/STIX格式)实现跨主体联防 | 依赖共享意愿与标准化程度 |
方法论定位:本课题的四层检测模型属于"情报层"的生产工具——它的产出(带证据链的仿冒判定)只有接入注册局处置、DNS阻断与投递层拦截才形成完整防御。第7页将给出各防线对应的处置通道映射。
05 · 检测质量评估与对抗性思考
- 评估指标:以"品牌保护场景"为单位度量——召回率(发现的仿冒/全部活跃仿冒)、精确率(真仿冒/全部告警)、证据链完备率(可直投诉比例)、平均发现时延(注册→告警);
- 基准数据集:建议构建三部分评测集——公开恶意域名清单(如PhishTank/URLhaus历史数据)、人工构造的同形异义对抗集(固定字体、固定版本号)、生产环境采样集(用于误报率标定);所有评测集标注UTS/Unicode版本号;
- 对抗样本预期:攻击者可采用"单字符同形+多字符合法"的稀释策略(仅一个字符同形、其余全部合法以规避混合文字种检测)、罕见字体渲染差异、以及注册后先挂合法内容再切换的"养号"策略——L4行为层是这些策略的主要对策;
- 对抗评估纪律:不发布可指导逃逸的细节化绕过清单;公开讨论限定在防御方法论层面。
§ · 本节参考来源(第4页)
Unicode UTS #39《Unicode Security Mechanisms》及官方confusables数据——unicode.org/reports/tr39
Unicode UTS #46《Unicode IDNA Compatibility Processing》——unicode.org/reports/tr46
Unicode UAX #24《Unicode Script Property》——unicode.org/reports/tr24
dnstwist开源仿冒域名检测工具——github.com/elceef/dnstwist
OpenCC简繁转换开源项目——github.com/BYVoid/OpenCC
IETF RFC 5890-5894(IDNA2008)、RFC 3492(Punycode)——rfc-editor.org
证书透明度(Certificate Transparency,RFC 6962)与crt.sh检索服务——crt.sh
PhishTank、URLhaus公开钓鱼域名数据(评测基准建议来源)——phishtank.org、urlhaus.abuse.ch