溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

2011-12-01 SQL注入的防備

發(fā)布時間:2020-08-11 01:06:47 來源:ITPUB博客 閱讀:130 作者:hanaka 欄目:關(guān)系型數(shù)據(jù)庫

http://www.itpub.net/thread-1499223-21-1.html

207樓

我創(chuàng)建如下的兩張表并填入數(shù)據(jù):

CREATE TABLE plch_names1 (name VARCHAR2 (100))
/
CREATE TABLE plch_names2 (name VARCHAR2 (100))
/
BEGIN
   INSERT INTO plch_names1 VALUES ('Paul');
   INSERT INTO plch_names1 VALUES ('Ringo');
   INSERT INTO plch_names1 VALUES ('John');
   INSERT INTO plch_names1 VALUES ('George');
   INSERT INTO plch_names2 VALUES ('Jerry');
   INSERT INTO plch_names2 VALUES ('Bob');
   INSERT INTO plch_names2 VALUES ('Phil');
   COMMIT;
END;
/

然后我創(chuàng)建了這個函數(shù)來返回一個游標(biāo),里面包含了指定表名的name列的數(shù)據(jù):

CREATE OR REPLACE FUNCTION plch_get_names (table_in IN VARCHAR2)
   RETURN SYS_REFCURSOR
IS
   l_cv   SYS_REFCURSOR;
BEGIN
   OPEN l_cv FOR 'select name from ' || table_in || ' order by name';
   RETURN l_cv;
END plch_get_names;
/

這里是一個“幫手”過程來顯示這個函數(shù)所返回的數(shù)據(jù):

CREATE OR REPLACE PROCEDURE plch_show_names (table_in IN VARCHAR2)
IS
   l_cv     SYS_REFCURSOR;
   l_name   plch_names1.name%TYPE;
BEGIN
   DBMS_OUTPUT.put_line ('Names in ' || table_in);
   l_cv := plch_get_names (table_in);
   LOOP
      FETCH l_cv INTO l_name;
      EXIT WHEN l_cv%NOTFOUND;
      DBMS_OUTPUT.put_line (l_name);
   END LOOP;
   CLOSE l_cv;
END plch_show_names;
/

當(dāng)我執(zhí)行下列這個代碼塊,我可以看到Beatles 和 Grateful Dead樂隊的成員。(即上述兩張表中的數(shù)據(jù))

BEGIN
   plch_show_names ('plch_names1');
   plch_show_names ('plch_names2');
END;
/

不幸的是,如果我這樣來執(zhí)行:

BEGIN
   plch_show_names (
      'plch_names2 where 1=2 union select username from all_users --');
END;
/

我看到了數(shù)據(jù)庫實例中所有用戶的名字,這屬于安全違規(guī)(是一種SQL注入)

下面哪些plch_get_names函數(shù)會拋出異常,假如調(diào)用時傳入了那個“注入”參數(shù)值,但是如果傳入像plch_names1 和 plch_names2這樣的“真實”表名你還可以看到表中數(shù)據(jù)?

(A)

BEGIN
   OPEN l_cv FOR
         'select name from '
      || DBMS_ASSERT.simple_sql_name (table_in)
      || ' order by name';
   RETURN l_cv;
END plch_get_names;

(B)

BEGIN
   DBMS_ASSERT.simple_sql_name (table_in);
   OPEN l_cv FOR 'select name from ' || table_in || ' order by name';
   RETURN l_cv;
END plch_get_names;

(C)

BEGIN
   OPEN l_cv FOR
         'select name from '
      || DBMS_ASSERT.qualified_sql_name (table_in)
      || ' order by name';
   RETURN l_cv;
END plch_get_names;

(D)

BEGIN
   OPEN l_cv FOR 'select name from :table_name order by name' USING table_in;
   RETURN l_cv;
END plch_get_names;

答案說明在209樓

2011-12-01答案AC.
DBMS_ASSERT.SIMPLE_SQL_NAME檢查一個名字是否為SQL中可用的簡單名字:
  名字必須以字母開頭,隨后可跟隨數(shù)字、字母或_, $, # 字符;
  允許帶雙引號,雙引號之間可以是任意字符;
  假如雙引號之內(nèi)的名字本身就帶有雙引號,那么必須重復(fù)雙引號兩次來表示;
  輸入?yún)?shù)如果前后帶有空格被忽略。
  名字的長度沒有被檢測。
DBMS_ASSERT.qualified_sql_name則更寬松一些,允許帶.(小數(shù)點(diǎn),比如用在記錄成員、PACKAGE里面的函數(shù)、SCHEMA OWNER等)和@ (用在DBLINK)
答案B: simple_sql_name是函數(shù)不是存儲過程,必須將返回值賦給變量。
答案D: 表名不可以用綁定變量。
向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI