1.CERT-J輸入驗(yàn)證和數(shù)據(jù)凈化,需要解決sql注入問(wèn)題
SQL注入漏洞的出現(xiàn)是因?yàn)樯傻腟QL查詢語(yǔ)句部分元素來(lái)自非受信源。在沒(méi)有防范的情況下,來(lái)自非受信源的數(shù)據(jù)可能惡意串改SQL查詢語(yǔ)句,導(dǎo)致了信息的泄露和數(shù)據(jù)的更改.
假設(shè)一個(gè)系統(tǒng)對(duì)用戶進(jìn)行身份驗(yàn)證,通過(guò)如下查詢語(yǔ)句訪問(wèn)SQL數(shù)據(jù)庫(kù)。如果查詢返回任何結(jié)果,則驗(yàn)證成功,否則,身份驗(yàn)證失敗。
SELECT * FROM db_user WHERE username='<USERNAME>' AND password='<PASSWORD>'
假設(shè)攻擊者可以把<用戶名>和<密碼>替換為任意字符串。在這種情況下,為用戶名輸入下列字符串而密碼輸入任意值就可以順利繞過(guò)身份驗(yàn)證機(jī)制:
validuser’or‘1’= ‘1
鑒權(quán)用戶的查詢語(yǔ)句拼接如下:
SELECT * FROM db_user WHERE username='validuser' OR '1'='1' AND password='<PASSWORD>'
如果validuser記錄在數(shù)據(jù)庫(kù)表中存在,是一個(gè)有效的用戶名,查詢語(yǔ)句停止繼續(xù)檢查其他條件,不需要驗(yàn)證密碼部分,因?yàn)橛脩裘?validuser 判定結(jié)果是True,所有or 后面的部分不需要繼續(xù)進(jìn)行判定,但需要保證OR后面的SQL表達(dá)式語(yǔ)法正確,這樣攻擊者就取得了 validuser 用戶的權(quán)限。類似的,攻擊方可以通過(guò)構(gòu)造如下密碼和任意的用戶名。
' OR '1'='1
查詢語(yǔ)句拼接后如下:
SELECT * FROM db_user WHERE username='<USERNAME>' AND password='' OR '1'='1'
'1'='1判定結(jié)果恒定是True, 這樣SQL查詢返回?cái)?shù)據(jù)庫(kù)中所有數(shù)據(jù)。這種場(chǎng)景下,攻擊者不需要一個(gè)有效的用戶名和密碼就能取得授權(quán)。
解決方法:
在SQL語(yǔ)句中使用占位符?來(lái)代替用戶輸入的值,然后再按順序?yàn)檎嘉环x值。
用PreparedStatement替換Statement,即用占位符作為實(shí)參定義sql語(yǔ)句
合格樣例:
String sqlString ="select * from db_user where username=? and password=?";
PreparedStatement stmt = connection.prepareStatement(sqlString);
stmt.setString(1,username);
stmt.setString(2,pwd);
ResultSet rs = stmt.executeQuery();
if(!rs.next())
{
throw new SecurityException("User name or password incorrect");
}
2.CERT-J面向?qū)ο?/b>,不要返回類的私有可變成員對(duì)象的引用
在一個(gè)java類中如果成員變量是可變對(duì)象就不能使用默認(rèn)get方法獲取這個(gè)可變變量的引用,而應(yīng)使用clone,否則會(huì)造成私有狀態(tài)的改變。以Date為例:
因?yàn)镈ate是可變對(duì)象,直接使用默認(rèn)的get方法,引用了可變變量進(jìn)行修改,實(shí)例中的可變變量也被修改。如果是不可變變量就不存在這樣的問(wèn)題,比如下圖的int i。

關(guān)于java中可變對(duì)象和不可變對(duì)象的介紹可以參考下面這個(gè)鏈接: