温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

2011-12-01 SQL注入的防备

发布时间:2020-08-11 01:06:47 来源:ITPUB博客 阅读:137 作者:hanaka 栏目:关系型数据库

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

207楼

我创建如下的两张表并填入数据:

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;
/

然后我创建了这个函数来返回一个游标,里面包含了指定表名的name列的数据:

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;
/

这里是一个“帮手”过程来显示这个函数所返回的数据:

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;
/

当我执行下列这个代码块,我可以看到Beatles 和 Grateful Dead乐队的成员。(即上述两张表中的数据)

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

不幸的是,如果我这样来执行:

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

我看到了数据库实例中所有用户的名字,这属于安全违规(是一种SQL注入)

下面哪些plch_get_names函数会抛出异常,假如调用时传入了那个“注入”参数值,但是如果传入像plch_names1 和 plch_names2这样的“真实”表名你还可以看到表中数据?

(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中可用的简单名字:
  名字必须以字母开头,随后可跟随数字、字母或_, $, # 字符;
  允许带双引号,双引号之间可以是任意字符;
  假如双引号之内的名字本身就带有双引号,那么必须重复双引号两次来表示;
  输入参数如果前后带有空格被忽略。
  名字的长度没有被检测。
DBMS_ASSERT.qualified_sql_name则更宽松一些,允许带.(小数点,比如用在记录成员、PACKAGE里面的函数、SCHEMA OWNER等)和@ (用在DBLINK)
答案B: simple_sql_name是函数不是存储过程,必须将返回值赋给变量。
答案D: 表名不可以用绑定变量。
向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI