安全人員須知的TOP20漏洞編碼安全規范(二)
11. 代碼注入
? 風險描述
web應用代碼中,允許接收用戶輸入一段代碼,之后在web應用服務器上執行這段代碼,并返回給用戶。由于用戶可以自定義輸入一段代碼,在服務器上執行,所以惡意用戶可以寫一個遠程控制木馬,直接獲取服務器控制權限,所有服務器上的資源都會被惡意用戶獲取和修改,甚至可以直接控制數據庫。
? 漏洞示例

以上代碼允許用戶注入任意的代碼,若其中args[0]參數設置如下,則將允許惡意用戶創建任意文件。

? 規范要求
1、寫死需要執行的命令,或通過白名單、預設命令的方式,限制可以執行的命令。
2、輸入驗證,對于進入執行代碼的參數進行檢查,檢查參數長度及包含特殊字符,當發現非法字符,拒絕請求。
3、字符轉義,對特殊字符進行轉義。
12. XML注入
? 風險描述
XML注入攻擊,和SQL注入的原理一樣,都是攻擊者輸入惡意的代碼來執行自身權限以外的功能。XML是存儲數據的一種方式,如果在修改或者查詢時,沒有做轉義,直接輸入或輸出數據,都將導致XML注入漏洞。攻擊者可以修改XML數據格式,增加新的XML節點,對數據處理流程產生影響。
? 漏洞示例
下面是一個保存注冊用戶信息為XML格式的例子

可以看到,這段代碼沒有進行任何的過濾操作。一個普通用戶注冊后,會產生這樣一條數據記錄:

攻擊者輸入自己email時,可以輸入如下代碼:

最終用戶注冊后,數據就變成了:

可以看到,多出了一條role=“admin_role”的管理員lf,達到攻擊目的。
? 規范要求
1、對用戶提交的數據在保存和展示前對特殊字符進行轉義,防止XML注入攻擊。例如:
& --> &
< --> <
> --> >
" --> "
' --> '
在XML保存和展示之前,對數據部分,單獨做轉義即可

13.密碼安全
? 風險描述
密碼安全問題主要存在明文密碼、弱密碼、密碼硬編碼等問題。此類問題均容易導致密碼的泄露。惡意攻擊者可直接讀取獲得明文賬號密碼,導致其他相關聯系統應用口令泄漏,擴大入侵范圍。
? 漏洞示例
存在安全漏洞代碼如下:

如果有一個具備中間件服務器機器訪問權限的人,看到了這個例如applicationContext.xml的文件,并且打開該文件,就會知道數據庫的用戶名和密碼是什么。
下面是對該漏洞的處理:
首先,我們需要將配置文件抽取到property中來:

將上面的第一個代碼修改為第二個代碼,第一個類是負責抓取jdbc.properties中的屬性并且填充到dataSource當中來,這樣,我們就可以將所有的注意力都集中在jdbc.properties上了。然后擴展PropertyPlaceholderConfigurer父類PropertyResourceConfigurer的解密方法convertProperty:

然后將上面完成的類替換配置文件中的PropertyPlaceholderConfigurer:

處理后的jdbc.properties里面的文件內容就變成如下所示了:

? 規范要求
1、配置文件中涉及到需要用戶驗證的密碼字段采用加密后保存,禁止明文或使用弱加密算法對密碼進行加密。
2、涉及密碼的配置,需要把密碼設置具備一定的強度,大小寫數字特殊字等最少3類型8位以上,并且不能包含與用戶名一樣的字符串。
3、程序代碼中涉及到使用密碼的地方,密碼引用不得直接寫入到程序中,需把密碼寫入相應的配置文件中。
4、對硬編碼密碼進行模糊化處理,將密碼獲取途徑分散到其他系統或文件各處,增加直接獲取密碼難度。
14.敏感數據未加密
14.1.密碼明文傳輸
? 風險描述
數據加密主要應用于數據存儲及數據傳輸過程中,敏感數據未加密進行存儲或傳輸,容易導致數據泄露,惡意攻擊者可嗅探到明文傳輸的敏感數據,從而竊取相關信息。
? 漏洞示例
某登錄頁面輸入賬號密碼登錄,利用burpsuite抓包:

