freeBuf
主站

分类

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

特色

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

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

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

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

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

shiro-web 软件分析
mag1c7 2025-01-06 15:41:43 123772
所属地 广东省

shiro-web

看之前可以先了解:shiro-core 分析

  • shiro-web是shiro-core的wrapper

其特征都是 ”实现一方,调用一方“ 注:调用不一定要显式的调用(代码上的),隐式调用也算,比如子类对于没有重写父类的方法,其字节码的函数引用与父类的一致,所以也可算作子类调用了父类的函数

比如shiro-web实现了Filter接口,从而使得Tomcat可以调用,同时ShiroFilter,又调用了WebSubject,
从抽象的接口的意义上讲,Shiro***Filter调用WebSubject相关验证和授权接口,但这些接口是继承自Subject的,所以会调用Subject接口,从而调用了shiro-core

如图:红色代表shiro-core, 蓝色是shiro-web

这里的ShiroFilter不是具体的某个类,而是代表所有shiro内的Filter

image

从具体实现的意义过程来讲,当然是类调用类,但这是实现,不是"概念",从抽象意义讨论调用过程比较契合概念.

同时由于其是软件级别的wrapper,shiro-core与其wrapper(shiro-web) 不是完全单向的调用关系,某些情况shiro-core会调用wrapper中的实现,比如SessionManager的两种实现

同时shiro-web与Servlet容器也不是单向关系

Apache Shiro Web Support | Apache Shiro| session_management

结构分析 && 流程分析

shiro-web主要通过继承的方式,让shiro-web容器直接依赖Webxxx自己的类,从而实现shiro-web与shiro-core解耦

eg:

image

image

类似的还有WebSecurityManger,

servlet容器直接依赖shiroFilter,shiroFilter又直接依赖WebSubject,WebSubject又直接依赖WebSecurityManger....它们的逻辑大部分都由shiro-core实现,这种方式使得shiro-web不在代码上直接依赖shiro-core:shiro-web与shiro-core解耦

因此对于这些部分不再赘述,直接看shiro-core即可,只分析shiro-web特有部分;

==由于shiro-web特有部分非常少故直接从实现阶段分析==

Filter

类图
image

  • 从OncePerRequestFilter开始有一个分支,其中右边是直接对接servlet容器中的Filter,也就是说对于servlet容器,shiro-web只是一个Filter,其名字为ShiroFilter,(通过web.xml配置)

  • 左边是shiro-web实际执行过滤逻辑的Filter

OncePerRequestFilter

OncePerRequestFilter.doFilter()
image

实际逻辑由doFilterInternal()决定,它由子类实现

ShiroFilter(AbstractShiroFilter)

初始化(读取解析配置文件)

image

doFilter()

AbstractShiroFilter::

image
核心算法:获取执行链,执行过滤操作
image
关于获取执行链:先获取一个FilterChainResolver,然后调用getChain(request,response,oriChain)
image

getExecutionChain()返回的chain是ProxiedFilterChain,以及oriChain是servlet容器中实际的过滤链后面讨论

AdviceFilter

A Servlet Filter that enables AOP-style "around" advice for a ServletRequest via preHandle, postHandle, and afterCompletion hooks.

image

preHandle等“advice()"主要由子类实现;

AccessControlFilter

主要分类:最重要的是左边两个分类

image

InvalidRequestFilter:用于封锁恶意请求

UserFilter:
Filter that allows access to resources if the accessor is a known user, which is defined as having a known principal. This means that any user who is authenticated or remembered via a 'remember me' feature will be allowed access from this filter. If the accessor is not a known user, then they will be redirected to the loginUrl

AuthenticationFilter

image

AuthorizationFilter

image

FilterChainManager

A FilterChainManager manages the creation and modificationof Filter chains from an available pool of Filter instances.

image

NamedFilterList extend List
NamedFilterList是装载NameableFilter(及其子类)的列表,(NameableFilter在上面Filter部分的图中),NameableFilter是我们在配置文件中配置的过滤器:

[main]
shiro.loginUrl = /login
shiro.successUrl = /loginSuccess


filtername = className
[users]
# format: username = password, role1, role2, ..., roleN

admin=123456,admin
user=123456,user



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

# value部分就是NameableFilter
[urls]
/login = authc
/admin = authc, roles[admin]
/user = authc , roles[user]
/** = anon

key是url同时也是filterChain的名字,value部分是filtername,可以配置多个filtername(必须在main部分声明filtername = className,除非使用的是Default Filter),在[urls]部分中
/some/path/** = myFilter,otherFilter
表示的意思是,当前这个路径(/some/path/**)需要经过 myFilter,otherFilter两个filter

以下是Default Filter
imagefrom:Apache Shiro Web Support#default_filters | Apache Shiro

FilterChainResolver

根据request.url 返回对应的FilterChain

其实现类只有一个:PathMatchingFilterChainResolver

image

实现方式很简单,(1)获取requestUrl, (2)再遍历所有filterChainNames(pathPattern),并一个一个比对,比对成功则调用FIlterChainManger.proxy(originalChian,pathPattern),并返回,

跟进proxy():

//DefaultFilterChainManager::
public FilterChain proxy(FilterChain original, String chainName) {
        NamedFilterList configured = getChain(chainName);//根据名字取出配置中相应的的过滤器链
        if (configured == null) {
            String msg = "There is no configured chain under the name/key [" + chainName + "].";
            throw new IllegalArgumentException(msg);
        }
        return configured.proxy(original);  //代理
    }

//SimpleNamedFilterList::
public FilterChain proxy(FilterChain orig) {
//调用构造函数,传入servlet容器中的过滤器链(orig)和shiro自身的链(NamedFilterList)
        return new ProxiedFilterChain(orig, this);
    }

ProxiedFilterChain

architecture

image

  • filters: shiro实际的过滤器

  • orig: servlet容器中原来的链

  • dofilter()

//ProxiedFilterChain::
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
        if (this.filters == null || this.filters.size() == this.index) {
            //we've reached the end of the wrapped chain, so invoke the original one:
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Invoking original filter chain.");
            }
            this.orig.doFilter(request, response);
        } else {
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Invoking wrapped filter at index [" + this.index + "]");
            }
            this.filters.get(this.index++).doFilter(request, response, this);
        }
    }
}

大致逻辑就是先调用filters的doFilter,当执行完后,就执行orig.doFilter(...) ,从而执行servlet容器中下一个过滤器,这也意味着ShiroFilter结束了
Ma.png

总体流程

根据上述内容得出:(不包括初始化部分)
Main.png

# Java代码审计 # 软件分析
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 mag1c7 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
软件分析/代码审计
mag1c7 LV.5
这家伙太懒了,还未填写个人描述!
  • 24 文章数
  • 10 关注者
[PoC] Tomcat CVE-2025-24813 RCE
2025-03-12
DJL CVE-2025-0851 绝对路径遍历
2025-03-09
Tomcat CVE-2024-50379 条件竞争导致命令执行
2025-02-27
文章目录