base64的天坑

admin 2023年6月16日08:59:22评论22 views字数 2547阅读8分29秒阅读模式

base64编码补位的坑,导致数据验证被绕过,也绕过了系统黑名单的检测。

背景

突然,测试人员找上我,说篡改某对象ID的值会绕过系统的黑名单检测!

我非常不相信,因为该对象ID生成有随机因素,而且它的校验也有hash判断,只要校验不通过,立马会拒绝。

他把那个对象ID发给我,是这样的

NWE3MGQzMTBhYWYyODUxZTFlN2QwOWY2OWFmOGE5ZjMtMmUzOGIxZWNlZTVkNDUzNjkyYTg2NDAxYTVhZjk0MzUwMDAyLUx3QTF1OGpXWC8zelM2TUt0NG9pbW1qZzVEOD1=

是基于下面这个值改的。

NWE3MGQzMTBhYWYyODUxZTFlN2QwOWY2OWFmOGE5ZjMtMmUzOGIxZWNlZTVkNDUzNjkyYTg2NDAxYTVhZjk0MzUwMDAyLUx3QTF1OGpXWC8zelM2TUt0NG9pbW1qZzVEOD0=

第一个是篡改后的,第二个是原始生成的。第一个和第二个的差别是倒数第二个字符由0改为1

定位过程

原始的字符串是经过base64编码生成。用于base64解码一下

>>> origin = "NWE3MGQzMTBhYWYyODUxZTFlN2QwOWY2OWFmOGE5ZjMtMmUzOGIxZWNlZTVkNDUzNjkyYTg2NDAxYTVhZjk0MzUwMDAyLUx3QTF1OGpXWC8zelM2TUt0NG9pbW1qZzVEOD0="
>>> modified = "NWE3MGQzMTBhYWYyODUxZTFlN2QwOWY2OWFmOGE5ZjMtMmUzOGIxZWNlZTVkNDUzNjkyYTg2NDAxYTVhZjk0MzUwMDAyLUx3QTF1OGpXWC8zelM2TUt0NG9pbW1qZzVEOD1="
>>> origin == modified
False
>>> origin_decode = base64.b64decode( origin )
>>> modified_decode = base64.b64decode( modified )
>>> origin_decode == modified_decode
True
>>> origin_decode
b'5a70d310aaf2851e1e7d09f69af8a9f3-2e38b1ecee5d453692a86401a5af94350002-LwA1u8jWX/3zS6MKt4oimmjg5D8='
>>> modified_decode
b'5a70d310aaf2851e1e7d09f69af8a9f3-2e38b1ecee5d453692a86401a5af94350002-LwA1u8jWX/3zS6MKt4oimmjg5D8='

WTF, 这是怎么回事,为什么两个解码的结果是一样的?再继续修改看看是怎么回事?

>>> modified = "NWE3MGQzMTBhYWYyODUxZTFlN2QwOWY2OWFmOGE5ZjMtMmUzOGIxZWNlZTVkNDUzNjkyYTg2NDAxYTVhZjk0MzUwMDAyLUx3QTF1OGpXWC8zelM2TUt0NG9pbW1qZzVEOD2="
>>> modified_decode = base64.b64decode( modified )
>>> origin_decode == modified_decode
True
>>> modified = "NWE3MGQzMTBhYWYyODUxZTFlN2QwOWY2OWFmOGE5ZjMtMmUzOGIxZWNlZTVkNDUzNjkyYTg2NDAxYTVhZjk0MzUwMDAyLUx3QTF1OGpXWC8zelM2TUt0NG9pbW1qZzVEOD3="
>>> modified_decode = base64.b64decode( modified )
>>> origin_decode == modified_decode
True
>>> modified = "NWE3MGQzMTBhYWYyODUxZTFlN2QwOWY2OWFmOGE5ZjMtMmUzOGIxZWNlZTVkNDUzNjkyYTg2NDAxYTVhZjk0MzUwMDAyLUx3QTF1OGpXWC8zelM2TUt0NG9pbW1qZzVEOD4="
>>> modified_decode = base64.b64decode( modified )
>>> origin_decode == modified_decode
False

同样的步骤重复下去,会发现倒数第二个值竟然是以4单位的区间解码出来的结果是一样的。

为什么会这样呢?

看wiki百科关于base64的说明

由于Base64是6位编码,并且在现代计算机上,解码值被分成8位八位字节,因此Base64编码文本的每四个字符(4个六位字节=46=24位)代表三个八位字节的未编码文本或数据(3个八位字节=38=24位)。这意味着,当未编码输入的长度不是3的倍数时,编码输出必须添加填充,以便其长度是4的倍数。填充字符是=,这表示不需要更多的位来完全编码输入。

原因终于明白了,这是base64编码补位的问题。

在系统上,这个对象ID的校验是64位解码后,变成A-B-C三段,然后对C和f(A,B)进行比较,f是运算过程。由于补位,导致上面篡改的对象ID都可以解成同一个,所以通过校验。而系统的黑名单又是对象ID作为key,没有这个key,就认为是不存在黑名单,所以就绕过了黑名单的检测。

解决方法

由于黑名单的key有一些格式限制,不能使用base64解码出来的内容,所以,只能继续用对象ID作为key。黑名单的key生成改成这种方式,经验证OK

import base64
bs = base64.b64decode( obj_id )
obj_id = base64.b64encode( bs ).decode('utf-8')


原文始发于微信公众号(debugeeker):base64的天坑

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年6月16日08:59:22
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   base64的天坑https://cn-sec.com/archives/923221.html

发表评论

匿名网友 填写信息