安全漏洞掃描,風險緣由分析及解決方案

1 會話標識未更新 
1.1 緣由 
在用戶進入登陸頁面,但還未登陸時,就已經產生了一個session,用戶輸入信息,登陸之後,session的id不會改變,也就是說仍是之前的那個session(事實上session也確實不會改變,由於沒有創建新session,原來的session也沒有被銷燬)。 
不少人只是讓會話invalidate沒有用(request.getSession().invalidate();),是由於invalidate方法不是真正的將session銷燬,只是將session中的內容清空,因此當invalidate之後再新建session,新建的session其實不是新的,是將以前的session從新啓用了。因而session的id不變就不奇怪了。只有cookie失效掉,才能換成新的session id 
1.2 解決 
在登陸頁面上加上一段代碼: javascript

request.getSession().invalidate() ;         //清空session 

if (request.getCookies()!=null) { 
   Cookie cookie = request.getCookies()[0];     // 獲取cookie 
   cookie.setMaxAge(0);                    // 讓cookie過時 
} 


注:會話失效後,請不要在代碼前面使用SESSION保存數據。 
2 SQL注入 
2.1 緣由 
1. 沒有正確過濾轉義字符  
在用戶的輸入沒有爲轉義字符過濾時,就會發生這種形式的注入式攻擊,它會被傳遞給一個SQL語句。這樣就會致使應用程序的終端用戶對數據庫上的語句實施操縱。比方說,下面的這行代碼就會演示這種漏洞: html

statement := "SELECT * FROM users WHERE name = '" + userName + "'; " 


將用戶名變量(即username)設置爲:a' or 't'='t,此時原始語句發生了變化. 

2. 用戶輸入錯誤的數據類型 
若是一個用戶提供的字段並不是一個強類型,或者沒有實施類型強制,就會發生這種形式的攻擊。當在一個SQL語句中使用一個數字字段時,若是程序員沒有檢查用戶輸入的合法性(是否爲數字型)就會發生這種攻擊。例如: 
statement := "SELECT * FROM data WHERE id = " + a_variable + "; " 
從這個語句能夠看出,做者但願a_variable是一個與「id」字段有關的數字。不過,若是終端用戶選擇一個字符串,就繞過了對轉義字符的須要。例如,將a_variable設置爲:1; DROP TABLE users,它會將「users」表從數據庫中刪除,SQL語句變成: java

SELECT * FROM DATA WHERE id = 1; DROP TABLE users; 


3. 數據庫服務器中的漏洞 
有時,數據庫服務器軟件中也存在着漏洞,如MYSQL服務器中mysql_real_escape_string()函數漏洞。這種漏洞容許一個攻擊者根據錯誤的統一字符編碼執行一次成功的SQL注入式攻擊。 
4. 盲目SQL注入式攻擊 
當一個Web應用程序易於遭受攻擊而其結果對攻擊者卻不見時,就會發生所謂的盲目SQL注入式攻擊。有漏洞的網頁可能並不會顯示數據,而是根據注入到合法語句中的邏輯語句的結果顯示不一樣的內容。這種攻擊至關耗時,由於必須爲每個得到的字節而精心構造一個新的語句。可是一旦漏洞的位置和目標信息的位置被確立之後,一種稱爲Absinthe的工具就可使這種攻擊自動化。 
5. 條件響應 
注意,有一種SQL注入迫使數據庫在一個普通的應用程序屏幕上計算一個邏輯語句的值: mysql

SELECT booktitle FROM booklist WHERE bookId = 'OOk14cd' AND 1=1 


這會致使一個標準的面面,而語句 
SELECT booktitle FROM booklist WHERE bookId = 'OOk14cd' AND 1=2 
在頁面易於受到SQL注入式攻擊時,它有可能給出一個不一樣的結果。如此這般的一次注入將會證實盲目的SQL注入是可能的,它會使攻擊者根據另一個表中的某字段內容設計能夠評判真僞的語句。 
6. 條件性差錯 
若是WHERE語句爲真,這種類型的盲目SQL注入會迫使數據庫評判一個引發錯誤的語句,從而致使一個SQL錯誤。程序員

例如: web

SELECT 1/0 FROM users WHERE username='Ralph'


