2011-12-01SQL注入的防備-創(chuàng)新互聯(lián)
/tupian/20230522/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)建了這個(gè)函數(shù)來(lái)返回一個(gè)游標(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; /
這里是一個(gè)“幫手”過(guò)程來(lái)顯示這個(gè)函數(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í)行下列這個(gè)代碼塊,我可以看到Beatles 和 Grateful Dead樂(lè)隊(duì)的成員。(即上述兩張表中的數(shù)據(jù))
BEGIN plch_show_names ('plch_names1'); plch_show_names ('plch_names2'); END; /
不幸的是,如果我這樣來(lái)執(zhí)行:
BEGIN plch_show_names ( 'plch_names2 where 1=2 union select username from all_users --'); END; /
我看到了數(shù)據(jù)庫(kù)實(shí)例中所有用戶的名字,這屬于安全違規(guī)(是一種SQL注入)
下面哪些plch_get_names函數(shù)會(huì)拋出異常,假如調(diào)用時(shí)傳入了那個(gè)“注入”參數(shù)值,但是如果傳入像plch_names1 和 plch_names2這樣的“真實(shí)”表名你還可以看到表中數(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;
答案說(shuō)明在209樓
2011-12-01答案AC. DBMS_ASSERT.SIMPLE_SQL_NAME檢查一個(gè)名字是否為SQL中可用的簡(jiǎn)單名字: 名字必須以字母開(kāi)頭,隨后可跟隨數(shù)字、字母或_, $, # 字符; 允許帶雙引號(hào),雙引號(hào)之間可以是任意字符; 假如雙引號(hào)之內(nèi)的名字本身就帶有雙引號(hào),那么必須重復(fù)雙引號(hào)兩次來(lái)表示; 輸入?yún)?shù)如果前后帶有空格被忽略。 名字的長(zhǎng)度沒(méi)有被檢測(cè)。 DBMS_ASSERT.qualified_sql_name則更寬松一些,允許帶.(小數(shù)點(diǎn),比如用在記錄成員、PACKAGE里面的函數(shù)、SCHEMA OWNER等)和@ (用在DBLINK) 答案B: simple_sql_name是函數(shù)不是存儲(chǔ)過(guò)程,必須將返回值賦給變量。 答案D: 表名不可以用綁定變量。
當(dāng)前名稱:2011-12-01SQL注入的防備-創(chuàng)新互聯(lián)
網(wǎng)站URL:http://www.xueling.net.cn/article/jdhji.html