軟體開發過程中安全程式碼的七大實踐

軟體開發過程中安全程式碼的七大實踐

【51CTO。com快譯】眾所周知,軟體的安全性如今已得到了前所未有的重視程度。許多企業會將安全性嵌入到應用程式的開發階段。這樣既能有利於整體安全性的遵守,又可以在軟體的不同層面上建立多個安全性檢查點。本文將透過如下圖所示的各種方面,以例項的形式,向您展示各種安全程式碼的實踐。雖然主要是以Java為例,但是它們也可以被運用到任何其他程式語言上。

軟體開發過程中安全程式碼的七大實踐

1。轉義/逃逸輸入(Escape the Input)

所謂轉義攻擊是指攻擊者將執行命令/查詢,偽裝並嵌入到普通的文字輸入中,透過欺騙應用程式的執行引擎,而讓其能夠向攻擊者提供各種資訊與控制權。可見,為避免此類攻擊的發生,我們需要對使用者的輸入進行轉義,將其解釋為文字,而非某些命令。同理,我們也需要對儲存在資料庫中的資料進行轉義。

試想,如果某使用者在其回帖的文字輸入中帶有JavaScript,那麼他就可以試圖從瀏覽器中竊取到Cookie。例如,當該回帖的內容被呈現在其他使用者的瀏覽器螢幕上時,一旦我們的程式程式碼不去轉義帖子中的包含的惡意程式碼。那麼該JavaScript程式碼將被執行,併為攻擊者提取各種所需的資訊與控制權。以下是帶有潛在風險的資料庫查詢程式碼,和相應的採取了轉義措施的Java程式碼。

示例:

包含潛在風險的Java程式碼

String query = “SELECT user_id FROM user_data WHERE user_name = ‘”               + req。getParameter(“userID”)               + “’ and user_password = ‘” + req。getParameter(“pwd”) +“’”; try {     Statement statement = connection。createStatement( … );     ResultSet results = statement。executeQuery( query ); }

安全的Java程式碼

Codec ORACLE_CODEC = new OracleCodec(); String query = “SELECT user_id FROM user_data WHERE user_name = ‘” + ESAPI。encoder()。encodeForSQL( ORACLE_CODEC, req。getParameter(“userID”)) + “’ and user_password = ‘” + ESAPI。encoder()。encodeForSQL( ORACLE_CODEC, req。getParameter(“pwd”)) +“’”;

2。避免將ID作為序列號

在某些情況下,攻擊者會設法超過現有的限制,以獲取更多的資訊。例如,某個API的使用者只被允許檢視ID號為1-100的使用者資訊。而如果該系統採用的是以ID為順序的遞增編號方式,那麼我們就可以預測到下一個使用者的序列號將是101。由此,攻擊者便可以利用這一邏輯上的漏洞,來獲取在其許可權之外的資訊。

示例:

包含潛在風險的Java程式碼

String sqlIdentifier = “select TESTING_SEQ。NEXTVAL from dual”; PreparedStatement pst = conn。prepareStatement(sqlIdentifier); synchronized( this ) {    ResultSet rs = pst。executeQuery();    if(rs。next())      long myId = rs。getLong(1);

安全的Java程式碼

// This example is for Oracle String sqlIdentifier = “select TESTING_SEQ。NEXTVAL from dual”; PreparedStatement pst = conn。prepareStatement(sqlIdentifier); synchronized( this ) {    ResultSet rs = pst。executeQuery();    if(rs。next())      long myId = rs。getLong(1) + UUID。random();

3。運用極簡主義方法

為了減少攻擊面,系統應採用最小的空間使用策略。從本質上說,這就意味著系統能夠很好地避免各種許可權的暴露。例如,根據某項業務需求,系統需要使用程式碼“HTTP 200”,來響應存在著被請求的資源。但是如果我們為REST API提供了get操作,那麼就會增加攻擊者的攻擊面。相反,該系統應該只通過HTTP協議的head方法,來提供有關現有資源的資訊,而不必提供更多的無關資訊。

示例:

包含潛在風險的Java程式碼

//Get is allowed where we need to just check user exist http://localhost:8080/User/id/1

安全的Java程式碼

http://localhost:8080/User/id/1 Head

4。最小特權原則

讓我們試想一個場景:通常,客服部門某個使用者的常規訪問許可權是可以訪問訂單資料的API。但是為了簡便起見或是某種原因,系統為其分配了超級管理員的角色。那麼一旦他所處的系統被黑或遭到了帳號破壞,攻擊者就可以利用他的超級管理員許可權,來對該系統發起一系列的攻擊操作。可見,為了減少攻擊面,我們應當僅根據實際需求,以及既定的角色,來授予目標API相應的最小訪問許可權,不應該在系統中設定所謂可以訪問所有內容的超級使用者角色。

5。儘可能使用HTTPS或雙向SSL

切勿以最原始的HTTP方式釋出您的網站或是節點。畢竟如今大多數瀏覽器都會對那些單純的HTTP站點顯示警告。而且,業界建議針對整合的端點採用雙向(2-Way)SSL方式,而對網站或站點透過HTTPS的方式,實現端到端加密。

不過,由於HTTPS只能保護了通訊通道免受攻擊,卻無法在通道的金鑰發生洩露時,保護資料。因此,業界建議使用強大的加密演算法,對各種資料記錄先進行加密,再透過可信的網路予以傳輸。

6。不要使用不安全的或弱的加密演算法

如今,隨著計算機算力的不斷迭代與提高,弱的金鑰已不再能夠防止那些暴力破解的攻擊手段。一些知名組織甚至將如下不安全的、或弱的加密演算法,列入了所謂的“黑名單”。因此您在日常進行安全程式設計時,應當儘量避免使用到它們。

SHA-1

1024位RSA或DSA

160位ECDSA(橢圓曲線)

80/112位2TDEA(雙金鑰三重DES)

與其他各種舊演算法類似,MD5從來都不是政府可以接受的演算法。

7。將動態可執行程式碼(Dynamically Executed Code)列入白名單

如果您有一些程式碼是從API或APP的使用者側傳入的,或者是在使用者輸入之後才生成的,那麼為了讓它們能夠作為整體流程的一部分被執行,您需要讓系統將這些待執行的命令列入白名單。例如,如果系統需要公佈某項服務,以列出伺服器上的對應目錄,那麼我們就需要將ls或dir之類的命令列入白名單,並轉義使用者輸入的標誌。

小結

綜上所述,我們從加密、編碼、白名單、最小特權、以及轉義不可信的使用者輸入等方面,為您羅列了日常軟體開發過程中的七種安全編碼的實踐示例。希望它們能夠協助您大幅減少軟體所面臨的各種安全威脅,並提高自身的程式碼級安全態勢。

原文標題:7 Practical Secure Coding Practices,作者:Awkash Agrawal

【51CTO譯稿,合作站點轉載請註明原文譯者和出處為51CTO。com】

TAG: user程式碼Java攻擊者使用者