├── README.md ├── app.jar ├── docker-compose.yml ├── images ├── 20221130172657-23125b56-7091-1.png ├── 20221130172704-26bfa8da-7091-1.png ├── 20221130172718-2f9afe50-7091-1.png ├── 20221130172910-723fddf2-7091-1.png ├── 20221130172921-7897c976-7091-1.png └── 20221130172927-7c76e054-7091-1.png ├── pom.xml └── src └── main ├── java └── com │ └── example │ └── demo │ ├── HeapdumpShiroVulnApplication.java │ ├── config │ ├── MyRealm.java │ └── ShiroConfig.java │ └── controller │ └── LoginController.java └── resources ├── application.properties └── templates ├── 403.html ├── index.html └── login.html /README.md: -------------------------------------------------------------------------------- 1 | # heapdump_shiro_vuln 2 | 2024.5.16 3 | 4 | 没想到这个环境还有挺多人用,我更新了一下,打包成了jar,并且可以docker运行:`docker compose up -d` 5 | 6 | ## 0x01 7 | 8 | heapdump泄露Shiro key从而RCE的漏洞环境 9 | 10 | This is a heapdump leaks Shiro key causing RCE vulnerability environment. 11 | 12 | Shiro deserialization is an unfixable vulnerability. As long as you have the Shiro key, you can exploit it, Visit https://xz.aliyun.com/t/11908 for full content. 13 | ## 0x02 14 | After loading the vulnerability environment, you can see that the Shiro version is 1.8.0: 15 | ![1](https://github.com/P4r4d1se/heapdump_shiro_vuln/blob/main/images/20221130172657-23125b56-7091-1.png) 16 | 17 | Access /actuator/heapdump on port 8080 to obtain the heapdump file: 18 | ![1](https://github.com/P4r4d1se/heapdump_shiro_vuln/blob/main/images/20221130172704-26bfa8da-7091-1.png) 19 | 20 | Get the shiro key from heapdump: 21 | ![1](https://github.com/P4r4d1se/heapdump_shiro_vuln/blob/main/images/20221130172718-2f9afe50-7091-1.png) 22 | 23 | Vulnerability exploited successfully: 24 | ![1](https://github.com/P4r4d1se/heapdump_shiro_vuln/blob/main/images/20221130172910-723fddf2-7091-1.png) 25 | 26 | Restart the server to obtain the shiro key again. You can see that the key has changed, because a new key is randomly generated every time it is started: 27 | ![1](https://github.com/P4r4d1se/heapdump_shiro_vuln/blob/main/images/20221130172921-7897c976-7091-1.png) 28 | 29 | Vulnerability exploited successfully again using new key: 30 | ![1](https://github.com/P4r4d1se/heapdump_shiro_vuln/blob/main/images/20221130172927-7c76e054-7091-1.png) 31 | -------------------------------------------------------------------------------- /app.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P4r4d1se/heapdump_shiro_vuln/1f49ab09e8c102f4189fabee0be0a25a2059e949/app.jar -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | heapdump_shiro_vuln: 3 | image: openjdk:8-jdk 4 | volumes: 5 | - "./app.jar:/app/app.jar" 6 | working_dir: /app 7 | command: java -jar app.jar 8 | ports: 9 | - "8080:8080" 10 | -------------------------------------------------------------------------------- /images/20221130172657-23125b56-7091-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P4r4d1se/heapdump_shiro_vuln/1f49ab09e8c102f4189fabee0be0a25a2059e949/images/20221130172657-23125b56-7091-1.png -------------------------------------------------------------------------------- /images/20221130172704-26bfa8da-7091-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P4r4d1se/heapdump_shiro_vuln/1f49ab09e8c102f4189fabee0be0a25a2059e949/images/20221130172704-26bfa8da-7091-1.png -------------------------------------------------------------------------------- /images/20221130172718-2f9afe50-7091-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P4r4d1se/heapdump_shiro_vuln/1f49ab09e8c102f4189fabee0be0a25a2059e949/images/20221130172718-2f9afe50-7091-1.png -------------------------------------------------------------------------------- /images/20221130172910-723fddf2-7091-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P4r4d1se/heapdump_shiro_vuln/1f49ab09e8c102f4189fabee0be0a25a2059e949/images/20221130172910-723fddf2-7091-1.png -------------------------------------------------------------------------------- /images/20221130172921-7897c976-7091-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P4r4d1se/heapdump_shiro_vuln/1f49ab09e8c102f4189fabee0be0a25a2059e949/images/20221130172921-7897c976-7091-1.png -------------------------------------------------------------------------------- /images/20221130172927-7c76e054-7091-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P4r4d1se/heapdump_shiro_vuln/1f49ab09e8c102f4189fabee0be0a25a2059e949/images/20221130172927-7c76e054-7091-1.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | com.example 6 | shiro-springboot 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | 11 | org.springframework.boot 12 | spring-boot-starter-parent 13 | 2.2.13.RELEASE 14 | 15 | 16 | 17 | 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-web 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-actuator 32 | 33 | 34 | 35 | org.apache.shiro 36 | shiro-spring 37 | 1.8.0 38 | 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-thymeleaf 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-maven-plugin 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/HeapdumpShiroVulnApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class HeapdumpShiroVulnApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(HeapdumpShiroVulnApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/config/MyRealm.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.config; 2 | 3 | import org.apache.shiro.authc.AuthenticationException; 4 | import org.apache.shiro.authc.AuthenticationInfo; 5 | import org.apache.shiro.authc.AuthenticationToken; 6 | import org.apache.shiro.authc.SimpleAuthenticationInfo; 7 | import org.apache.shiro.authc.UsernamePasswordToken; 8 | import org.apache.shiro.authz.AuthorizationInfo; 9 | import org.apache.shiro.authz.SimpleAuthorizationInfo; 10 | import org.apache.shiro.realm.AuthorizingRealm; 11 | import org.apache.shiro.subject.PrincipalCollection; 12 | 13 | import java.util.HashSet; 14 | import java.util.Set; 15 | 16 | public class MyRealm extends AuthorizingRealm { 17 | 18 | @Override 19 | protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 20 | UsernamePasswordToken userToken = (UsernamePasswordToken) token; 21 | 22 | // 模拟用户验证,这里可以替换成数据库查询 23 | if ("user".equals(userToken.getUsername())) { 24 | return new SimpleAuthenticationInfo(userToken.getUsername(), "password", getName()); 25 | } 26 | 27 | return null; 28 | } 29 | 30 | @Override 31 | protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { 32 | String username = (String) principals.getPrimaryPrincipal(); 33 | 34 | // 模拟角色和权限的获取,这里可以替换成从数据库或其他数据源获取 35 | Set roles = new HashSet<>(); 36 | Set permissions = new HashSet<>(); 37 | 38 | // 假设用户 "user" 拥有角色 "admin" 和权限 "read" 39 | if ("user".equals(username)) { 40 | roles.add("admin"); 41 | permissions.add("read"); 42 | } 43 | 44 | SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(roles); 45 | authorizationInfo.setStringPermissions(permissions); 46 | 47 | return authorizationInfo; 48 | } 49 | } -------------------------------------------------------------------------------- /src/main/java/com/example/demo/config/ShiroConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.config; 2 | 3 | import org.apache.shiro.mgt.SecurityManager; 4 | import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; 5 | import org.apache.shiro.spring.web.ShiroFilterFactoryBean; 6 | import org.apache.shiro.web.mgt.DefaultWebSecurityManager; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | import java.util.LinkedHashMap; 11 | import java.util.Map; 12 | 13 | @Configuration 14 | public class ShiroConfig { 15 | 16 | @Bean 17 | public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { 18 | ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); 19 | shiroFilterFactoryBean.setSecurityManager(securityManager); 20 | 21 | // 配置登录的 URL 和成功后跳转的 URL 22 | shiroFilterFactoryBean.setLoginUrl("/login"); 23 | shiroFilterFactoryBean.setSuccessUrl("/index"); 24 | 25 | // 配置未授权的 URL 26 | shiroFilterFactoryBean.setUnauthorizedUrl("/403"); 27 | 28 | // 配置过滤规则 29 | Map filterChainDefinitionMap = new LinkedHashMap<>(); 30 | filterChainDefinitionMap.put("/logout", "logout"); 31 | filterChainDefinitionMap.put("/actuator/**", "anon"); // 允许未认证访问 actuator 端点 32 | filterChainDefinitionMap.put("/**", "authc"); 33 | shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); 34 | 35 | return shiroFilterFactoryBean; 36 | } 37 | 38 | @Bean 39 | public SecurityManager securityManager() { 40 | DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); 41 | securityManager.setRealm(myRealm()); 42 | return securityManager; 43 | } 44 | 45 | @Bean 46 | public MyRealm myRealm() { 47 | return new MyRealm(); 48 | } 49 | 50 | @Bean 51 | public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { 52 | AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); 53 | advisor.setSecurityManager(securityManager); 54 | return advisor; 55 | } 56 | } -------------------------------------------------------------------------------- /src/main/java/com/example/demo/controller/LoginController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.controller; 2 | 3 | import org.apache.shiro.SecurityUtils; 4 | import org.apache.shiro.authc.UsernamePasswordToken; 5 | import org.apache.shiro.subject.Subject; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.PostMapping; 9 | 10 | @Controller 11 | public class LoginController { 12 | 13 | @GetMapping("/login") 14 | public String login() { 15 | return "login"; 16 | } 17 | 18 | @PostMapping("/login") 19 | public String login(String username, String password) { 20 | Subject subject = SecurityUtils.getSubject(); 21 | UsernamePasswordToken token = new UsernamePasswordToken(username, password); 22 | try { 23 | subject.login(token); 24 | return "redirect:/index"; 25 | } catch (Exception e) { 26 | return "login"; 27 | } 28 | } 29 | 30 | @GetMapping("/index") 31 | public String index() { 32 | return "index"; 33 | } 34 | 35 | @GetMapping("/403") 36 | public String unauthorized() { 37 | return "403"; 38 | } 39 | } -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # 应用服务 WEB 访问端口 2 | server.port=8080 3 | 4 | spring.thymeleaf.enabled=true 5 | spring.thymeleaf.cache=false 6 | # Actuator 配置 7 | management.endpoints.web.exposure.include=* -------------------------------------------------------------------------------- /src/main/resources/templates/403.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 |

403 Forbidden

8 |

You do not have permission to access this page.

9 | 10 | 11 | -------------------------------------------------------------------------------- /src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Index 5 | 6 | 7 |

Welcome to the Index Page

8 | Logout 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/main/resources/templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Login 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | --------------------------------------------------------------------------------