base64隐写原理-深入理解base64编码
admin
2026年8月22日 18:47
本文热度 30
base64 本质很多系统(如电子邮件、URL)只能处理文本,如果直接传二进制可能出错或者被误解析。Base64 把二进制“伪装成文本”,安全传输。编码映射 img 一个字节8位,字符和数字用自定义编码映射,从数字或字母转为对应编码,每次取三个字节,24比特,然后拆分为4份,每份6比特,然后转为十进制,进行映射如果不够末尾不够三个字节,那么就会补0,如果补一个字节,就加一个 = ,两个字节就是 == 例子 img 那么这样的话,3个字节的数据就变成了3*8/6=4个字节 如果字节数不是 3 的倍数,则位数就不是 6 的倍数,那么就不能精确地划分成 6 位的块. 此时,需在原数据二进制值后面添加零,使其字节数是 6 的倍数. 然后,在编码后的字符串后面添加 1 个或 2 个等号,表示所添加的零值字节数. 比如,字符串 Tr0y 经过 Base64 编码后变为 VHIweQ== (补了两个字节) 解码 解码就是编码的逆过程。 注意红色的 0,我们在解码的时候将其丢弃了,所以这里的值不会影响解码. 所以我们可以在这进行隐写。为什么等号的那部分 0 不能用于隐写?因为修改那里的二进制值会导致等号数量变化,解码的第 1 步会受影响。自然也就破坏了源字符串。而红色部分的 0 是作为最后一个字符二进制的组成部分,还原时只用到了最后一个字符二进制的前部分,后面的部分就不会影响还原
img 所以直接解密 VHIweQ== 与 VHIweR== ',得到的结果都是'Tr0y'
结论 就是把不影响base64解码后原值的一些二进制位,塞上所有可能的变体情况,从而在改变base64编码后值情况下不影响base64解码原值
类似的攻击技术 1. 限流绕过原理 传统限流:基于请求参数进行限流 - 用户A:token=ABC123 → 限流计数+1 - 用户A:token=ABC123 → 限流计数+2 (触发限流) 变体攻击: - 用户A:token=ABC123 (原始) → 限流计数+1 - 用户A:token=ABC124 (变体1) → 限流计数+1 (不同token) - 用户A:token=ABC125 (变体2) → 限流计数+1 (不同token) - 用户A:token=ABC126 (变体3) → 限流计数+1 (不同token) 结果:解码都是同一个值,但限流系统认为是不同请求! 2. 风控绕过原理 风控系统:检查请求参数 - 提取 token 字符串 - 与黑名单/白名单比对 - 异常检测(频率、模式等) 变体攻击: - 前端发送时:token=ABC125 (变体) - 后端解码后:实际值还是原值 - 风控看的是字符串:ABC125 ≠ 黑名单中的ABC123 - 业务逻辑看的是解码值:原值=ABC123 ✓ 类似的攻击技术 1. Unicode规范化绕过 # 不同Unicode表示相同字符 é = U+ 00E9 (预组合) é = U+0065 + U+0301 (分解) # 风控认为是不同字符串,但规范化后相同 2. URL编码变体 # 同一个字符多种编码 空格 = % 20 空格 = + 空格 = % 2520 (双重编码) # 后端解码后相同 3. JSON键名变体 // 风控看到不同字段,但业务解析相同 { "user_id" : 123 } { "userId" : 123 } { "USER_ID" : 123 } 4. HTTP头大小写变体 X-Forwarded-For : 127.0.0.1 x-forwarded-for : 127.0.0.1 X-FORWARDED-FOR : 127.0.0.1 防御措施 1. 标准化后再验证 def validate_token ( raw_token ): # 1. Base64解码 decoded = base64_decode(raw_token) # 2. 重新编码成规范格式 canonical = base64_encode(decoded, standard_format= True ) # 3. 验证规范格式 return check_whitelist(canonical) 2. 限流使用规范化值 def rate_limit ( request ): # 限流key使用解码后的值,而非原始值 key = base64_decode(request.token) return increment_counter(key) 3. 输入标准化前置 def normalize_input ( data ): # Unicode规范化 data = unicodedata.normalize( 'NFC' , data) # Base64标准化 data = standard_base64(data) # URL解码标准化 data = urllib.parse.unquote(data) return data 现实案例 这种技术在以下场景中被广泛使用:
最佳实践建议 1. "先解码,再决策" :所有基于值的判断都应在标准化后进行 2. "限流看本质" :限流key使用业务含义值,而非传输格式 3. "风控看本质" :风控规则建立在标准化后的数据上 4. "统一规范" :团队内部统一编码规范,拒绝接受非标准格式 1. 把 Base64 字符串去掉等号,转为二进制数( VHIweQ== -> VHIweQ -> 010101000111001000110000011110010000 ) 2. 从左到右,8 个位一组,多余位的扔掉,转为对应的 ASCII 码( 01010100 01110010 00110000 01111001 0000 -> 扔掉最后 4 位 -> 01010100 01110010 00110000 01111001 -> Tr0y )
阅读原文:点击这里
该文章在 2026/8/22 18:47:43 编辑过