顯然,若是用戶Ralph存在的話,被零除將致使錯誤。 
7. 時間延誤 
時間延誤是一種盲目的SQL注入,根據所注入的邏輯,它能夠致使SQL引擎執行一個長隊列或者是一個時間延誤語句。攻擊者能夠衡量頁面加載的時間,從而決定所注入的語句是否爲真。 
2.2 解決 
1. 用預編譯處理語言 
要防護SQL注入,用戶的輸入就絕對不能直接被嵌入到SQL語句中。偏偏相反,用戶的輸入必須進行過濾,或者使用參數化的語句。參數化的語句使用參數而不是將用戶輸入嵌入到語句中。在多數狀況中,SQL語句就得以修正。而後,用戶輸入就被限於一個參數。下面是一個使用Java和JDBC API例子: sql

PreparedStatement prep = conn.prepareStatement("SELECT * FROM USERS WHERE PASSWORD=?"); 

prep.setString(1, pwd); 


整體上講,有兩種方法能夠保證應用程序不易受到SQL注入的攻擊,一是使用代碼複查,二是強迫使用參數化語句的。強迫使用參數化的語句意味着嵌入用戶輸入的SQL語句在運行時將被拒絕。 
2. 軌範出錯處理 
防範SQL注入,還要避免出現一些詳細的錯誤消息,由於黑客們能夠利用這些消息。要使用一種標準的輸入確認機制來驗證全部的輸入數據的長度、類型、語句、企業規則等。 
3. 使用專業的漏洞掃描工具 
但防護SQL注入攻擊也是不夠的。攻擊者們目前正在自動搜索攻擊目標並實施攻擊。其技術甚至能夠輕易地被應用於其它的Web架構中的漏洞。企業應當投資於一些專業的漏洞掃描工具,如大名鼎鼎的Acunetix的Web漏洞掃描程序等。一個完善的漏洞掃描程序不一樣於網絡掃描程序,它專門查找網站上的SQL注入式漏洞。最新的漏洞掃描程序能夠查找最新發現的漏洞。 

3 XSS跨站腳本編制 
3.1 緣由 
它指的是惡意攻擊者往Web頁面裏插入惡意html代碼,當用戶瀏覽該頁之時,嵌入其中Web裏面的html代碼會被執行,從而達到惡意用戶的特殊目的。XSS屬於被動式的攻擊,由於其被動且很差利用,因此許多人常忽略其危害性。 
3.2 解決 
在防止這類問題時,輸入內容的轉義效果遠比內容過濾要好。 
具體實施能夠增長一個request的轉碼過濾器。代碼: 數據庫

package com.apusic.portal.sso; 
import java.io.IOException; 
import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.FilterConfig; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.http.*; 
import java.util.*; 
/** 
* Servlet Filter implementation class SqlEscapeFilter 
*/ 
public class SqlEscapeFilter implements Filter { 
    /** 
     * Default constructor. 
     */ 
    public SqlEscapeFilter() { 
        // TODO Auto-generated constructor stub 
    } 
    /** 
     * @see Filter#destroy() 
     */ 
    public void destroy() { 
        // TODO Auto-generated method stub 
    } 
    /** 
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain) 
     */ 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 
        // TODO Auto-generated method stub 
        // place your code here 
        HttpServletRequest hreq = (HttpServletRequest)request; 
        Map map = hreq.getParameterMap(); 
        Iterator itr = map.keySet().iterator(); 
        while( itr.hasNext() ) 
        { 
            String key = itr.next().toString(); 
            String [] values = hreq.getParameterValues(key); 
            if( values != null ) 
            { 
                for( int i = 0; i < values.length; i++ ) 
                { 
                    values[i] = cleanXSS(values[i]); 
                } 
            } 
            hreq.setAttribute(key, values); 
        } 
        // pass the request along the filter chain 
        chain.doFilter(request, response); 
    } 
    /** 
     * @see Filter#init(FilterConfig) 
     */ 
    public void init(FilterConfig fConfig) throws ServletException { 
        // TODO Auto-generated method stub 
    } 
    private String cleanXSS(String value) 
    { 
        value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;"); 
        value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "&#41;"); 
        value = value.replaceAll("'", "& #39;"); 
        value = value.replaceAll("eval\\((.*)\\)", ""); 
        value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\""); 
        value = value.replaceAll("script", ""); 
        return value; 
    } 
} 


配置應用中的web.xml 
Web.xml: 瀏覽器

<filter> 
     <display-name>SqlEscapeFilter</display-name> 
     <filter-name>SqlEscapeFilter</filter-name> 
     <filter-class>com.apusic.portal.sso.SqlEscapeFilter</filter-class> 
