从安全运营的角度看,这类问题的价值不在于“怎么绕过”,而在于“为什么能绕过”。十六进制编码和表情符号之所以成为AI安全攻防里的高频词,是因为它们正好打在大模型内容安全体系最薄弱的接缝上:字符串层和语义层之间的错位。这篇文章不提供任何攻击配方,只从防御者视角拆解编码混淆的底层机制、安全限制的工作边界,以及工程上如何把这类绕过路径堵住。
1. 安全对齐为什么会被一个“看似乱码”的字符串骗过
1.1 大模型处理文本的三层流水线:分词、嵌入、语义
要理解十六进制编码为什么能绕过生成式AI的内容安全限制,得先搞清楚大模型读文本的完整链路。以ChatGPT这类产品为例,输入文本进入模型之后,不是像人一样直接“看到”字符串,而是经过三个层次的处理:
第一层是tokenization(分词)。文本被切分成token,中文按字或词切分,英文按子词切分,特殊符号和数字也有对应的token ID。GPT系列用的是BPE(Byte Pair Encoding)算法的变体,字节级别的编码让模型理论上能表示任意字符。
第二层是embedding(嵌入)。每个token ID被映射成一个高维向量,这个向量是模型理解语义的基础。相近语义的词在向量空间里距离更近。
第三层是Transformer的注意力计算。模型在这个阶段做上下文融合,逐步生成输出。
问题就出在这里:内容安全过滤系统和模型对文本的理解,发生在不同层次。很多产品的输入过滤用的是关键词黑名单、分类器、或少样本提示词约束,它们处理的是“已经解码的明文”。而大模型自己却具备处理编码字符的能力——当输入是十六进制字符串时,模型照样能做token化、向量化,甚至有能力在内部完成解码逻辑。
于是出现了一个错位:过滤器在看“表面”,模型在看“结构”和“概率”。十六进制编码恰好能让一句话的“表面形态”与“语义内容”完全脱钩。过滤器扫到的是一堆\x68\x74\x74\x70之类的字符,而模型可能会在推理过程中识别出这串字节对应的意义,甚至在一些场景下模型会先“解码”再理解。
1.2 过滤系统和模型理解发生在不同层次
我见过不少刚接触AI安全的朋友会有个误解:觉得模型的安全机制是一个整体,输入防护和输出防护共享同一套语义理解。实际情况远没有这么“聪明”。
典型的内容安全体系至少有三道闸门:
- 输入侧关键词过滤:做字符串匹配或规则匹配,检查是否出现敏感词、危险指令模式。这部分速度最快,但对编码变体基本无效。
- 模型自身的安全对齐:通过RLHF、基于人类反馈的强化学习等训练方式,让模型在生成阶段“自觉”拒绝输出危险内容。这部分对语义层面的禁忌有效,但对编码后的输入并不稳定。
- 输出侧二次检查:模型生成内容后再跑一遍分类器,拦截漏网之鱼。
这三道闸门对编码混淆的敏感度完全不同。关键词过滤对任意编码变体都是聋子;模型安全对齐依赖于训练数据里是否覆盖了类似形态的攻击样本,覆盖不到就形同虚设;输出侧检查通常只看明文,但输出侧如果模型被诱导去做“编码→明文”的转换,它自己就可能亲手把危险内容“解码”出来。
1.3 攻防的错位本质:规则匹配 vs 语义理解
把问题抽象一层:任何内容安全体系的本质都是“判断一段文本是否有害”,而判断发生在不同的抽象层上。十六进制编码攻击利用的正是规则匹配层和语义理解层之间的信息差。
我举一个生活化的类比。门卫查证件只看姓名和照片是不是一致,用的是“表面比对”;你换一身打扮、戴个口罩帽子走进门,门卫依然认得你是昨天那个人,靠的是“整体特征识别”。规则匹配就是前者,一眼看表面;语言模型是后者,它通过海量语料学到了语言的内在规律,即使输入形态很怪,它依然可能推断出真实意图。
所以“十六进制编码绕过ChatGPT安全限制”这类案例的底层逻辑,不是模型傻,而是过滤层的执行标准(明文匹配)和模型的能力(编码理解)不一致。这种不一致是所有编码混淆类攻击的共同土壤。
2. 十六进制编码绕过:解码发生在模型内部,过滤却停留在表面
2.1 编码字符串在流量里的真实形态
十六进制编码攻击在Web安全里不算新鲜事,SQL注入时代就有人用CHAR(83)绕过WAF,XSS攻击里也有\x3cscript\x3e的写法。到了大模型时代,这类老手法找到了新土壤。
真实的攻击样本通常长这样:把一句话中的关键部分转成十六进制字节串,或者混进\x前缀的转义序列,中间穿插普通文本,让整段输入看起来像技术日志、调试代码、或者简单的乱码。还有变体是Unicode转义,形如\u0048这种形式;更进一步的是各种编码叠加,十六进制套Base64,再套URL编码。
这些形态对人和机器都不友好,唯独对语言模型“可能友好”。为什么?因为大模型的训练语料里包含了大量包含十六进制、Unicode转义、Base64的代码和技术文档。模型见过这些形态,而且见过“编码形态→明文形态”之间的对应模式。
2.2 哪个环节会被骗、哪个环节其实不受影响
为了控制变量,我梳理一下三种输入形态遇到各道防线时的效果:
| 输入形态 | 输入侧关键词过滤 | 模型安全对齐 | 输出侧分类器 |
|---|---|---|---|
| 纯明文危险词 | 直接命中 | 大概率拒绝 | 能拦到 |
| 十六进制编码 | 不命中 | 取决于模型是否“理解”编码含义 | 模型若明文输出,可能拦截 |
| 编码+解码指令组合 | 不命中 | 不稳定,可能中招 | 输出若为编码后的文本,无法判断;若为明文,可拦截 |
这里的关键差异在于第二步。模型安全对齐是在语义空间里工作的,一个让模型“解密后再回答”的组合输入,实际上把模型当成了一个解码器。模型的安全对齐更关注“输出内容本身是否危险”,而不是“用户输入的形式是否可疑”。所以当恶意意图被编码隐藏,模型可能在生成过程中逐步把编码翻译成明文,甚至在翻译完成后才“意识到”内容危险。
第三道输出侧防线其实值得注意:如果输出是明文危险内容,分类器有很大概率拦截。所以具备攻击常识的人会要求模型“以十六进制形式输出答案”,让输出侧也避开文本分类器。这就形成了完整的绕过链:编码进、编码出,中间模型完成翻译和理解。
2.3 为什么“转义加解释”比直接输出明文更容易规避指令冲突
还有一个细节容易被忽略:模型的安全对齐里包含大量“拒绝回答危险指令”的偏好,但用户如果要求的是“解释一下这段十六进制字符串的含义”或“分析这段代码的行为”,模型会进入“技术解释”模式。在这个模式下,模型对内容的要求放低了——因为它觉得自己在做翻译或代码分析,而不是执行危险操作。
这就是“指令语义重定向”。同样是“怎么写一个能绕过认证的脚本”,直接问会被拒;但如果拆解成“第一步:找到登录接口的认证逻辑;第二步:以十六进制形式列出可能的参数;第三步:解释参数的校验方式”,模型判定每一个子任务技术性强、危险度低,就一步步放行了。
安全对齐系统的颗粒度还是太粗:它对“整体危险指令”敏感,对“逐步分拆的技术问题”不敏感。而十六进制编码天然就是分拆形态——一长串无效字节,过滤系统找不到完整的敏感特征,模型却又足够聪明到在内部把它拼回原意。
3. 表情符号:视觉与语义的分叉,也是安全策略的盲区
3.1 表情符号在tokenizer里到底是什么
表情符号的绕过逻辑和十六进制编码完全不同,它靠的不是隐藏明文,而是打乱注意力分配。
在OpenAI的tokenizer里,表情符号通常会被拆成多个token,有的emoji还会触发字节级编码。比如一个最常用的emoji,可能被拆成几个字节级token。这意味着什么?意味着表情符号在模型眼里根本不是“一个整体图形”,而是一串被赋予了特定向量表示的字节组合。
这些token的语义权重很特殊。模型从语料中学到的模式是“表情符号往往出现在轻松对话、社交媒体文本、非正式交流中”,这个先验会让模型对整句话的危险性判断产生偏移。同样一句话,带个笑脸或比个手势,模型的分类器打分可能就变了。
3.2 一个表情符号如何改变整句的“安全评分”
我实测过很多类似的对抗样本,发现一个规律:表情符号不仅出现在句尾,还会被插入到敏感词内部、指令动词前后、重要名词之间。比如把一个敏感短语的中间插入一个表情符号,整个短语在字符层面就被拆散了,关键词匹配完全失效。
更微妙的影响在注意力机制层面。Transformer模型是靠注意力权重决定“重点关注哪些token”的。突兀的表情符号会吸引部分注意力,导致模型对紧随其后或穿插其中的真实意图词组的注意力分配发生变化。如果表情符号足够多、位置足够刁钻,模型可能生成时“误解”了用户请求的真实强度。
有人会问:模型真的这么容易被干扰吗?答案是现代大模型对输入里的无关干扰有一定鲁棒性,但这种鲁棒性是统计意义上的,不是绝对意义上的。当攻击者把干扰做到极致——比如把一句话完全打散成“表情符号+单字+表情符号+单字”,模型为了补全语义,会自动脑补出完整的表达结构。这个自动补全的过程,恰恰绕过了安全对齐里“识别危险请求”的先验规则。
3.3 从文本攻击到多模态:图像、特殊字体、组合Unicode
表情符号绕过还有一种升级形态,就是和其他Unicode机制组合使用:
- 零宽字符(zero-width space,
\u200b)插入敏感词中间,视觉上无缝,token层面却被切开; - 视觉相似字符替换(用西里尔字母替换相似拉丁字母,形如“Раssword”),让人和模型都产生混淆;
- 组合表情符号加上肤色修饰符、方向修饰符,让一个字符序列被拆成更多token;
- 特殊字体、花体字母(如数学字母数字符号区段),让分类器找不到原始特征。
再往后走一步,就是多模态攻击——把文字内容渲染进图片,利用多模态模型对图像的文字识别能力,让安全限制完全绕开文本分类器。图像里的文字经过各种滤镜、扭曲、背景干扰,OCR都未必能准确识别,但不代表大模型读不出来。CLIP这类的视觉编码器对图像语义的编码是整体的,不太依赖逐字识别,这也是为什么有些“图片里藏提示词”的攻击在特定场景下奏效。
暴露出的是一个深层问题:安全防御体系把主要精力放在了“明文文本”和“标准格式”上,对非标准媒体形态和编码形态的覆盖远远不够。而多模态模型的语义理解能力已经很强了,它认识编码、认识花体、认识图片里的字,安全系统却还停留在只认明文。这种能力差,就是攻击者反复利用的空间。
4. 红队视角下的安全限制边界:单层过滤永远不够
4.1 安全限制的分层架构
前面提到了三道闸门,这里把全景展开。业界比较认可的内容安全分层模型大致是:
- 传输与接入层:账号、设备指纹、速率限制、IP信誉、企业级策略管理;
- 输入解析层:格式校验、规范化、编码识别、词法分析;
- 模型层:系统提示词、少样本约束、RLHF对齐、生成参数限制;
- 输出审计层:敏感信息检测、内容分类器、多模态审核;
- 运营层:红队测试、威胁情报、用户举报、自动化评估与迭代。
十六进制编码攻击瞄准的主要是第2层和第3层之间的空隙。表情符号则更多干扰的是第3层内部的语义判断。多模态相关攻击瞄准的是第2层到第4层的整个文本管道。
分层架构本身没有错,错的是层与层之间的判定标准不一致。输入解析层用规则、输出审计层用分类器、模型层用RLHF偏好,三层各自训练、各自优化,互相之间的特征空间根本没有对齐。攻击者只需要找到“其中两层都识别不了”的输入形态,就能穿透整个体系。
4.2 编码攻击想要突破的是哪一层
我在内部红队测试时复盘过不少编码类绕过样本,发现攻击成功率最高的路径是“编码输入+解码指令+编码输出”三段式:
- 输入编码:使输入解析层失明;
- 附带解码指令:引导模型在推理层面完成解码,使关键词过滤的漏检成为可利用空间;
- 输出编码:使输出审计层的文本分类器也失明。
这三段里,第一段和第三段都绕规则,第二段考验的是模型对“指令意图”的判断。单看每一段,都不算“高危内容”,但拼接起来的整体行为远超单段的风险等级。很多安全运营团队只监控单条请求的文本内容,没有把跨请求、跨模态的行为链关联起来,所以这类攻击在日志里经常被当成无害乱码直接放过。
4.3 实际攻防中的效果与局限
对于这类攻击的实际效果,我得说句公道话:网上流传的很多“破解”案例有夸大成分。现在主流大模型的安全对齐迭代非常快,公开的绕过模板生命周期很短,可能今天能用,明天就被补丁封掉。真正有威胁的不是某个具体模板,而是这个方法论本身——只要编码层和语义层的判定不一致存在,就会有新型变体持续出现。
还有一层局限容易被忽略:编码混淆攻击的目标是让模型说出危险内容,但模型输出里如果包含大段编码或怪异的Unicode,在很多业务场景里本身就会被下游系统标记为异常。换句话说,攻击者要的最终效果是“模型输出能被人看懂的危害内容”,而不是一堆纯乱码。这个业务需要限制了可用的编码方式,也为防御方提供了输出侧检测的机会。
4.4 安全限制失效时,真正兜底的是什么
当所有过滤都被绕过时,最后一道防线是什么?我的判断是权限边界和控制平面。真正严重的问题不是模型说出了什么,而是它能调用什么工具、触碰什么数据。如果模型本身没有任何外部工具权限,输出再危险也只是文本;如果模型接了插件、搜索、代码执行环境,那编码混淆攻击就可能从“文本生成问题”升级成“实际危害问题”。
所以做AI应用安全,不能只做内容过滤,还要做权限最小化。模型应该在最小必要权限下运行,外部动作应该全部经过人审或者强校验。这样即使文本层全被穿透,影响范围仍然可控。
5. 防御侧工程实践:让编码混淆攻击失效的落地方法
5.1 第一步:输入规范化与多路径扫描
防御编码混淆,有一个绕不开的基础动作:输入规范化。把所有用户输入统一转成标准化明文后再做过滤,可以大幅压缩攻击面。
具体做法分成两步。第一步是解码:对十六进制转义、Unicode转义、URL编码、Base64、HTML实体等常见编码形式做递归解码。注意是“递归”——嵌套编码需要解码多轮,直到内容不再变化。第二步是标准化:将全角字符转半角、去掉零宽字符、对不可见控制字符做标记、把相似字形统一映射到标准ASCII范围。
这里有三个容易踩的坑:
- 解码深度不够,只解一层就认为搞定,嵌套编码轻松穿透;
- 编码识别太激进,把正常业务文本里的
\x序列也解了,导致误伤; - 规范化之后只做一次检测,没有对原始输入和解码后输入做交叉关联。
我建议的做法是多路径检测:原始输入扫一遍、规范化解码后扫一遍、AST解析结果扫一遍,三条结果合并计算风险分。这种冗余检测会牺牲一点响应延迟,但对安全敏感的业务完全值得。
5.2 第二步:不只靠关键词,还要做意图分类与指令检测
关键词黑名单在编码混淆面前不堪一击。真正有效的第二道防线是指令意图识别——用一个专门的分类模型,判断用户请求的“行为意图”是什么,而不是匹配具体字符。
比如“帮我把这段十六进制转成可执行脚本”这句话没有任何关键词特征,但意图是“生成代码”。分类模型应该把这一类输入识别为高风险。再比如“分析这个字符串解码后会执行什么操作”意图是“危险代码分析”。这里的关键是把攻击面的判定标准从事项特征上升为行为特征。
还有一类危险指令值得单独建模:让模型“扮演解码器”的角色。用户不直接要求生成危险内容,而是要求模型“解密、解码、翻译、转义”某段输入。模型在完成解码后若继续加工成可执行内容,风险就出现了。对这种“工具行为”的检测,不能只看首条指令,还要看完整的对话链路。
5.3 第三步:输出侧同样需要编码检查
输出侧的防护逻辑和输入侧一致:不能让模型用编码形态输出危险内容。具体手段是在输出管道里部署一个编码检测器,识别输出中是否包含异常密集的十六进制、Base64、Unicode转义序列;同时维护一份“明文等价风险词库”,对解码后的输出内容做二次过滤。
这一步的实施成本比输入规范化还要低,因为输出是模型生产的,格式相对可控。我要提醒的是:输出检测和输入检测必须对称建设。很多团队只做输入检测,输出侧完全裸奔,结果攻击者只需要把“编码+解码指令”组合好,就能在输出侧获得明文结果。
5.4 第四步:持续做对抗性红队测试
编码混淆攻击的变体是动态的,静态规则注定会被绕过。靠谱的做法是把红队测试做成常态化机制,而不是上线前做一次就完事。
我建议的节奏是:每次模型版本更新、每次内容安全策略调整、每次新功能上线,都要跑一轮编码混淆专项测试。测试用例库要持续扩充,把十六进制、Unicode变体、表情符号插入、零宽字符、多模态组合、嵌套编码、业务场景上下文等维度全部覆盖进去。跑完测试后,把成功绕过的新样本加入回归集,确保后续更新不会让旧漏洞复活。
红队测试岗位最好独立于开发团队。自己做的东西自己测,天然会有盲区,这是人性问题,不是技术问题。第三方或者独立安全团队做红队,效果通常好得多。
5.5 一份可以直接抄走的安全评估清单
最后给一个我在多个项目里用过的检查清单,适合给需要接入大模型能力的业务团队做自查:
| 检查项 | 通过标准 |
|---|---|
| 输入规范化 | 递归解码、标准化、零宽字符清理均已实现 |
| 多路径检测 | 原始文本、解码文本、AST结果三条检测路径全覆盖 |
| 意图分类模型 | 能识别“解码指令”“工具行为”“危险代码分析”等输出意图 |
| 输出侧编码检查 | 能识别高密度编码输出,并对解码后内容做二次过滤 |
| 权限最小化 | 模型无多余工具权限,所有外部动作需人工确认 |
| 红队常态化 | 有独立测试流程,回归集覆盖历史绕过样本 |
| 监控与告警 | 对“编码输入+解码指令”组合行为设置了独立告警规则 |
这套清单不区分模型供应商、不限定技术栈,核心思想只有一条:让安全能力覆盖整个输入-处理-输出链路,而不是只押注在某一层上。
我在实际落地中的体会是,安全攻防最大的难点从来不是某个具体绕过手法,而是防御者能不能把“形式”和“语义”之间的差异始终放在心上。十六进制编码攻击、表情符号干扰、多模态混淆,本质上都是在这条缝里做文章。只要把这个底层逻辑想透了,设计防御方案时就不会总是被动追赶新变体,而是能够从机制上封住一整类攻击路径。