中安威士:詳解SpringMVC框架中常見漏洞的防禦
下面我們就用利用SpringMVC自帶的資料庫操作類jdbcTemplate舉例。比如下面Dao中有如下的兩個函式。
函式save使用的是繫結變數的形式很好的防止了sql注入,而queryForInt_函式接收id引數直接對sql語句進行了拼接,測試時出現sql注入。
public static void save(String username,String password) {
jdbcTemplate.update("insert into test_table(user_name,password) values(?,?)",
new Object[]{username,password});
}
public static int queryForInt_(String id){
return jdbcTemplate.queryForInt("select count(0) from test_table where id = " + id);
}
#為了方便僅僅貼出了DAO層程式碼
所以,在java程式碼的開發過程中,我們儘量避免使用拼接sql語句的形式去執行資料庫語句。如果需要使用拼接sql語句的形式進行資料庫查詢,那麼OWASP提供了一個防禦sql注入的Esapi包,這個包中的encodeForSQL方法能對sql注入進行很好的防禦。
接著我們就分析下這個encodeForSQL方法。
首先我們介紹這個方法的使用,使用時呼叫如下,不同的資料庫使用不到的方法。
//防止Oracle注入
ESAPI.encoder().encodeForSQL(new OracleCodec(),queryparam)
//防止mysql注入
ESAPI.encoder().encodeForSQL(new MySQLCodec(Mode.STANDARD),queryparam) //Mode.STANDARK為標準的防注入方式,mysql一般用使用的是這個方式
//防止DB2注入
ESAPI.encoder().encodeForSQL(new DB2Codec(),queryparam)
//防止Oracle注入的方法例子,為了方便僅僅給出sql語句的拼接部分
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"))+"’";
下面我們就用mysql為例字分析encodeForSQL函式做了什麼防禦。具體函式過
程就不跟蹤了,直接分析最後呼叫了哪個方法。根據程式碼可知最後呼叫的是encodeCharacter方法。
public String encodeCharacter( char[] immune, Character c ) {
char ch = c.charValue();
// check for immune characters
if ( containsCharacter( ch, immune ) ) {
return ""+ch;
}
// check for alphanumeric characters
String hex = Codec.getHexForNonAlphanumeric( ch );
if ( hex == null ) {
return ""+ch;
}
switch( mode ) {
case ANSI: return encodeCharacterANSI( c );
case STANDARD: return encodeCharacterMySQL( c );
}
return null;
}
上述方法中containsCharacter函式是不進行驗證的字串白名單,Codec.getHexForNonAlphanumeric函式查詢字元傳中是否有16進位制,沒有返回空值。
而encodeCharacterANSI和encodeCharacterMySQL才是防禦的重點,我們看一下這兩個函式的不同,如果選擇的我們選擇是Mode.ANSi模式,則字串則進入下面的函式,可以看到這個函式對單撇號和雙撇號進行了轉義。
private String encodeCharacterANSI( Character c ) {
if ( c == '\'' )
return "\'\'";
if ( c == '\"' )
return "";
return ""+c;
}
如果選擇的是Mode.STANDARD模式,則字串 則進入下面的函式,可以看到這個函式對單撇號和雙撇號、百分號、反斜線等更多的符號進行了轉換,所以使用時推薦使用標準模式。
private String encodeCharacterMySQL( Character c ) {
char ch = c.charValue();
if ( ch == 0x00 ) return "\\0";
if ( ch == 0x08 ) return "\\b";
if ( ch == 0x09 ) return "\\t";
if ( ch == 0x0a ) return "\\n";
if ( ch == 0x0d ) return "\\r";
if ( ch == 0x1a ) return "\\Z";
if ( ch == 0x22 ) return "\\\"";
if ( ch == 0x25 ) return "\\%";
if ( ch == 0x27 ) return "\\'";
if ( ch == 0x5c ) return "\\\\";
if ( ch == 0x5f ) return "\\_";
return "\\" + c;
}
我們介紹了利用繫結變數和利用esapi兩種方式對sql注入進行防禦,我的建議是儘量使用繫結變數的是形式進行防注入,安全效能都比較好。
0x02:跨站指令碼攻擊
關於跨站指令碼攻擊的防禦,我們分析esapi的防禦方式。
esapi的防禦方式是根據輸出點的不同在不同的輸出點進行相應的編碼。我們看一下使用方法:
xss輸出點在html網頁中
ESAPI.encoder().encodeForHTML(String input)
xss輸出點在html屬性中
ESAPI.encoder().encodeForHTMLAttribute(String input)
xss輸出點在JavaScript程式碼中
ESAPI.encoder().encodeForJavaScript(String input)
xss輸出點在CSS程式碼中
ESAPI.encoder().encodeForCSS(String input)
xss輸出點在VBScript程式碼中
ESAPI.encoder().encodeForVBScript(String input)
xss輸出點在XPath中
ESAPI.encoder().encodeForXPath(String input)
xss輸出點在XML中
ESAPI.encoder().encodeForXML(String input)
xss輸出點在XML屬性中
ESAPI.encoder().encodeForXMLAttribute(String input)
直接對url進行URL編碼
ESAPI.encoder().encodeForURL(String input)
如果java輸出在html頁面,使用如下示例的方法即可。
String username = ESAPI.encoder().encodeForHTML(req.getParameter("name"))
接下來我們就研究這個方法的具體實現。
public String encodeCharacter( char[] immune, Character c ) {
// check for immune characters
if ( containsCharacter(c, immune ) ) {
return ""+c;
}
// check for alphanumeric characters
String hex = Codec.getHexForNonAlphanumeric(c);
if ( hex == null ) {
return ""+c;
}
// check for illegal characters
//ascii碼中的非數字,字元的編碼,一般為非列印字元,即不能轉換的為uncoide的ascii字元,直接替換成\ufffd,顯示的為?
if ( ( c <= 0x1f && c != '\t' && c != '\n' && c != '\r' ) || ( c >= 0x7f && c <= 0x9f ) )
{
hex = REPLACEMENT_HEX; // Let's entity encode this instead of returning it
c = REPLACEMENT_CHAR;
}
// check if there's a defined entity
//#惡意字元以實體的形式輸出
String entityName = (String) characterToEntityMap.get(c);
if (entityName != null) {
return "&" + entityName + ";";
}
// return the hex entity as suggested in the spec,#如果是16進位制就轉換為html16進位制實體字元輸出
return "&#x" + hex + ";";
}
惡意字元在js中的編碼大家可以看到使用的是js的十六進位制編碼或者jsunicode編碼進行的編碼。
其實上面的方法大都是對字元進行html實體編碼,html十六進位制編碼,js十六進位制編碼,jsunicode的編碼和url編碼來防止惡意標籤的執行。如果感興趣可以看一下其他的編碼方法,原理大致相同就不在一一介紹。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69914889/viewspace-2640798/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- webgame中常見安全問題、防禦方式與挽救措施WebGAM
- 疫情當前,中安威士助力支撐聯防聯控工作
- JAVA中常見的阻塞佇列詳解Java佇列
- 威脅預警|微軟最新遠端高危漏洞通告及防禦措施微軟
- 【小白必學】檔案上傳的漏洞介紹及常見防禦方法
- 常見的網路安全威脅詳解!
- java中常見的六種執行緒池詳解Java執行緒
- 盤點web應用程式中常見的漏洞!Web
- 一文帶你瞭解網路安全中的主動防禦與被動防禦!
- SpringMVC 框架系列之元件概述與配置詳解SpringMVC框架元件
- 萬能密碼的SQL隱碼攻擊漏洞其PHP環境搭建及程式碼詳解+防禦手段密碼SQLPHP
- flask中的csrf防禦機制Flask
- 中安威士:刑事司法系統中大資料的雙刃劍大資料
- SQL隱碼攻擊漏洞威脅網路安全 防禦措施應從編碼開始做起SQL
- 寶塔漏洞防禦 防止資料庫被刪的方案資料庫
- web常見的攻擊方式有哪些?如何防禦?Web
- 中安威士入選中國網路安全能力100強
- 【知識分享】高防伺服器的常見幾種防禦模式伺服器模式
- 資訊保安最常見的5種主要威脅詳解!
- springmvc中Dispatchservlet繼承體系詳解SpringMVCServlet繼承
- 常見的伺服器漏洞防護措施!伺服器
- 2022 SDC 議題 | Linux 核心漏洞檢測與防禦Linux
- PHP檔案上傳漏洞原理以及防禦姿勢PHP
- 常見RDP協議攻擊方法 防禦措施協議
- 常見網路攻擊有哪些?如何防禦?
- 反射式 XSS 的解釋及其防禦反射
- Java中常見方法詳解合集(方法的定義及語法結構)Java
- cc攻擊防禦解決方法
- spring中常見的一些註解Spring
- SpringMVC詳解(補加)SpringMVC
- SpringMVC工作原理詳解SpringMVC
- 你的郵件安全嗎? 電子郵件威脅與防禦剖析
- 21個JavaScript 面試中常見演算法問題詳解JavaScript面試演算法
- AccessibilityService防禦
- DDoS 防禦
- 0day漏洞是什麼以及如何進行防禦
- 【技術向】CVE-2019-1040漏洞分析&防禦報告
- Storm中Trident框架詳解ORMIDE框架