</filter> 
<filter-mapping> 
     <filter-name>SqlEscapeFilter</filter-name> 
     <url-pattern>*.jsp</url-pattern> 
</filter-mapping> 


4 XSRF跨站請求僞造 
4.1 緣由 
CSRF利用方式比較相似XSS(跨站腳本 Cross Site Scripting) ,不過不一樣的是CSRF是構造一個提交來讓其餘人訪問後,利用站點對這些人的信任來進行一些所指望的操做. 
好比:A和B在同一個有XSS漏洞的站點C,B登陸過D站點,而且有這個D站點的Cookies,這時候若是A構造一個CSRF,內容爲給 A在D站點的帳戶轉移一些虛擬幣,若是這時候在C站點瀏覽的B用戶打開了A構造的含有CSRF的頁面,這時候B的D站點用戶會由於對B用戶的信任而進行給 A轉帳的操做. 
4.2 解決 
此類攻擊的情景相對的比較複雜,具體解決能夠參考如下5點: 
第一:限制驗證cookie的到期時間。這些cookie的合法時間越短,黑客利用你的Web應用程序的機會就越小。不過,這個時間越短,用戶就越不方便。所以,你須要在安全性和方便性之間進行平衡。 
第二:執行重要業務以前,要求用戶提交額外的信息。要求用戶在進行重要業務前輸入口令,這能夠防止黑客發動CSRF攻擊(只要瀏覽器中沒有包含口令),由於這種重要信息沒法預測或輕易得到。 
第三:使用祕密的沒法預測的驗證符號。當保存在用戶瀏覽器中的cookie僅由一次會話確認時,CSRF攻擊纔會有效。因此在每次HTTP請求(固然攻擊者沒法提早知道)中都有附加的特定會話的信息,這樣就能夠挫敗CSRF攻擊。不過,若是這種應用程序存在跨站腳本漏洞,黑客就有可能訪問這種驗證符號。 
第四:使用定製的HTTP報頭。若是執行交易的全部請求都使用XMLHttpRequest並附加一個定製的HTTP報頭,同時拒絕缺乏定製報頭的任何請求,就能夠用XMLHttpRequest API來防護CSRF攻擊。因爲瀏覽器一般僅准許站點將定製的HTTP報頭髮送給相同站點,從而了防止由CSRF攻擊的源站點所發起的交易。 
第五:檢查訪問源的報頭。在瀏覽者發送HTTP請求時,它一般會包含源自訪問源報頭的URL。理論上講,你可使用這些信息來阻止源自其它任何站點(而不是來自Web應用程序自身)的請求。 

綜合公司以往平臺報出此類漏洞產出的緣由,基本上均可以經過如下簡單作法加以解決: 
在請求後面加上一次性令牌。如驗證碼,手機短信驗證,或者sessionID等。 
5 登陸錯誤消息憑證枚舉(不充分賬戶封鎖) 
5.1 緣由 
當試圖利用不正確的憑證來登陸時,當用戶輸入無效的用戶名和無效的密碼時,應用程序會分別生成不一樣的錯誤消息。經過利用該行爲攻擊者能夠經過反覆試驗,加暴力破解來發現應用程序的有效用戶名、再繼續嘗試發現相關聯的密碼。 
5.2 解決 
不論用戶名或密碼出現問題都提示一樣的錯誤,且同時加上登錄失敗次數達到規定次數,則執行賬戶鎖定功能。 
6 HTML註釋敏感信息泄露 
6.1 緣由 
頁面源代碼不正確的註釋方式。 
6.2 解決 
將html中有關密碼之類的敏感註釋去掉或者用<%-- -%>隱式註釋。 
7 應用程序錯誤 
7.1 緣由 
未執行驗證,可能輸入參數數據類型不匹配。 
7.2 解決 
實行嚴格的數據類型驗證。 
8 已解密的登陸請求 
8.1 緣由 
AppScan 的推理是「AppScan 識別了不是經過SSL 發送的密碼參數。 
8.2 解決 
第一:採用基於SSL的HTTPS傳輸協議 
第二:對敏感信息加密並繞過掃描(只要不是採用SSL安全認證即便加密了可是AppScan仍是會掃描出來) 
    緩存

 <input type="text" id="password1"  style="width:195px; height:25px; line-height:25px;border: solid 1px #89B4D6;color:#999" value="10086密碼" onfocus="javascript:clearPass();"  onkeyup="this.value=this.value.replace(/./g,'*');" onkeypress="javascript:hiddenPass()"/> 
     <input id="password" type="hidden" name="password"  class="inputs_dl" value="" /> 
將type爲password的改成text,而後用JS作一個假的密碼輸入框,AppScan會掃描type爲password的控件。 
   function hiddenPass(){ 
        var pass = document.getElementById("password1"); 
    var j_pass = document.getElementById("password"); 
      if(event.keyCode==13){ 
      check(); 
      } 
       var keycode=event.keyCode;                 
        var keychar=String.fromCharCode(keycode); 
      j_pass.value=j_pass.value+keychar; 
      j_pass.value=j_pass.value.substring(0,pass.length);    
  } 
    
   function clearPass(){ 
       $("#password1").val(""); 
       $("#password").val(""); 
  } 


而後傳輸密碼的時候加個密: 

password = base64encode(password); 


9 啓用了不安全的HTTP方法 
9.1 緣由 
除標準的GET與POST方法外,HTTP請求還使用其餘各類方法。許多這類方法主要用於完成不常見與特殊的任務。若是低權限用戶能夠訪問這些方法,他們就可以以此嚮應用程序實施有效攻擊。如下是一些值得注意的方法:
PUT,向指定的目錄上傳附加文件; 
DELETE,刪除指定的資源; 
COPY,將指定的資源複製到Destination消息頭指定的位置; 
MOVE,將指定的資源移動到Destination消息頭指定的位置; 
SEARCH,在一個目錄路徑中搜索資源。 
PROPFIND,獲取與指定資源有關的信息,如做者、大小與內容類型。 
TRACE,在響應中返回服務器收到的原始請求。可使用這種方法避開阻止跨站點腳本的防護 
9.2 解決 
如何禁止DELETE、PUT、OPTIONS、TRACE、HEAD等協議訪問應用程序應用程序呢? 
解決方法 
第一步:修改應用程序的web.xml文件的協議 

1.    <?xml version="1.0" encoding="UTF-8"?> 
2.    <web-app xmlns="http://java.sun.com/xml/ns/j2ee" 
3.    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
4.    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" 
5.    version="2.4"> 


第二步:在應用程序的web.xml中添加以下的代碼便可 

1.    <security-constraint> 
2.    <web-resource-collection> 
3.    <url-pattern>/*</url-pattern> 
4.    <http-method>PUT</http-method> 
5.    <http-method>DELETE</http-method> 
6.    <http-method>HEAD</http-method> 
7.    <http-method>OPTIONS</http-method> 
8.    <http-method>TRACE</http-method> 
9.    </web-resource-collection> 
10.    <auth-constraint> 
11.    </auth-constraint> 
12.    </security-constraint> 
13.    <login-config> 
14.    <auth-method>BASIC</auth-method> 
15.    </login-config> 


10 禁止頁面緩存 
10.1 緣由 
可以訪問到緩存的脫機數據致使泄密。 
10.2 解決 
建議在web管理後臺程序的過濾器裏增長以下代碼: 
 

 response.setHeader("Cache-Control", "no-cache"); //只是請求或響應消息不緩存 
  response.setHeader("Cache-Control", "no-store"); //在請求消息中發送將使得請求和響應消息都不使用緩存                                                                                            
response.setDateHeader("Expires", 0); //緩存距離過時的時間爲0毫秒,即緩存當即過時 
  response.setHeader("Pragma", "no-cache"); //頁面不緩存 


11 數據庫錯誤模式 
11.1 緣由 
主要是一些數據鏈接錯誤信息,經過提交特殊構造的字符,程序會暴露一些數據庫信息,也容易引發SQL注入攻擊。 
現有平臺發現的例子: 

<html><head><title>Apache Tomcat/5.5.28 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 500 - </h1><HR size="1" noshade="noshade"><p><b>type</b> Exception report</p><p><b>message</b> <u></u></p><p><b>description</b> <u>The server encountered an internal error () that prevented it from fulfilling this request.</u></p><p><b>exception</b> <pre>javax.servlet.ServletException: org.hibernate.HibernateException: java.sql.SQLException: ORA-12899: value too large for column &quot;QCSMS&quot;.&quot;T_SYS_LOGON_LOG&quot;.&quot;USER_CODE&quot; (actual: 24, maximum: 20) 
相關文章
相關標籤/搜索