發現密碼在傳輸過程當中未進行任何加密處理,直接已明文形式進行傳輸,這樣很容易被第3方監聽并獲取明文的密碼。
? 規范要求
建議采用不可逆的加密方式對密碼進行加密如MD5。禁止明文或使用弱加密算法對密碼進行加密,密碼設置應具備一定的強度,大小寫數字特殊字等最少3類型8位以上,并且不能包含與用戶名一樣的字符串。
14.2.配置文件密碼明文存儲
? 風險描述
惡意攻擊者在獲取一定讀取權限下可獲取到數據庫配置文件的賬號密碼明文信息,通過該信息,攻擊者可對數據庫進行惡意操作,甚至可能導致其他系統被控制,擴大被入侵的范圍。
? 漏洞示例
某系統配置文件中密碼以明文方式存儲:

在這里,很明顯能看到數據庫的賬號密碼是明文。
? 規范要求
禁止明文或使用弱加密算法對密碼進行加密,密碼設置應具備一定的強度,大小寫數字特殊字等最少3類型8位以上,并且不能包含與用戶名一樣的字符串。
15.弱加密算法
? 風險描述
一些低強度的密碼算法,如DES、RC2等已經可以很容易的在短時間內被人所破解,其它一些容易被誤用的“密碼算法”,如base64、escape、urlencode等,其實并不是密碼算法,只是簡單的編碼而已,不能起到密碼算法保護信息的作用。
? 漏洞示例
以“古典密碼算法”為例:
public class Caesar {
public static void encode(String PlainText, int Offset) {
String CipherText = "";
for (int i = 0; i < PlainText.length(); i++) {
if (PlainText.charAt(i) == 32)
CipherText += (char)(32);
else if (PlainText.charAt(i) >= 'a' && PlainText.charAt(i) <= 'z')
CipherText += (char)('a' + ((PlainText.charAt(i) - 'a' + Offset) % 26));
else if (PlainText.charAt(i) >= 'A' && PlainText.charAt(i) <= 'Z')
CipherText += (char)('A' + ((PlainText.charAt(i) - 'A' + Offset) % 26));
else if (PlainText.charAt(i) >= '0' && PlainText.charAt(i) <= '9')
CipherText += (char)('0' + ((PlainText.charAt(i) - '0' + Offset) % 10));
}
System.out.println("Ciphertext: " + CipherText);
}
由于在算法中同一字符每次都是映射到另一字符,因此,只要獲取到一定數量的明文和加密后的密文,就可以清楚的還原出每個字符的映射關系。并且可以通過映射關系,可以寫出解密程序,如下所示:
public static void decode(String CipherText, int Offset) {
String PlainText = "";
for (int i = 0; i < CipherText.length(); i++) {
if (CipherText.charAt(i) == 32)
PlainText += (char)(32);
else if (CipherText.charAt(i) >= 'a' && CipherText.charAt(i) <= 'z')
if((CipherText.charAt(i) - Offset) < 'a'){
PlainText += (char)('z' - ('a' - (CipherText.charAt(i) - Offset)) + 1);
}else{
PlainText += (char)('a' + ((CipherText.charAt(i) - 'a' - Offset) % 26));
}
else if (CipherText.charAt(i) >= 'A' && CipherText.charAt(i) <= 'Z')
if((CipherText.charAt(i) - Offset) < 'A'){
PlainText += (char)('Z' - ('A' - (CipherText.charAt(i) - Offset)) + 1);
}else{
PlainText += (char)('A' + ((CipherText.charAt(i) - 'A' - Offset) % 26));
}
else if (CipherText.charAt(i) >= '0' && CipherText.charAt(i) <= '9')
if((CipherText.charAt(i) - Offset) < '0'){
PlainText += (char)('9' - ('0' - (CipherText.charAt(i) - Offset)) + 1);
}else{
PlainText += (char)('0' + ((CipherText.charAt(i) - '0' - Offset) % 10));
}
}
System.out.println("PlainText: " + PlainText);
}
? 規范要求
推薦使用的安全算法
對稱算法:3DES密鑰長度128及以上,切k1,k2,k3互不相等。
對稱算法:AES密鑰長度128及以上。
非對稱算法:RSA密鑰長度1024及以上。
哈希算法:SHA2密鑰長度256及以上。
消息認證碼算法:HMAC-SHA2密鑰長度256及以上。
16.文件包含
? 風險描述
通過文件包含函數特性去包含任意文件時,由于要包含的這個文件來源過濾不嚴,從而可以去包含一個惡意文件,而攻擊者可以構造的這個惡意文件可以達到執行任意代碼、控制網站、甚至控制服務器的目的。
? 漏洞示例
以PHP本地包含文件為例,缺陷代碼如下:

程序本意是獲取action并引入action里的功能函數,這里上傳頭像image.jpg,然后包含進來發現在頁面顯示了phpinfo的信息

上傳的頭像image.jpg代碼改為一句話木馬:

上傳成功后,使用菜刀連接,成功getshell, 可以下載、修改服務器的所有文件。

? 規范要求
1、如果是PHP代碼則設置allow_url_fopen和 allow_url_include屬性為0ff。
2、涉及到的危險函數:(如include(),include_once(),require(),require_once())當使用這些函數時,要求程序員包含文件里的參數盡量不要使用變量,如果使用變量,就一定要嚴格檢查要包含的文件名,過濾危險字符,絕對不能由用戶任意指定。
17. Cookie 安全
? 風險描述
Cookie作為用戶身份的替代,其安全性有時決定了整個系統的安全性,Cookie的安全性問題主要如下所述:
(1) Cookie欺騙
Cookie記錄了用戶的帳戶ID、密碼之類的信息,通常使用MD5方法加密后在網上傳遞。雖然經過了加密處理,但是截獲Cookie的人不需要知道這些字符串的含義,只要把別人的Cookie向服務器提交,并且能夠通過驗證,就可以冒充受害人的身份登陸網站,這種行為叫做Cookie欺騙。非法用戶通過Cookie欺騙獲得相應的加密密鑰,從而訪問合法用戶的所有個性化信息,包括用戶的E-mail甚至帳戶信息,對個人信息造成嚴重危害。
(2)Cookie截獲
Cookie以純文本的形式在瀏覽器和服務器之間傳送,很容易被他人非法截獲和利用。任何可以截獲Web通信的人都可以讀取Cookie。Cookie被非法用戶截獲后,然后在其有效期內重放,則此非法用戶將享有合法用戶的權益。例如,對于在線閱讀,非法用戶可以不支付費用即可享受在線閱讀電子雜志。
? 漏洞示例
有一個后臺登錄頁面(login.asp)的源代碼

登錄頁面的兩個Cookies值分別為cmsname和cmsid

網頁會把輸入的管理員帳號和管理員ID分別賦值給cmsname和cmsid這兩個cookies值,如果密碼正確就會跳轉到后臺首頁,并添加上述的兩個cookies值。檢查用戶登錄狀態的文件,源代碼如下:

可以看到,網頁雖然有驗證用戶登錄狀態,但只僅僅驗證了Cookies的內容,只要兩個Cookies的內容都對得上,就能訪問后臺首頁,這樣,就會產生Cookies欺騙漏洞。
? 規范要求
1、設置認證COOKIE時,增加Cookie httponly這個屬性。如果在Cookie中設置了"HttpOnly"屬性,那么通過程序(JS腳本、Applet等)將無法讀取到Cookie信息
2、增加Secure這個屬性。當該屬性設置為true時,表示創建的 Cookie 會被以安全的形式向服務器傳輸,也就是只能在 HTTPS 連接中被瀏覽器傳遞到服務器端進行會話驗證,如果是 HTTP 連接則不會傳遞該cookie信息,所以不會被竊取到Cookie 的具體內容。就是只允許在加密的情況下將cookie加在數據包請求頭部,防止cookie被帶出來。secure屬性是防止信息在傳遞的過程中被監聽捕獲后信息泄漏,HttpOnly屬性的目的是防止程序獲取cookie后進行攻擊。
18.會話超時設置
? 風險描述
瀏覽器和服務器之間創建了一個Session,若沒有做會話超時設置,當客戶端長時間(休眠時間)沒有與服務器交互的情況下,服務器也沒有將此Session銷毀,若攻擊者獲取此會話,就能一直利用該會話,進行與服務器的交互。
? 漏洞示例
下面一段存在漏洞的代碼中,沒有對session做一個失效的處理。

修復后的代碼如下所示,用戶在登錄的時候,首先會讓之前的session失效,然后又獲取新的seesion。

? 規范要求
設置空閑會話強制超時時間,時間不能設置過長,建議設置為5分鐘。
設置Session超時時間方式:
方式一:
在web.xml中設置session-config如下:
2
即客戶端連續兩次與服務器交互間隔時間最長為2分鐘,2分鐘后session.getAttribute()獲取的值為空
API信息:
session.getCreationTime() 獲取session的創建時間
session.getLastAccessedTime() 獲取上次與服務器交互時間
session.getMaxInactiveInterval() 獲取session最大的不活動的間隔時間,以秒為單位120秒。
方式二:
在Tomcat的/conf/web.xml中session-config,默認值為:30分鐘
30
方式三:
在Servlet中設置
HttpSession session = request.getSession();session.setMaxInactiveInterval(60);//單位為秒
19.日志處理
? 風險描述
日志處理是由于在全局過濾的時候沒有考慮日志文件內容,當一些敏感內容通過日志文件保存下來的時候,或者說木馬病毒代碼通過日志記錄下來時,可以通過日志文件查看或執行。導致敏感信息泄露,甚至被上傳webshell,導致攻擊者可以隨時進入后臺,對文件進行操作。
? 特殊字符
Php木馬:
Asp木馬:<%execute(request("value"))%>
Aspx木馬:<%@ Page Language="Jscript"%>
還有password,passwd(密碼),phone(電話號碼),ip等。
? 漏洞示例
以某后臺數據庫為例,先執行語句setglobalgeneral_log='on',把general log設置為ON

再執行SET global general_log_file='D:/phpStudy/WWW/cmd.php',修改日志文件名。

然后執行一條sql語句。

用然后菜刀進行連接。

還有就是日志記錄敏感賬號密碼等信息:

在代碼100行處,直接將用戶名密碼明文形式記錄在日志中。
? 規范要求
對日志文件中的敏感內容進行轉義,凡是從日志文件中輸出的內容都要進行驗證。而且對于一些敏感信息,如電話號碼,密碼,ip地址等內容都要進行加密保存。
20.未配置全局過濾器
? 風險描述
在系統龐大的系統下,很多漏洞是具有通用性的,如XSS、SQL,未授權訪問、任意文件上傳下載等,如若一個地方出現,在未配置全局危險字符過濾器的情況下,通常其他地方也會出現同樣的安全漏洞。
? 漏洞示例

在該配置文件中,只配置了編碼過濾器,而沒有配置全局危險字符過濾器。
? 規范要求
1、根據業務需求配置健壯的全局危險字符過濾器,對用戶所有輸入輸出進行過濾檢查,如檢查異常則跳轉到制定的error頁面。
2、使用xml配置文件的方式記錄配置信息,配置信息包含是否開啟校驗、是否記錄日志、是否中斷請求、是否替換腳本字符等。