您好,登錄后才能下訂單哦!
這篇“如何實現Java的Filter權限繞過”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“如何實現Java的Filter權限繞過”文章吧。
常見的實現方式,在不調用Spring Security、Shiro等權限控制組件的情況下,會使用Filter獲取請求路徑,進行校驗。
編寫一個servlet
package com.nice0e3;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/helloServlet")
public class helloServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("hello!!!");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
定義一個Filter
package com.nice0e3.filter;
import com.nice0e3.User;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter("/*")
public class demoFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
String uri = request.getRequestURI();
StringBuffer requestURL = request.getRequestURL();
System.out.println(requestURL);
if(uri.startsWith("/system/login")) { //登陸接口設置?白名單,即登錄頁面
System.out.println("login_page");
resp.getWriter(). write("login_page");
chain.doFilter(request, resp);
}
else if(uri.endsWith(".do")||uri.endsWith(".action")) {
//檢測當前?戶是否登陸
User user =(User) request.getSession().getAttribute("user");
if(user == null) {
resp.getWriter(). write("unauthorized access"); //未授權訪問
System.out.println("unauthorized access");
resp.getWriter(). write("go to login_page");//跳轉登錄
System.out.println("go to login_page");
}
}
}
public void init(FilterConfig config) throws ServletException {
}
}
這里使用 request.getRequestURI();
獲取URI為 /system/login
開頭 則直接放行。結尾,為.do
和.action
的請求去做校驗,獲取session有沒有user的值,沒有的話即返回unauthorized access
,如果不為.do
和.action
的請求或session中存在user即放行。
訪問main頁面,顯示未授權訪問并且跳轉到登錄的頁面
在Java中通常會使用request.getRequestURL()
和request.getRequestURI()
這兩個方法獲取請求路徑,然后對請求路徑做校驗。
../
繞過方式
這里采用../
的方式繞過
這里就繞過了,權限控制,直接能訪問到main,而不是顯示未授權訪問。在繞過時候可以找一些白名單的路徑,然后使用../
去繞過。
payload:/system/login/../../login/main.do
上圖可以看到我們前面為system/login
開頭
符合匹配的規則,而匹配上該規則后則是直接放行,讓系統認為訪問路徑是一個登錄的路徑,但在后面加入2個../
進行跳轉到根目錄,并且拼接上login/main.do
,這時候實際訪問到的是http://127.0.0.1/login/main.do
。
但使用
StringBuffer requestURL = request.getRequestURL(); if(requestURL.toString().startsWith("/system/login"))
request.getRequestURL();
該方法獲取URL是攜帶http://127.xxx
等信息的。其實這里比較廢話,因為驗證首部的字符路徑的話,使用 request.getRequestURI();
來獲取請求路徑部分來校驗。
URL截斷繞過
基于前面Filter代碼將../
進行過濾
package com.nice0e3.filter;
import com.nice0e3.User;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter("/*")
public class demoFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
String uri = request.getRequestURI();
StringBuffer requestURL = request.getRequestURL();
System.out.println(requestURL);
if(uri.startsWith("/system/login")) { //登陸接口設置?白名單,即登錄頁面
System.out.println("login_page");
resp.getWriter(). write("login_page");
chain.doFilter(request, resp);
}
else if(uri.endsWith(".do")||uri.endsWith(".action")) {
//檢測當前?戶是否登陸
User user =(User) request.getSession().getAttribute("user");
if(user == null) {
resp.getWriter(). write("unauthorized access"); //未授權訪問
System.out.println("unauthorized access");
resp.getWriter(). write("go to login_page");//跳轉登錄
System.out.println("go to login_page");
}
}
}
public void init(FilterConfig config) throws ServletException {
}
}
添加多了一個uri.contains("./")
做過濾只要包含./
字符直接報錯。
這時候會報錯,可見上圖。可;
進行繞過
payload:/login/main.do;123
繞過分析
URL中有一個保留字符分號;
,主要為參數進行分割使用,有時候是請求中傳遞的參數太多了,所以使用分號;
將參數對(key=value)連接起來作為一個請求參數進?傳遞。
再來看到代碼,代碼中識別.do
和.action
的后綴的字符,而加入;
加上隨便內容后,代碼中就識別不到了。則會走到最下面的chain.doFilter(request,resp);
,而在后面添加;
分號不會對地址的訪問有任何影響。
多/
繞過
創建一個后臺接口,只允許admin用戶登錄訪問
package com.nice0e3.Servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/system/UserInfoSearch.do")
public class UserInfoServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("admin_login!!!");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
而權限控制這步肯定是在Filter里面實現
String uri = request.getRequestURI();
if(uri.equals("/system/UserInfoSearch.do")){
User user =(User) request.getSession().getAttribute("user");
String role = user.getRole();
if(role.equals("admin")) {
//當前?用戶為admin,允許訪問該接?
chain.doFilter(request, resp);
}
else {
resp.getWriter().write("Unauthorized");
return;
}
}
這時候去對/system/UserInfoSearch.do
做了校驗,獲取URI地址后匹配如果是這個/system/UserInfoSearch.do
,則驗證用戶身份,加入不為admin,則顯示Unauthorized
,越權訪問。
可直接訪問到admin用戶才可訪問的頁面下。
payload: //system/UserInfoSearch.do;123
繞過分析
看到代碼中只是對比了URI是否為/system/UserInfoSearch.do
,而多加一個/
并不影響正常解析,而又能讓該規則匹配不到。
URL編碼繞過
還是用上面的代碼演示,繞過手法則是換成url編碼繞過的方式。
payload:/system/%55%73%65%72%49%6e%66%6f%53%65%61%72%63%68%2e%64%6f
繞過分析
當Filter處理完相關的流程后,中間件會對請求的URL進行一次URL解碼操作,然后請求解碼后的Servlet,而在request.getRequestURL(
)和request.getRequestURI()
中并不會自動進行解碼,所以這時候直接接收過來進行規則匹配,則識別不出來。這時候導致了繞過。
Spring MVC中追加/
繞過
在SpringMVC中假設以如下方法配置:
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
特定情況下Spring匹配web路徑的時候會容錯后面的/
如,/admin/main.do/
修復
使用該代碼接受URI
String uri1 = request.getServletPath() + (request.getPathInfo() != null ? request.getPathInfo() : "");
下面來嘗試前面的幾種繞過方式。
分號階段繞過 payload: /login/main.do;123
多/
繞過payload: //system/UserInfoSearch.do;123
URL編碼繞過payload:/system/%55%73%65%72%49%6e%66%6f%53%65%61%72%63%68%2e%64%6f
../
繞過payload:/system/login/../../login/main.do
均不可用,使用上面的方式接受URI后,接受過去的時候發送特殊字符一律被剔除了。打斷點可見。
關注點
前面提到過request.getRequestURL()
和request.getRequestURI()
,這些危險字符并不會自動剔除掉。可重點關注該方法。
以上就是關于“如何實現Java的Filter權限繞過”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。