安全檢測Java Web應用網站漏洞(下)

  • 有了樣板,我們來分析這套程序中可能出現的各種web漏洞。 

        1、SQL注入漏洞 

            從SQL注入漏洞說起吧,在web漏洞裏,SQL注入是最容易被利用而又最具有危害性的。怎麼快速的找到呢?先分析流程,就拿用戶查看文章這個流程爲例:用戶訪問一個action,告訴它用戶想看ID爲7的文章,這個action就會繼續完成前面所說的流程。 

            如果是ASP程序,這就是最容易產生問題的時候,ASP是弱類型,接到參數後不需要轉換類型,就和SQL語句連加起來。但是JSP就不一樣,JSP是強類型的語言,接受有害的參數後:對於GET請求(直接在地址欄訪問頁面),如果這裏要的是int型,即使不懂安全的程序員,也會把它(文章的ID)立刻轉換成int,因爲這裏轉換後在後面的處理中會更容易操作,而這時程序就出錯了;對於POST請求,如果這裏要的是int型,程序會在把它封裝成Form對象時,因爲自動要進行類型轉化,同樣發生錯誤,這兩種錯誤發生後,根本不會訪問後面的流程就跳出了,或許這就是JSP天生的安全性。所以,通常提交的變量是int時,不會發生問題,問題會出現在string參數這裏,如果要查看某用戶的信息,程序可能會讓你提交如下參數:showuser.do?    username=kxlzx。問題來了,因爲這裏是string類型,所以不懂安全的程序員頂多會判斷一下是不是空,就連加成爲SQL語句。有漏洞的程序大概會寫成這個樣子: 

        ACTION的代碼:
