XSS研究4-來自外部的XSS***的防範


引入:javascript

這篇文章咱們來專門探討如何防範來自外部的XSS***。html


實踐:java

其實從http://supercharles888.blog.51cto.com/609344/1339921 文章中能夠看出,主要的***手段無讓***者機器上運行一段JS,這段js中包含一段對於document.cookie的處理,若是這個能拿到正確的值,那麼就能夠用獲取的信息發送到***者的某個指定機器上,從而盜用。因此從這個思路上想解決方法就很容易了,就是經過一段機制,讓植入到***者機器上的惡意的js代碼中拿document.cookie拿不到內容。web


能實現這一點麼,簡單查閱了下文檔,發現了原來有Cookie 有個HttpOnly這麼個標記,若是把它設置爲true的時候,那麼這個cookie只能經過http協議訪問,而沒法經過javascript 腳本,或者applet進行訪問。咱們在想,既然信息的盜用都是一段js腳本去拿到document.cookie的內容,那麼若是設置Cookie爲HttpOnly後,是否解決問題了呢?瀏覽器


爲此,咱們作個實驗,咱們讓Cookie用java代碼生成而不是和上文鏈接中的用某段js生成(這樣作的目的是萬一HttpOnly真起做用了,那麼咱們設置Cookie的這段js代碼就生效了)服務器

代碼很簡單,咱們作了一個Servlet,而後讓用戶訪問這個Servlet的時候,它會建立一個Cookie(如今hard-coded):爲了比較,咱們先作一個不設置HttpOnly的例子:cookie

代碼以下:session

package com.charles.study;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * 這個Servlet用於產生一個Cookie
 * @author charles.wang
 *
 */
public class CookieServlet extends HttpServlet{
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        buildResponseWithCookie(response);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
    /**
     * hard-code一個Cookie信息,而且寫到客戶端
     * @param response
     * @throws IOException
     */
    private void buildResponseWithCookie(HttpServletResponse response) throws IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
        Cookie cookie = new Cookie("charles","1234567890");
        cookie.setMaxAge(24*3600);
        cookie.setPath("/");
        response.addCookie(cookie);
        out.println("Already Written Cookie to Client");
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}


而後在 web.xml中定義好 servlet-mapping(略去)app

而後當咱們訪問頁面時候,打開Firebug,切換到Cookie標籤:ide

123446332.png

能夠看到,默認狀況下,這個CookieHttpOnly屬性是沒有設置值的(下方表格第七欄)

如今,咱們切換到Console標籤頁,而後輸入document.cookie:

123640124.png

紅色部分顯示,這時候咱們是拿獲得cookie的值的,也就是說js徹底能夠獲取cookie的內容。


如今咱們把咱們的代碼變下,在建立cookie的地方,加一行 cookie.setHttpOnly(true);


/**
     * hard-code一個Cookie信息,而且寫到客戶端
     * @param response
     * @throws IOException
     */
    private void buildResponseWithCookie(HttpServletResponse response) throws IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
        Cookie cookie = new Cookie("charles","1234567890");
        cookie.setMaxAge(24*3600);
        cookie.setPath("/");
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
        //如下這行專門用於解決來自外部的XSS***問題
        cookie.setHttpOnly(true);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
        response.addCookie(cookie);
        out.println("Already Written Cookie to Client");
    }

其餘不變,而後咱們重複上面實驗,咱們打開這個servlet頁面,打開Firebug,切換到Cookie標籤

124119518.png

這時候能夠發現第7列HttpOnly屬性被設置了。

如今,咱們切換到Console標籤頁,而後輸入document.cookie:

124412888.png

此次咱們發現,這個Cookie再也不顯示「charles=1234567890"了,取而代之的是,它只顯示""空,這就代表,咱們的HttpOnly屬性起做用了。咱們的惡意js沒法經過document.cookie拿到任何有價值信息。


結論的延伸:

因而,從上面2個實驗對比,咱們發現了HttpOnly屬性是解決來自外部XSS***的關鍵屬性,咱們不知足上面實驗,咱們還能夠進行擴展,由於上述實驗中,咱們是讓response直接添加了一個cookie, 然現實中的例子多數是經過會話HttpSession,而後它的scope上添加了一些機密信息,而且維護在服務器端的。而後客戶端也會有一個id去引用這個對應的session,那麼這個Session是否可使用HttpOnly屬性呢?答案是確定的。

若是你使用的是servlet 3.0+的版本,那麼在對應的web.xml中,能夠自然的經過下面一段代碼來配置HttpOnly屬性:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <display-name>XSSDemo</display-name>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
    <session-config>
        <cookie-config>
            <http-only>true</http-only>
        </cookie-config>
    </session-config>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
..

這裏,注意咱們的xsd是servlet 3.0的xsd,因此咱們能夠在<session-config>中使用 <cookie-config>子元素,而後用<http-only>true來啓用這個HttpOnly特徵。

咱們來作個實驗證實,咱們修改下CookieServlet,從而當咱們訪問這個Servlet時候他會建立一個Session:

public class CookieServlet extends HttpServlet{
                                                                                                                                                                                                                                                                                                                                                                                                        
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        HttpSession session= request.getSession();
        session.setAttribute("charles_session","9876543210");
                                                                                                                                                                                                                                                                                                                                                                                                            
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.println("Session Created");
                                                                                                                                                                                                                                                                                                                                                                                                             
    }
                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                      
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

而後咱們訪問頁面:

125850183.png

顯然,從第七列看出來,這個剛建立的Session Cookie ,它的HttpOnly被正確的設置了。


總結:

咱們作了幾個實驗,大致上解決了外部XSS***的問題,主要是經過設置HttpOnly屬性,這個屬性可防止js或者applet去操做cookie,並且它不只適用於通常的Cookie,也適用於Session Cookie. 其實它的思想很簡單,既然外部XSS***是你把情報帶出去,那麼我海關就嚴格一條,任何紙條只要經過海關就」燒「掉(我只是打個比方) ,這樣你無論如何,你都不能經過惡意代碼從這個灰燼的紙條中拿到信息了。


實踐上看,對於通常的Cookie,只要在它建立的時候,設置cookie.setHttpOnly(true).

對於Session Cookie,若是你的app容器支持servlet 3.0規範,那麼只要配置 <cookie-config>讓其啓用<http-only>就能夠了,若是你的app容器比較老,那麼你必須經過覆寫SET-COOKIE的 Http響應頭來顯式添加HttpOnly標誌。

//經過覆寫SET-COOKIE的 Http響應頭來顯式的添加HttpOnly
 String sessionid = request.getSession().getId();
 response.setHeader("SET-COOKIE", "JSESSIONID=" + sessionid + "; HttpOnly");


其實,如今主流的瀏覽器都能很好的支持HttpOnly了,***們要***難度又加大了。

相關文章
相關標籤/搜索