freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

shiro-web CVE-2010-3863 路径绕过
2024-11-16 11:55:06
所属地 湖北省

[condition] < shiro 1.1.0

背景

  1. 如果对shiro-web的原理不清楚可以参考以下链接:shiro-web 软件分析

  2. 发送URL前,浏览器本身会对../``./这类路径进行处理,将其还原成实际路径,然后才会发送请求。

【url栏】http://ip:port/test/../admin.html   ---> 【请求包】 http://ip:port/admin.html

但是,可以拦截请求包,对URL进行篡改

漏洞环境

https://github.com/dota-st/vulnEnv

文件结构:

image

主要配置文件:

realm.ini:

image

ShiroConfig:

package com.vuln.shirodemo.Shiro;

import java.util.LinkedHashMap;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Created by dotast on 2022/10/14 15:13
 */
@Configuration
public class ShiroConfig {

    @Bean
    public IniRealm getIniRealm(){
        return new IniRealm("classpath:realm.ini");
    }

    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm){
        return new DefaultWebSecurityManager(realm);
    }


    /*
     * anon:无需认证就可以访问
     * authc:必须认证才能访问
     * user:必须拥有记住我功能才能访问
     * perms:拥有某个资源的权限才能访问
     * role:拥有某个角色的权限才能访问
     * */
    @Bean
    ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(defaultWebSecurityManager);
        bean.setLoginUrl("/login.html");
        LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
        map.put("/admin.html", "authc, roles[admin]");
        map.put("/user.html", "authc, roles[user]");
        map.put("/**", "anon");
        bean.setFilterChainDefinitionMap(map);
        return bean;
    }
}

漏洞分析

payload:

GET /./admin.html HTTP/1.1
Host: localhost:8088
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Priority: u=0, i

FlowChart:shiro-web整体流程

Main.png

红色部分为漏洞点
详情:shiro-web 软件分析

代码分析

PathMatchingFilterChainResolver.getChain(...):

image

局部变量

image可以看出没有做任何过滤,直接获取url

image

配置文件里设置的FilterChain的名字序列

最终匹配到/**
该链只有anon:AnonymousFilter一个过滤器

image

Anonymous的过滤逻辑:允许任何人通过

image

漏洞修复

如果是我,我会如何修复?

当然是像浏览器那样,将带有../的路径规范化后再进行比较,比较逻辑不变

实际修复

shiro-1.1.0:

  1. request中url没有变
    image

  2. 但是requstURI 被规范化了
    image
    所以一定是getPathWithApplication(request)内部逻辑发生改变了
    最后不断跟进找到:

//org.apache.shiro.web.util.WebUtils::

//shiro-1.0.1-incubating
public static String getRequestUri(HttpServletRequest request) {
        String uri = (String) request.getAttribute(INCLUDE_REQUEST_URI_ATTRIBUTE);
        if (uri == null) {
            uri = request.getRequestURI();
        }
        return decodeAndCleanUriString(request, uri);
    }


//shiro-1.1.0
public static String getRequestUri(HttpServletRequest request) {
    String uri = (String)request.getAttribute("javax.servlet.include.request_uri");
    if (uri == null) {
        uri = request.getRequestURI();
    }

    return normalize(decodeAndCleanUriString(request, uri));
}

image
添加了一个normalize函数

private static String normalize(String path, boolean replaceBackSlash) {
        if (path == null) {
            return null;
        } else {
            String normalized = path;
            //'\' ASCII 是 92
            if (replaceBackSlash && normalized.indexOf(92) >= 0) {
                normalized = normalized.replace('\\', '/');
            }

            if (normalized.equals("/.")) {
                return "/";
            } else {
                if (!normalized.startsWith("/")) {
                    normalized = "/" + normalized;
                }

                while(true) {
                    int index = normalized.indexOf("//");
                    if (index < 0) {
                        while(true) {
                            index = normalized.indexOf("/./");
                            if (index < 0) {
                                while(true) {
                                    index = normalized.indexOf("/../");
                                    if (index < 0) {
                                        return normalized;
                                    }

                                    if (index == 0) {
                                        return null;
                                    }
// ‘/’ ASCII :47
                                    int index2 = normalized.lastIndexOf(47, index - 1);
                                    //循环去除 ‘/../’
                                    normalized = normalized.substring(0, index2) + normalized.substring(index + 3);
                                }
                            }
							//循环去除 ‘/./’
                            normalized = normalized.substring(0, index) + normalized.substring(index + 2);
                        }
                    }
					//循环去‘//’
                    normalized = normalized.substring(0, index) + normalized.substring(index + 1);
                }
            }
        }
    }

Reference

JavaSec/12.Shiro/CVE-2010-3863权限绕过/index.md at main · Y4tacker/JavaSec (github.com)

# 漏洞分析 # Java代码审计
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录