安全人員須知的TOP20漏洞編碼安全規范(一)
1.SQL注入
? 風險描述
SQL注入主要發生在應用程序數據庫層面上。程序員在設計程序的時候,沒有對用戶的輸入進行校驗,含有特殊字符語句會被數據庫誤認為是正常的SQL指令而運行,從而使數據庫受到攻擊,可能導致數據被竊取、更改、刪除,以及進一步導致網站被嵌入惡意代碼、被植入后門程序等危害。
? 特殊字符
對SQL注入而言,特殊字符包括但不限于 (注意大小寫繞過以及雙寫繞過):
“--,#,//(注釋符)”、“ and”、“ or”、“ select”、“ update”、“ delete”、“ drop”、“ declare”、“ insert”、“ xp_shell”以及(,)括號、||,+, (空格)連接符、' 單引號、|(豎線符號)、& (& 符號)、;(分號)、$(美元符號)、%(百分比符號)、@(at 符號)、'(單引號)、"(引號)、\'(反斜杠轉義單引號)、\"(反斜杠轉義引號)、<>(尖括號)、CR(回車符,ASCII 0x0d)、LF(換行,ASCII 0x0a)、,(逗號)、\(反斜杠)等。
? 漏洞示例

其中request.getParameter("searchWord")中的參數“searchWord”是從前端獲取到的,也就是jsp頁面中input標簽中id為“searchWord”的值,如下:

后臺SQL語句是以拼接的形式執行,代碼所示:

