自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Oracle SQL注入與PL注入剖析

數(shù)據(jù)庫 Oracle
本人很喜歡Oracle SQL注入與PL注入的代碼編寫,在工作中也很喜歡總結(jié)關(guān)于PL/SQL的語言,下面就SQL注入這個問題來詳細說說吧。

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

例如有這樣一個procedure,功能為禁用某個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)該可以看出來,上面的procedure存在幾個危險的變量:
1. p_table
2. p_constraint_name
3. p_schema

前兩者容易發(fā)現(xiàn),但為什還有p_schema呢?因為當(dāng)前的USER名字也有可能是用戶構(gòu)造的危險字符串。好了,根據(jù)一般規(guī)律,我們應(yīng)該遵循以下順序進行修改:
1. 靜態(tài)SQL。能不使用變量就不使用。
2. 綁定變量。與Java中的PreparedStatement類似,不把數(shù)據(jù)直接拼接在sql里,而是存入變量中,直接被數(shù)據(jù)庫使用。
3. 檢查變量的值。

顯然,前兩個方法對這個procedure不適用。我們只能使用最不爽的第3個方法。好在對于Oracle SQL注入與PL注入來說,我們不用自己編寫復(fù)雜的字符判斷。Oracle有個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時,如果傳入的變量不滿足規(guī)定的格式或條件,則會拋異常,從而保護我們自己的procedure不被SQL注入。

我們判斷這些方法是否可用:

1. SIMPLE_SQL_NAME, QUALIFIED_SQL_NAME

這些方法要求用戶出入的參數(shù)本身是一個有效的sql名字。比如,如果有個table名為"Table One",那么就要求傳入的值中包含雙引號。使用這些方法存在一個問題,直接從data-dictionary讀取出來的table名字是不帶雙引號的。如果用戶直接從data-dictionary中讀取table名字,然后直接傳入我們的procedure,則會因為它不滿足simple sql name的要求而拋異常,但實際上這個table名字應(yīng)該是正確的。所以不能直接使用這些function。

2. SCHEMA_NAME, SQL_OBJECT_NAME

這些方法要求傳入的參數(shù)值是數(shù)據(jù)庫中已經(jīng)存在的對象名字。如果數(shù)據(jù)庫中本來有個table名為 "Table One",那么如果用戶傳入Table One,則被視為正確。使用這些方法,避免了第一個方法的data-dictionary問題,而且也能夠避免遭受類似table' -- 的問題。但存在所謂二次攻擊的問題。如果用戶提前創(chuàng)建了一個包含危險字符的table,然后再調(diào)用我們的procedure,依舊會造成SQL注入。

3. ENQUOTE_NAME, ENQUOTE_LITERAL

這些方法直接把參數(shù)的值用雙引號或單引號括起來。如果括起來之后的值本身還存在危險的話,會拋異常。對于我們舉例的procedure來說,只需要使用ENQUOTE_NAME。ENQUOTE_NAME需要兩個參數(shù),一個是需要enquote的變量,另一個為是否轉(zhuǎn)換為大寫?,F(xiàn)在,對于我們的procedure,應(yīng)該使用ENQUOTE_NAME(p_table, FALSE),保證Table One不被轉(zhuǎn)換為"TABLE ONE"。

這是我們的最終解決方案。但需要注意的是,由于使用了ENQUOTE_NAME,對于我們的procedure來說,table和constraint的名字對大小寫敏感。如果名為table_1,則必須傳入TABLE_1,否則會執(zhí)行錯誤。

修改后的代碼如下:

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;

/
 

【編輯推薦】

  1. Oracle性能診斷不能不知的秘籍
  2. 使用dtu遠程連接Oracel 9i數(shù)據(jù)庫的方法
  3. Windows2000服務(wù)器下安裝Oracle9i與10g
  4. Oracle多表查詢優(yōu)化的代碼示例
  5. Oracle更改的默認端口號剖析
責(zé)任編輯:佚名
相關(guān)推薦

2010-04-12 08:59:00

2010-12-20 16:04:30

2010-09-14 16:00:16

2009-03-27 10:53:52

注入SQLMySQL

2017-08-10 10:23:59

2009-12-16 17:58:18

2020-10-26 07:04:29

SQL注入mysql

2013-05-02 15:09:22

2017-05-05 11:31:34

2017-09-07 15:54:49

2020-09-28 09:30:13

mybatis

2010-09-27 11:17:31

2011-10-19 10:47:56

2020-12-16 13:22:37

Web安全SQL工具

2010-11-01 17:22:44

2014-11-27 09:31:26

2009-07-24 10:29:29

PL SQL編程規(guī)范

2010-09-08 13:10:03

2010-06-30 17:56:06

2017-05-08 14:33:51

點贊
收藏

51CTO技術(shù)棧公眾號