<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    XSS漏洞

    XSS漏洞

    攻擊者利用XSS(Cross-site scripting)漏洞攻擊可以在用戶的瀏覽器中執行JS惡意腳本,XSS攻擊可以實現用戶會話劫持釣魚攻擊惡意重定向點擊劫持掛馬XSS蠕蟲等,XSS攻擊類型分為:反射型存儲型DOM型

    1. 反射型XSS攻擊

    示例 - 存在反射型XSS的xss.jsp代碼:

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

    攻擊者通過傳入惡意的input參數值可以在用戶瀏覽器中注入一段JavaScript腳本。

    示例 - 注入XSS代碼:

    <script>alert('xss');</script>

    瀏覽器請求:http://localhost:8000/modules/servlet/xss.jsp?input=%3Cscript%3Ealert(%27xss%27)%3B%3C/script%3E

    XSS漏洞

    2. 存儲型XSS攻擊

    示例 - 存在存儲型XSS的guestbook.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>

    訪問:http://10.10.99.2:8000/modules/servlet/guestbook.jsp,并在留言內容出填入xss測試代碼,如下:

    XSS漏洞

    提交留言后頁面會刷新,并執行留言的xss代碼:

    XSS漏洞

    3. DOM XSS

    示例 - dom.jsp代碼:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    Date: <span style="color: red;"></span>
    <input type="hidden" value="<%=request.getParameter("date")%>" />
    <script>
        var date = document.getElementsByTagName("input")[0].value;
        document.getElementsByTagName("span")[0].innerHTML = date;
    </script>

    正常請求測試:http://localhost:8000/modules/servlet/dom.jsp?date=2020-11-15%2015:57:22

    XSS漏洞

    XSS攻擊測試:http://localhost:8000/modules/servlet/dom.jsp?date=%3Cimg%20src=1%20onerror=alert(/xss/)%20/%3E

    XSS漏洞

    4. XSS防御

    XSS最為常見的處理方式是轉義特殊字符,后端程序在接受任何用戶輸入的參數時都應當優先考慮是否會存在XSS攻擊。

    4.1 htmlspecialchars

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

    *示例 - htmlspecialchars 轉義: *

    字符 替換后
    & (& 符號) &amp;
    " (雙引號) &quot;
    ' (單引號) &#039;或者&apos;
    < (小于) &lt;
    > (大于) &gt;

    在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

    XSS漏洞

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

    4.3 RASP XSS攻擊防御

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

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

    XSS漏洞

    反射型的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片段,然后分析其中的標簽和屬性是否合法即可。

    XSS漏洞

    4.4 RASP XSS防御能力測試

    4.4.1 惡意的HTML標簽屬性XSS測試

    示例 - 提交帶有XSS攻擊的Payload:

    <img src='1.jpg' width='10px' height='10px' onerror='alert(/xss/);' />

    請求示例地址:http://localhost:8000/modules/servlet/guestbook.jsp,并填寫XSS攻擊代碼,如下圖:

    XSS漏洞

    RASP能夠正確識別并攔截XSS攻擊:

    XSS漏洞

    4.4.2 XSS富文本檢測測試

    RASP如果要實現精確的XSS檢測能力就必須能夠正確的識別出用戶傳入的數據到底是否合法,經過HTML詞法分析后RASP能夠正確認識用戶傳入的參數值是否是包含了惡意的HTML標簽或者屬性。

    示例 - 用戶在留言板中帶圖片回復:

    XSS漏洞

    示例 - 用戶在留言板中回復被注釋的HTML片段:

    XSS漏洞

    XSS漏洞

    經測試,RASP對XSS攻擊防御能力正常,能夠識別合法的HTML和javascript代碼(DOM類XSS占不支持)。

    本文章首發在 網安wangan.com 網站上。

    上一篇 下一篇
    討論數量: 0
    只看當前版本


    暫無話題~
    亚洲 欧美 自拍 唯美 另类