SQL語句一旦以拼接的方式執行,那么拼接的“word” 不僅僅是作為一個參數執行,還可以表示一個SQL語句,比如:word的值為1,那么SQL語句變成:Select * from test where id = 1;如果word的值為1’ and ‘a’=’a,而系統未對傳入后臺的參數做任何特殊字符過濾,或者字符過濾不全,那么SQL語句變成:Select * from test where id = 1’ and ‘a’=’a。兩條查詢語句都能成功執行。如果這時候將and后面的字句換成union或者order by語句就能將數據庫名、表名以及表中的數據查詢出來。
? 規范要求
1、添加全局過濾器,過濾特殊字符。方式如下:
Web.xml
SQLFilter
< filter -class>*.SQLFilte
SQLFilter
/* 攔截所有請求
在SQLFilter.java類中:
paramValue= paramValue.replaceAll(“>”, “”) paramValue= paramValue.replaceAll(“%”,“”)
2、SQL語句使用參數化查詢方式,代碼如下:
String sql=“select * from test where id=?”;
db=new DBHelper(sql);
try{
db.stmt.setString(1,word);
ret=db.stmt.executeQuery();
while(ret.next()){……}}
2.跨站腳本攻擊(XSS)
? 風險描述
跨站攻擊是因為網站程序對用戶輸入過濾不足,將用戶輸入的惡意腳本代碼正常執行或者提交。攻擊者可利用XSS漏洞獲取用戶cookie值、傳播蠕蟲、篡改頁面或進行釣魚等攻擊。
? 特殊字符
對XSS而言,特殊字符包括但不限于 (注意大小寫繞過以及雙寫繞過):
|(豎線符號)、& (& 符號)、 ;(分號)、$(美元符號)、%(百分比符號)、@(at 符號)、'(單引號)、"(引號)、\'(反斜杠轉義單引號)、\"(反斜杠轉義引號)、<>(尖括號)、()(括號)、+(加號)、CR(回車符,ASCII 0x0d)、LF(換行,ASCII 0x0a)、,(逗號)、\(反斜杠)、eval方法以及關鍵字document、cookie、javascript、script、onerror等。
? 漏洞示例

搜索框種的值即為可控參數,在URL中表現形式為:
http://.../searchword?word=
相關代碼如下:

此處參數在前端為EL表達式獲取,并且為添加任何過濾,最后直接顯示在頁面。當輸入框輸入的參數為:alert(1) 時,就會直接被瀏覽器當作腳本執行并彈框:


其中URL的表現形式:
http://.../searchword?word=%3Cscript%3Ealert%281%29%3C%2FscriFs%3E
上面的示例是直接與頁面交互,通過在URL中構造參數來實現XSS攻擊。還有一種是將參數進行傳遞并最終存儲到數據庫當中,因為參數在傳遞過程中未經過任何有效過濾(或者存在過濾不全,會被繞過),作為可信資源存入到數據庫中并最終被執行。代碼如下:


在前端頁面會顯示用戶存儲的數據,并且未做任何輸出過濾(或者過濾不全),頁面和代碼如下:

前端的頁面結構如下:

如果在編輯用戶信息的時候輸入:alert(1)

在數據庫中的存儲形式為:

在查詢的時候就會將相應的數據顯示在頁面,并執行腳本:


? 規范要求
1、添加全局過濾器,過濾特殊字符。方式如下:
Web.xml
XSSFilter
< filter -class>*.XSSFilte
XSSFilter
/* 攔截所有請求
在XSSFilter.java類中:
paramValue= paramValue.replaceAll(“>”, “”) paramValue= paramValue.replaceAll(“%”,“”)
2、輸出編碼,編碼就是讓解析者知道數據不是用來執行的代碼,從而可以避免受攻擊。主要包括3種編碼:URL編碼、HTML編碼、JavaScript編碼。對于不可信來源的數據需要執行輸出編碼,確保字符被視為數據,根據場景分別使用以上1種編碼或多種編碼組合。
3.任意文件下載
? 風險描述
網站在處理用戶下載文件的請求時,允許用戶提交任意文件路徑,并把服務器上對應的文件直接發送給用戶,這將造成任意文件下載威脅。如果服務器根據用戶提交的目錄地址,就把目錄下的文件列表發給用戶,會造成目錄遍歷安全威脅。惡意用戶會變換目錄或文件地址,下載服務器上的敏感文件、數據庫鏈接配置文件、網站源代碼等。
? 系統敏感文件
Linux操作系統:/root/.ssh/authorized_keys、 /root/.ssh/id_rsa
/root/.ssh/id_ras.keystore、 /root/.ssh/known_hosts、 /etc/httpd/conf/httpd.conf
/root/.bash_history、/root/.mysql_history、/proc/self/fd/fd[0-9]*(文件標識符)
/proc/mounts、/porc/config.gz、/etc/passwd、/etc/shadow、/etc/my.cnf
Windows操作系統:C:\Program Files\mysql\my.ini //Mysql配置、
C:\Program Files\mysql\data\mysql\user.MYD //Mysql root
C:\Windows\php.ini //php配置信息
C:\Windows\my.ini //Mysql配置信息、C:\boot.ini //查看系統版本
C:\Windows\System32\inetsrv\MetaBase.xml //IIS配置文件
C:\Windows\repair\sam //存儲系統初次安裝的密碼 ...
? 漏洞示例
存在下載功能的頁面

Url表現形式如下:
http://.../downloadFile.action?jpgPath=/download/&jpgName=test.jpg
在代碼中的表現形式如下,文件路徑和文件名都是從前端獲取,然后執行下載操作:
具體下載功能代碼如下:

當文件正常下載時,通過brupsuite截圖如下:

在此處直接替換文件名為“WEB-INF/web.xml”,嘗試下載系統配置文件:

可以看到下載文件失敗,返回不一樣的結果。但是可以通過添加“../”進行目錄跳轉:

可以看出上面返回了web.xml內容,表示已經下載成功。
? 規范要求
1、文件下載時進行過濾,過濾掉 “./”、“../”、“%”等,代碼如下:

當輸入“../”時:

2、對下載的文件路徑進行嚴格控制,只允許下載某部分目錄下的文件:



3、對下載文件后綴名做嚴格控制:



4、下載文件之前做權限判斷,判斷用戶是否有下載該文件的權限。可建立文件白名單,不屬于白名單內,不允許下載。
5、使用ID替換文件夾和文件名,使得整個輸入由路徑名變為一個表示ID的字符串,這種方法很容易驗證它的有效性。
4.任意文件上傳
? 風險描述
應用程序在處理用戶上傳的文件時,沒有判斷文件是否在允許的范圍內,就把文件保存在服務器上,導致惡意用戶可以上傳任意文件,甚至上傳腳本木馬到服務器上,直接控制服務器。文件上傳漏洞的利用是有限制條件的,首先要能夠成功上傳木馬文件,其次上傳的木馬文件能夠被執行,最后就是上傳文件的路徑必須可知。
? 漏洞示例

服務器端代碼:

可以看到,服務器對上傳文件的類型、內容沒有做任何的檢查、過濾,存在明顯的文件上傳漏洞。上傳文件hack.php(一句話木馬):

上傳成功,并且返回了上傳路徑:

通過菜刀連接:

連接成功后,就可以在服務器上執行任意命令,獲取webshell權限。可以下載、修改服務器的所有文件。

? 規范要求
1、對上傳文件的類型進行檢測,設置白名單進行過濾。(建議禁止上傳jsp、jspx、php、asp、aspx等格式的文件)。
2、對上傳文件的內容及大小進行檢測,代碼如下:
在這里,代碼對上傳文件的類型、大小做了限制。
5.越權操作
? 風險描述
如果一個Web應用程序不正確檢查用戶是否被授權訪問的特定的資源,就有可能導致產生越權漏洞。例如帳號A在登錄的狀態下,遍歷訪問請求中的ID就可以查看其它人的相關信息。甚至普通權限的用戶可以通過越權獲取到管理員的權限,從而可以訪問本部屬于自己權限的數據或頁面。
? 漏洞示例

在test001賬號訪問的頁面URL中直接將參數art=4改成art=6,則test001賬號就可以訪問原本只能被test002號訪問的數據,如下所示:

相關代碼如下:

在上面的代碼中,沒有判斷用戶的Session值,導致通過修改art的值就可以遍歷訪問其他的信息。
? 規范要求
1、驗證一切來自客戶端的參數,特別是和權限相關的參數,如用戶ID或角色ID等。
2、在進行增、刪、改、查等操作時,需將sessionID和認證的token綁定,存放在服務器的會話里,不要相信任何客戶端發來的認證和授權信息,包括消息頭、Cookie、隱藏的表單或者URL參數。下面時修復后的代碼:
在修復后的代碼中,首先會判斷用戶的Session,只有在Session為True的情況下才能夠查看返回的信息,因此當用戶遍歷art的值來嘗試訪問其他人的信息時,會提示無權訪問。
6.緩存區溢出
? 風險描述
緩存區溢出主要出現在C/C++當中,是一種非常普遍、非常危險的漏洞。利用緩沖區溢出攻擊,可以導致程序運行失敗、系統宕機、重新啟動等后果。更為嚴重的是,可以利用它執行非授權指令,甚至可以取得系統特權,進而進行各種非法操作。
? 漏洞示例

在代碼100行處,數組在復制過程中,后面一個數組的長度是前一個數組的兩倍,當需要復制的數據超過第一個數組的數組長度時,對數組完成復制后,由于數組沒有結束標識,讀取數組數據時存在內存溢出的可能性。

在代碼3278、3283行處,使用strncpy復制時只是復制了一個字節,而數組沒有經過初始化,且最后也沒有對數組做結束標識處理,在直接讀取數組時,可能會造成內存溢出。
? 規范要求
1、對傳遞的數據進行類型/大小/長度的檢驗。
2、過濾風險數據。
3、初始化參數。
7.URL跳轉
? 風險描述
應用程序接收到用戶提交的URL參數后,沒有對參數做“可信任URL”的驗證,就向用戶瀏覽器返回跳轉到該URL的指令。惡意攻擊者可以發送給用戶一個鏈接,但是用戶打開后,卻來到釣魚網站頁面,將會導致用戶被釣魚攻擊,賬號被盜,或賬號相關財產被盜。
? 漏洞示例
跳轉代碼:response.sendRedirect(request.getParameter("url"));
某應用程序有一個名為“redirect.jsp”的頁面,該頁面的參數為“url”,攻擊者精心構造一個鏈接將用戶重定向到一個惡意網站,執行釣魚攻擊并安裝惡意程序。
http://www.example.com/redirect.jsp?url=evil.com
? 規范要求
1、輸入驗證,對跳轉的URL進行驗證,對于不合法的跳轉URL拒絕跳轉訪問。可通過白名單進行驗證。
2、如果在本網站內跳轉,則使用相對路徑,而不要使用絕對路徑,如在URL的參數中使用了絕對路徑,建議在代碼里剝離URL中域名部分,然后再和網站的域名重新結合成絕對路徑,再跳轉。
3、如果請求允許跳轉的對象只是限制在有限的范圍內,可創建一個匹配的規則,通過數字類型的ID來代替跳轉到具體的頁面。
4、僅傳遞一個回調url作為參數是不安全的,增加一個參數簽名,保證回調url不被修改,在控制頁面轉向的地方校驗傳入的URL是否為公司域名(或者其他可信域名)
如以下是一段校驗是否公司域名的JS函數
function VaildURL(sUrl)
{
return (/^(https?:\/\/)?[\w\-.]+\.(qq|paipai|soso|taotao)\.com($|\/|\\)/i).test(sUrl)||(/^[\w][\w\/\.\-_%]+$/i).test(sUrl)||(/^[\/\\][^\/\\]/i).test(sUrl) ? true : false;
}
8.跨站請求偽造(CSRF)
? 風險描述
CSRF 是一種攻擊者迫使被攻擊者網頁瀏覽器發送HTTP 請求到攻擊者所選擇的網站的漏洞。CSRF依靠用戶標識,并利用網站對用戶標識的信任欺騙用戶瀏覽器發送HTTP請求給目標站點。通過跨站請求偽造漏洞,攻擊者能讓受害用戶修改可以修改的任何數據,或者是執行允許使用的任何功能。
? 漏洞示例
缺陷代碼


攻擊者執行完惡意代碼后用戶的賬戶和密碼會在不知情的情況下被更改
? 規范要求
1、執行標準的會話管理,通過在每個會話中使用強隨機令牌或參數來管理賬戶。
2、對于重要的數據提交,增加帶隨機令牌的隱藏字段,在提交給服務器后對令牌進行驗證,確保提交的請求是合法的。
3、對于重要的數據提交,也可進行二次重新認證,以確保請求是合法的。
4、對于重要的數據提交,也可增加圖形驗證碼進行驗證,以確保請求是合法的。
示例:

9. 敏感信息泄露及錯誤處理
? 風險描述
應用系統常常產生錯誤信息并顯示給使用者,導致信息泄露問題,很多時候,這些錯誤信息是非常有用的攻擊信息,因為它們暴露了應用系統實施細則或有用的開發信息,對攻擊系統有很大幫助。
? 規范要求
1、通過web.xml配置文件實現,產生異常或者錯誤時跳轉到統一的錯誤處理頁面,避免泄漏過多敏感信息。例如:
java.lang.Throwable /error.jsp
10. 遠程系統命令執行
? 風險描述
系統命令執行攻擊,是指代碼中有一段執行系統命令的代碼,但是系統命令需要接收用戶輸入,惡意攻擊者可以通過這個功能直接控制服務器。
? 漏洞示例

以上代碼調用系統的shell執行含有用戶輸入參數的命令,攻擊者可以將多個命令合并在一起。比如,輸入 “. & echo hello” 首先由dir命令羅列出當前目錄的內容,再用echo打印出友好的信息。
? 規范要求
1、所有需要執行的系統命令,必須是開發人員定義好的,不允許接收用戶傳來的參數,加入到系統命令中去。
2、字符轉義,對特殊字符進行轉義。
3、輸入驗證,對于進入命令執行的參數進行檢查,檢查參數長度及包含特殊字符,重點檢查各種命令分隔符(如;、&&、&、||、|等),當發現非法字符,拒絕請求。建議過濾出以下所有字符:
[1] |(豎線符號)
[2] & (& 符號)
[3];(分號)
[4] $(美元符號)
[5] %(百分比符號)
[6] @(at 符號)
[7] '(單引號)
[8] "(引號)
[9] \'(反斜杠轉義單引號)
[10] \"(反斜杠轉義引號)
[11] <>(尖括號)
[12] ()(括號)
[13] +(加號)
[14] CR(回車符,ASCII 0x0d)
[15] LF(換行,ASCII 0x0a)
[16] ,(逗號)
[17] \(反斜杠)