java中的xss


0x01、XSS漏洞

總所周知,xss分為三類,反射型,存儲型xss,dom型xss。那xss還能有不一樣嗎?不,都一樣。php中的xss

那么我們就不細細講解了,畢竟大家看的懂php,那么java和php的漏洞原理都是一致的

0x02、反射型xss

<%=request.getParameter("id")%>

就這么短短一句話,也就是說,用戶輸入的參數沒有進行過濾,就會進行反射型xss

0x02、存儲型xss

test.jsp 代碼:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.util.*" %>
<%
    String username = request.getParameter("username");
    String content = request.getParameter("content");

    String guestBookKey = "GUEST_BOOK";
    List<Map<String, String>> comments = new ArrayList<Map<String, String>>();

    if (content != null) {
        Object obj = application.getAttribute(guestBookKey);

        if (obj != null) {
            comments = (List<Map<String, String>>) obj;
        }

        Map<String, String> comment = new HashMap<String, String>();
        String              ip      = request.getHeader("x-real-ip");

        if (ip == null) {
            ip = request.getRemoteAddr();
        }

        comment.put("username", username);
        comment.put("content", content);
        comment.put("ip", ip);
        comment.put("date", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));

        comments.add(comment);

        application.setAttribute(guestBookKey, comments);
    }
%>
<html>
<head>
    <title>留言板</title>
</head>
<style>
    * {
        margin: 0;
        padding: 0;
    }
</style>
<body>
<div style="border: 1px solid #C6C6C6;">
    <div style="text-align: center;">
        <h2>在線留言板</h2>
    </div>
    <div>
        <dl>
            <%
                Object obj = application.getAttribute(guestBookKey);

                if (obj instanceof List) {
                    comments = (List<Map<String, String>>) obj;

                    for (Map<String, String> comment : comments) {
            %>
            <dd>
                <div style="min-height: 50px; margin: 20px; border-bottom: 1px solid #9F9F9F;">
                    <p><B><%=comment.get("username")%>
                    </B>[<%=comment.get("ip")%>] 於 <%=comment.get("date")%> 發表回復:</p>
                    <p style="margin: 15px 0 5px 0; font-size: 12px;">
                    <pre><%=comment.get("content")%></pre>
                    </p>
                </div>
            </dd>
            <%
                    }
                }
            %>
        </dl>
    </div>
    <div style="background-color: #fff; border: 1px solid #C6C6C6;">
        <form action="#" method="POST" style="margin: 20px;">
            昵稱: <input type="text" name="username" style="width:250px; height: 28px;"/><br/><br/>
            <textarea name="content" style="overflow: auto;width: 100%; height: 250px;"></textarea>
            <input type="submit" value="提交留言" style="margin-top: 20px; width: 80px; height: 30px;"/>
        </form>
    </div>
</div>
</body>
</html>

我們斷點慢慢走,不急,首先content是留言板的內容,然后username是昵稱。這邊判斷留言板內容不為空;然后走了進去,獲取域對象的這個guestBookKey的值。然后再判斷是否為空

判斷為空之后繼續往下走

然后這邊繼續存到hashmap當中。comments是個ArrayList類型的,他存儲的類型是map類型,同時兩邊都是字符串;然后再四個參數為一個comments。最后再設置到域對象當中

那么話不多說都知道,最后打印出來。重點就來了,我們知道xss語句一般是插入數據庫當中,然后再讀取出來。而java,則可以存儲到數據庫,也可以存儲到域對象當中。但是當Tomcat重啟之后,數據就會重置為空。

0x03、xss防御

4.1 htmlspecialchars

在PHP中通常會使用htmlspecialchars函數會將一些可能有攻擊威脅的字符串轉義為html實體編碼,這樣可以有效的避免XSS攻擊。

示例 - htmlspecialchars 轉義:

在Java中雖然沒有內置如此簡單方便的函數,但是我們可以通過字符串替換的方式實現類似htmlspecialchars函數的功能。

/**
 * 實現htmlSpecialChars函數把一些預定義的字符轉換為HTML實體編碼
 *
 * @param content 輸入的字符串內容
 * @return HTML實體化轉義后的字符串
 */
public static String htmlSpecialChars(String content) {
  if (content == null) {
    return null;
  }

  char[]        charArray = content.toCharArray();
  StringBuilder sb        = new StringBuilder();

  for (char c : charArray) {
    switch (c) {
      case '&':
        sb.append("&amp;");
        break;
      case '"':
        sb.append("&quot;");
        break;
      case '\'':
        sb.append("&#039;");
        break;
      case '<':
        sb.append("&lt;");
        break;
      case '>':
        sb.append("&gt;");
        break;
      default:
        sb.append(c);
        break;
    }
  }

  return sb.toString();
}

在存儲或者輸出請求參數的時候使用該方法過濾即可實現XSS防御。

4.2 全局的XSSFilter

package com.anbai.sec.vuls.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;

public class XSSFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;

        // 創建HttpServletRequestWrapper,包裝原HttpServletRequest對象,示例程序只重寫了getParameter方法,
        // 應當考慮如何過濾:getParameter、getParameterValues、getParameterMap、getInputStream、getReader
        HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(request) {
            public String getParameter(String name) {
                // 獲取參數值
                String value = super.getParameter(name);

                // 簡單轉義參數值中的特殊字符
                return value.replace("&", "&amp;").replace("<", "&lt;").replace("'", "&#039;");
            }
        };

        chain.doFilter(requestWrapper, resp);
    }

    @Override
    public void destroy() {

    }

}

web.xml添加XSSFilter過濾器:

<!-- XSS過濾器 -->
<filter>
  <filter-name>XSSFilter</filter-name>
  <filter-class>com.anbai.sec.vuls.filter.XSSFilter</filter-class>
</filter>

<filter-mapping>
  <filter-name>XSSFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

請求XSS示例程序:http://localhost:8000/modules/servlet/xss.jsp?input=%3Cscript%3Ealert(%27xss%27);%3C/script%3E

image-20201115164019678

經過全局過濾器轉義后的參數就不會再帶有XSS攻擊能力了。

4.3 RASP XSS攻擊防御

RASP可以實現類似於全局XSSFilter的請求參數過濾功能,比較穩定的一種方式是Hook到javax.servlet.ServletRequest接口的實現類的getParameter/getParameterValues/getParameterMap等核心方法,在該方法return之后插入RASP的檢測代碼。這種實現方案雖然麻煩,但是可以避免觸發Http請求參數解析問題(Web應用無法獲取getInputStream和亂碼等問題)。

示例 - RASP對getParameter返回值Hook示例:

image-20201115172732140

反射型的XSS防御相對來說比較簡單,直接禁止GET參數中出現<>標簽,只要出現就理解攔截,如:

http://localhost:8000/modules/servlet/xss.jsp?input=<script>alert('xss');</script>

過濾或攔截掉<>input參數就不再具有攻擊性了。

但是POST請求的XSS參數就沒有那么容易過濾了,為了兼顧業務,不能簡單的使用htmlSpecialChars的方式直接轉義特殊字符,因為很多時候應用程序是必須支持HTML標簽的(如:<img>、<h1>等)。RASP在防御XSS攻擊的時候應當盡可能的保證用戶的正常業務不受影響,否則可能導致用戶無法業務流程阻塞或崩潰。

為了支持一些常用的HTML標簽和HTML標簽屬性,RASP可以通過詞法解析的方式,將傳入的字符串參數值解析成HTML片段,然后分析其中的標簽和屬性是否合法即可。

image-20201115180617209

0x04、總結

我們要挖掘xss的漏洞同時,我們也需要知道它的過濾方式。比如某cms利用Filter進行過濾xss。那么我們就可以去看看filter是否存在過濾xss,如果存在的話,我們就可以快速判斷是否存在xss。不然直接白盒可能沒看到過濾點,但是就是無法彈窗。其實這也是代碼審計中,最常見的一種方式,那就是看配置文件


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM