新聞中心
Oracle sql注入是一個(gè)古老的安全問(wèn)題,一般做企業(yè)應(yīng)用的只關(guān)注Java層面的編寫(xiě)規(guī)范,比如使用preparedStatement,或者干脆直接過(guò)濾掉危險(xiǎn)字符等等。其實(shí)在編寫(xiě)PL/SQL的function或procedure的時(shí)候,也存在注入的問(wèn)題,我們來(lái)簡(jiǎn)單探討一下。

成都創(chuàng)新互聯(lián)專注于成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站制作、網(wǎng)站開(kāi)發(fā)。公司秉持“客戶至上,用心服務(wù)”的宗旨,從客戶的利益和觀點(diǎn)出發(fā),讓客戶在網(wǎng)絡(luò)營(yíng)銷中找到自己的駐足之地。尊重和關(guān)懷每一位客戶,用嚴(yán)謹(jǐn)?shù)膽B(tài)度對(duì)待客戶,用專業(yè)的服務(wù)創(chuàng)造價(jià)值,成為客戶值得信賴的朋友,為客戶解除后顧之憂。
例如有這樣一個(gè)procedure,功能為禁用某個(gè)table的constraint:
Sql代碼
CREATE OR REPLACE PROCEDURE Disable_Constraint ( p_constraint_name VARCHAR2, p_table VARCHAR2 )
AUTHID CURRENT_USER
AS
p_schema VARCHAR2(32) := USER;
sql_stmt VARCHAR2(2000) := 'ALTER TABLE '
|| p_schema
|| '.'
|| p_table
|| ' DISABLE CONSTRAINT '
|| p_constraint_name ;
BEGIN
EXECUTE IMMEDIATE sql_stmt;
END;
/
了解Oracle sql注入的同學(xué)應(yīng)該可以看出來(lái),上面的procedure存在幾個(gè)危險(xiǎn)的變量:
1. p_table
2. p_constraint_name
3. p_schema
前兩者容易發(fā)現(xiàn),但為什還有p_schema呢?因?yàn)楫?dāng)前的USER名字也有可能是用戶構(gòu)造的危險(xiǎn)字符串。好了,根據(jù)一般規(guī)律,我們應(yīng)該遵循以下順序進(jìn)行修改:
1. 靜態(tài)SQL。能不使用變量就不使用。
2. 綁定變量。與Java中的PreparedStatement類似,不把數(shù)據(jù)直接拼接在sql里,而是存入變量中,直接被數(shù)據(jù)庫(kù)使用。
3. 檢查變量的值。
顯然,前兩個(gè)方法對(duì)這個(gè)procedure不適用。我們只能使用最不爽的第3個(gè)方法。好在對(duì)于Oracle SQL注入與PL注入來(lái)說(shuō),我們不用自己編寫(xiě)復(fù)雜的字符判斷。Oracle有個(gè)SYS.DBMS_ASSERT包,提供了一些預(yù)置的function,如下:
NOOP No Operation. Returns string unchanged
SIMPLE_SQL_NAME Verify that the input string is a simple SQL name.
QUALIFIED_SQL_NAME Verify that the input string is a qualified SQL name.
SCHEMA_NAME This function verifies that the input string is an existing schema name.
SQL_OBJECT_NAME This function verifies that the input parameter string is a qualified SQL identifier of an existing SQL object.
ENQUOTE_NAME This function encloses a name in double quotes.
ENQUOTE_LITERAL Add leading and trailing single quotes to a string literal.
在執(zhí)行這些function時(shí),如果傳入的變量不滿足規(guī)定的格式或條件,則會(huì)拋異常,從而保護(hù)我們自己的procedure不被SQL注入。
我們判斷這些方法是否可用:
1. SIMPLE_SQL_NAME, QUALIFIED_SQL_NAME
這些方法要求用戶出入的參數(shù)本身是一個(gè)有效的sql名字。比如,如果有個(gè)table名為"Table One",那么就要求傳入的值中包含雙引號(hào)。使用這些方法存在一個(gè)問(wèn)題,直接從data-dictionary讀取出來(lái)的table名字是不帶雙引號(hào)的。如果用戶直接從data-dictionary中讀取table名字,然后直接傳入我們的procedure,則會(huì)因?yàn)樗粷M足simple sql name的要求而拋異常,但實(shí)際上這個(gè)table名字應(yīng)該是正確的。所以不能直接使用這些function。
2. SCHEMA_NAME, SQL_OBJECT_NAME
這些方法要求傳入的參數(shù)值是數(shù)據(jù)庫(kù)中已經(jīng)存在的對(duì)象名字。如果數(shù)據(jù)庫(kù)中本來(lái)有個(gè)table名為 "Table One",那么如果用戶傳入Table One,則被視為正確。使用這些方法,避免了第一個(gè)方法的data-dictionary問(wèn)題,而且也能夠避免遭受類似table' -- 的問(wèn)題。但存在所謂二次攻擊的問(wèn)題。如果用戶提前創(chuàng)建了一個(gè)包含危險(xiǎn)字符的table,然后再調(diào)用我們的procedure,依舊會(huì)造成SQL注入。
3. ENQUOTE_NAME, ENQUOTE_LITERAL
這些方法直接把參數(shù)的值用雙引號(hào)或單引號(hào)括起來(lái)。如果括起來(lái)之后的值本身還存在危險(xiǎn)的話,會(huì)拋異常。對(duì)于我們舉例的procedure來(lái)說(shuō),只需要使用ENQUOTE_NAME。ENQUOTE_NAME需要兩個(gè)參數(shù),一個(gè)是需要enquote的變量,另一個(gè)為是否轉(zhuǎn)換為大寫(xiě)?,F(xiàn)在,對(duì)于我們的procedure,應(yīng)該使用ENQUOTE_NAME(p_table, FALSE),保證Table One不被轉(zhuǎn)換為"TABLE ONE"。
這是我們的最終解決方案。但需要注意的是,由于使用了ENQUOTE_NAME,對(duì)于我們的procedure來(lái)說(shuō),table和constraint的名字對(duì)大小寫(xiě)敏感。如果名為table_1,則必須傳入TABLE_1,否則會(huì)執(zhí)行錯(cuò)誤。
修改后的代碼如下:
Sql代碼
CREATE OR REPLACE PROCEDURE Disable_Constraint ( p_constraint_name VARCHAR2, p_table VARCHAR2 )
AUTHID CURRENT_USER
AS
p_schema VARCHAR2(32) := SYS.DBMS_ASSERT.ENQUOTE_NAME(USER, FALSE);
sql_stmt VARCHAR2(2000);
safe_table VARCHAR2(32);
safe_constraint VARCHAR2(32);
BEGIN
safe_table := SYS.DBMS_ASSERT.ENQUOTE_NAME(p_table, FALSE);
safe_constraint := SYS.DBMS_ASSERT.ENQUOTE_NAME(p_constraint_name, FALSE);
sql_stmt := 'ALTER TABLE '
|| p_schema
|| '.'
|| safe_table
|| ' DISABLE CONSTRAINT '
|| safe_constraint ;
EXECUTE IMMEDIATE sql_stmt;
END;
/
【編輯推薦】
- Oracle性能診斷不能不知的秘籍
- 使用dtu遠(yuǎn)程連接Oracel 9i數(shù)據(jù)庫(kù)的方法
- Windows2000服務(wù)器下安裝Oracle9i與10g
- Oracle多表查詢優(yōu)化的代碼示例
- Oracle更改的默認(rèn)端口號(hào)剖析
文章題目:OracleSQL注入與PL注入剖析
標(biāo)題路徑:http://fisionsoft.com.cn/article/dhgpcdd.html


咨詢
建站咨詢