showuser.do 
    String username = null; 
    username = request.getParameter("username"); 
    Service service = new Service(); 
    service.findByUsername(username); 
    得到參數後調用service,service層直接交給了Dao層,dao的代碼: 
    public Object findByUsername(String username) 
     { 
    JdbcTemplate jt=new JdbcTemplate(); 
    String sql = "select * from Users where username=’"+username"’"; 
    List list = jt.query(sql); 
    ................... 
     }

       dao調用了DB層的JdbcTemplate,把SQL語句拼好後,傳給了JdbcTemplate去執行。不用再看這裏的JdbcTemplate,就可以知道里面的代碼使用了Statement的executequery()方法執行,導致了SQL注入。 

       分析了這麼半天,有讀者會問:“難道我要費這麼大的力氣才能找到漏洞麼?”。的確,通常在ASP程序裏找注入時的思路就是這樣子,但是我們現在是在使用了開發模式分層架構的JSP程序裏,應該按照分層架構的思維去找漏洞。在回答這個問題之前,我們還得繞個彎子,看看怎麼在這裏預防SQL注入(java始終都是這麼優美,它不會直接告訴你答案,而是一層一層的讓你撥開雲霧)。 

        剛纔分析流程,是從正向分析的,從用戶輸入到產生漏洞,我們在防禦的時候,不妨倒過來看看,從DB層入手。JdbcTemplate調用執行SQL語句,可以有兩個類供我們選擇,一個是Statement,另一個就是預處理的Statement,兩者有着效率上和安全上的顯著差別。在效率上,只要數據庫支持預處理技術(sqlserver,mysql,oracle等都支持,只有少數access等不支持),就會在大量執行SQL語句時增加速度;在安全上,使用預處理,會把接受的參數也經過預處理,從而不會作爲SQL語句的一部分執行,而是僅僅作爲SQL語句中的參數部分內容被執行。一旦DB層使用了預處理,DAO層的SQL語句也會發生變化,成爲這個樣子: 
    public Object findByUsername(String username) 
     { 
    JdbcTemplate jt=new JdbcTemplate(); 
    String sql = "select * from Users where username=?"; 
    List list = jt.query(sql,new Object[1]); 
    ................... 
    }

        這樣,SQL注入就和我們的程序幾乎無關了,注意我說的是幾乎,而不是全部。知道了怎麼防禦,於是一切在這裏變的簡單極了,我們應該直接去DB層找到JdbcTemplate,看看代碼,一旦使用了Statement,很好,這個系統十有八九有漏洞,下面要做的是使用Editplus搜索“request.getParameter”。沒有使用預處理的系統,可能會在action層進行防禦,對參數過濾,但總有防禦不到的時候,因爲戰線拉的太長了,每一個action裏都可能接受參數並存在漏洞。 

        還有一種情況,系統一部分使用了預處理,一部分沒有,這樣的情況可能是因爲項目趕的比較倉促,人員沒有經過正規培訓,最後艱難的整合到了一起。這種情況也好辦,直接在DAO層搜索("’)或(’"),這些符號用於和字符串變量連加,拼SQL語句,肯定是這些語句之後的代碼使用了Statement。然後再往上層找,看看哪個action調用了這個有問題的dao類,也可能發生SQL注入。 
       即使系統使用了預處理,別忘了,程序給客戶使用後,客戶有權利去擴展的。程序拿到客戶那裏,客戶有了新的需求,而這個需求又不大,很可能不願意花錢重新僱人來實現擴展功能,在這個時候也可能出現問題,客戶使用自己的程序員擴展AJAX功能,這個程序員因爲怕出問題,不敢動源程序,就在web.xml里加了一個servlet,這個servlet直接去調用conn。可怕的事情發生了。所以,我們的搜索漏洞規則中又加上了一條,在非dao層的文件中,搜索“select,update,delete”等字符串。 

    2、暴露程序信息漏洞 

        這個漏洞是怎麼來的呢?我們需要從異常說起。有經驗的入侵者,可以從JSP程序的異常中獲取很多信息,比如程序的部分架構、程序的物理路徑、SQL注入爆出來的信息等,這個漏洞很容易防禦,卻很難快速定位漏洞文件。出現這樣漏洞的時候,通常是我們在寫代碼的時候,少了一些可能性的考慮而導致的。這樣的問題都是經驗造成的,而尋找漏洞也要通過經驗加運氣(要有仙緣。。。),我個人技術有限,就不多說了。防禦的方法就是在程序中加上“Exception層”,自定義異常,把系統產生的異常統統包裝起來,不要放過任何一個可能產生異常的地方。像騰訊的異常就包裝的很好“對不起,今天的註冊人數已經達到十萬,請您明天再來。。。”,廢話,日註冊量都十萬,還讓不讓人活啦,鐵定是程序發生了異常,不敢讓各位大大們看到真實的面孔。 

   3、AJAX暴露出來的漏洞 

        前面講SQL注入的時候說過的例子就是一個典型的情況,因爲大多數網站不是在開發時就擁有Ajax技術的,都是後來看大家都用了,趕時髦加上。但是在加上的同時沒有意識到,在web上增加一個文件,就等於擴展了一點攻擊面。 

    4、業務邏輯漏洞 

        這個詞看起來挺抽象的,他和“暴露程序信息漏洞”有很多共同點,看名字就知道,應該是存在於業務邏輯層(service層)的漏洞。這樣的漏洞都和程序的運行邏輯有關,舉一個例子。 

        小王給小李轉賬,在業務層的流程應該是這樣子的,首先在小王的賬上扣除一百元,之後在小李的賬上增加一百元。 
        這個過程需要執行至少兩條SQL語句,也就是調用至少兩次dao方法,而一旦調用中間出現問題(產生異常),就應該立刻回滾而不是跳轉到異常處理機制。大家都應該想到使用“事務處理”,是的,在一個大型複雜的項目裏,一定要進行事務處理,一旦事務處理控制的不好,麻煩就大了。這就是它和“暴露程序信息漏洞”的共同點,發現的時候,要憑經驗和運氣。 

    5、XSS漏洞 

        這個漏洞也影響深遠,想要發現這樣的漏洞,除了在頁面上進行測試外,還要從流程上入手。用戶輸入有害信息後,信息保存到數據庫,從數據庫中讀出來丟給用戶時產生漏洞。也就是說我們有兩個過程可以攔截,就是保存到數據庫時,和從數據庫讀出來後交給用戶時。最快的方法是直接打開數據庫查看數據,如果數據沒有經過編碼直接放進了數據庫,那麼可能性就有了一半。剩下的一半更簡單,在action層搜索轉碼常用的字符,如果沒有,就很容易發現漏洞。即使有,也不用着急,在action層裏慢慢找,很可能還有漏網之魚。 

    6、頁面層的邏輯漏洞 

        此類漏洞涵蓋面很大,包括“暴露不該暴露的數據”、“權限控制的不精確”、“方便客戶的同時存在安全隱患”等等。這類漏洞就只能靠着自己的經驗,使用系統的每一個細小功能來尋找。我給出幾個例子供大家參考。 

       例1,“找回密碼”功能,這個功能是爲了方便客戶的,可以通過一些客戶之前確認的信息而獲得客戶的身份驗證。有些程序的邏輯是這樣的,“請輸入VIP用戶名”--(判斷VIP用戶不存在)--“請輸入提示問題答案”--顯示用戶密碼或提供修改密碼的鏈接。第一步,入侵者可以獲得VIP用戶名是否存在,進而獲取密碼,第二步,一旦用戶留的問題比較弱智,就等於告訴別人自己的密碼。 

        例2,用戶列表功能,試想,普通用戶閒着沒事看用戶列表做什麼?這個功分明是爲了方便入侵者蒐集用戶名的。 

        例3,不要把防護交給JS,誰告訴我們使用JS可以防止用戶做某些操作的?這簡直是陷阱,JS只能防護普通用戶而已,永遠不要相信客戶端提交上來的數據,我見到有人的系統在限制上傳文件時,僅僅在JS裏做了防護,這不是自欺欺人麼? 

        Web漏洞層出不窮,即使不存在以上漏洞,也別高興的太早,我們現在使用的技術,只能防範目前上了檯面的攻擊,或許今天你的系統固若金湯,明天就出現了新的攻擊方法。就像04年突然出現的“上傳文件”漏洞,在寫代碼的時候,誰能想到這裏還會出現問題?本文中,我僅僅是根據自己的一些經驗,以及一時靈感獲得的思路,給大家拋磚引玉來的,文中一定有沒有寫到的地方,而從分層架構的角度去看漏洞的思想纔剛剛開始,希望每一位讀者在自己的心裏都有一翻序曲。期待大家文明的踢場子和鼓勵。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章