freeBuf
主站

分类

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

特色

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

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

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

FreeBuf+小程序

FreeBuf+小程序

Shiro CVE-2020-13933 路径绕过(越权)
2025-01-18 16:24:56
所属地 广东省

漏洞描述

Apache Shiro before 1.6.0, when using Apache Shiro, a specially crafted HTTP request may cause an authentication bypass.

漏洞条件

  • shiro < 1.6.0

  • 分号使用url编码传递 :%3b,不能直接传递明文

  • 注意:

/admin/*  --> 不匹配 /admin
/admin/**  -->匹配  /admin

image

漏洞复现

【注】:以下漏洞复现中其实不登入也可以,因为是直接绕过shiro,所以验证和访问控制都被绕过了。这里只是为了更好的展现越权(绕过访问控制)而登入一个低权限账户。不登录的话,就是漏洞描述中的“authentication bypass”。

环境:

shiro : 1.5.3				  //使用的还是javax
spring-boot:2.7.4             //3.xx版本 最低java 17且依赖的是jakarta

shiro配置:

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


@Bean
    ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(securityManager);
        bean.setLoginUrl("/login");
        bean.setSuccessUrl("/loginSuccess");
        bean.setUnauthorizedUrl("/unauthorized");
        LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
        //url --> filter1,filter2....
        map.put("/print", "authc, perms[printer:print]");
        map.put("/query", "authc, perms[printer:query]");
        map.put("/admin/*", "authc, roles[admin]");  //注意不可以是"/admin/**"
        map.put("/login","authc");
        bean.setFilterChainDefinitionMap(map);
        return bean;
    }
//shiro.ini


# format: roleName = permission1, permission2, ..., permissionN
[roles]
user = printer:print
admin = printer:*


# format: username = password, role1, role2, ..., roleN
[users]
user1 = pswd123, user
admin1 = pswd321, admin

controller方法:

@GetMapping("/admin/{param}")
    public String adminInfo(@PathVariable String param) {

        return "Admin Info: " + param;
    }

具体步骤

  1. 以user1的身份登入,获取cookie;(不登入也可以)
    image

  2. 恶意访问网站:/admin/%3bhello
    image
    越权成功!!!

漏洞分析

漏洞入口(不是具体位置):PathMatchingFilterChainResolver.getChain(...)

image

调试
请求路径:/admin/%3bhello

1.进入getChain:

image
2. 进入getPathWithinApplication():
image
image
可以看到getServletPath(),已经对url解码了(%3b--> ;)

查看removeSemicolon()源码:

private static String removeSemicolon(String uri) {
        int semicolonIndex = uri.indexOf(';');
        return (semicolonIndex != -1 ? uri.substring(0, semicolonIndex) : uri);
    }
//是去除分号后面所有内容(包括分号)

因此返回值:

image

后面匹配时会去掉末尾的分割符/

  1. 匹配路径:获取所有配置路径,然后遍历匹配
    image
    最终结果:不匹配
    image
    因此绕过了shiro。


spring为什么最终能定位到具体的controller?

入口函数:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getHandlerInternal

定位到获取查询路径的函数:iniLookupPath(request)

image

可以看到在去除分号前,并没有对请求url进行解码。

进入removeSemicolonContent(lookupPath):
image

返回入口:

image

因为没有解码,导致无法找到分号,故直接返回。
后面经过多轮匹配最终是匹配到了对应方法:

image

根据漏洞复现最终响应可以知道,传参controller前对%3b解码了
总结

shiro与spring对路径的处理不同导致的。前者是先对路径解码后再去除分号。后者是去除分号后再解码。

漏洞修复

经过调试发现(此时shiro版本为1.6.0,其他配置不变),默认添加一个 filterChain:(即便你没有配置)

/** --> InvalidRequestFilter

image

定位到对应修复代码:
image.png
第一处红框处:
image.png
第二处红框处:添加了一个类
image

只展示核心算法

其逻辑很简单,就是查看路径中是否有非法字符,有则默认不通过。


由于其他匹配规则不变,所以毫无疑问最终会匹配到/**
所以最终结果是:不通过
image

image

总结:

不改变原来路径处理逻辑的基础上,添加一个InvalidFilter类来检查请求路径;并且会在初始化时自动添加一个

/** --> InvalidFilter

的filterChain,从而截断攻击。

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