base64解码小trick
N1CTF Junior 2025 2/2 中的,也是不出意料没做出来
python 的 base64 解码逻辑和命令行的 base64 命令是不一致的
Python 的base64.b64decode(..., validate=True)
在遇到 padding(=
)后还有额外的 base64 字符,会报错,而用默认解码base64.b64decode(...)
时,只会解出等号前的那一部分
但是命令行中会将两段都成功解出并拼接
这是因为 Base64 的编码本质上是一系列 4 字符为一组的字符块,最后一组可能用 =
填充以满足块对齐,根据解析器类型的不同,解析方法也会有区别
- **严格解析器(Python 的 **
**validate=True**
):一旦遇到合法的填充字符=
,就认为这是该 base64 段的结束;如果填充后仍有数据,会报错为“padding 之后有额外数据” - 宽松/流式解析器(GNU
**base64 -d**
等):通常会把整个输入当作可能包含多个 base64 段(或忽略某些格式约束),会尽量解出每一段能解的部分,因此出现“先解出第一段,到 padding 再继续解出第二段并拼接”这种行为。实现细节取决于具体工具/版本,但 GNU coreutils 的实现就是允许这种拼接
复现:
1 | python -c "import base64;print(base64.b64decode('MS4xLjEuMQ==O1BST09G'))" |
当我们在命令行运行这段代码,只会返回b'1.1.1.1'
(只解出第一个块)
1 | echo 'MS4xLjEuMQ==O1BST09G' | base64 -d |
这个会输出两段拼接的解码结果:1.1.1.1;PROOF
回到题目:
Ping
核心代码:
1 | def run_ping(ip_base64): |
对用户传入的 base64 的 ip 解码后进行审查,然后放入 command 中进行 base64,根据上面的 trick 我们直接构造 payload:
1 | MS4xLjEuMQ==OyBjYXQgL2ZsYWc= |
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.