存储过程可以防止 SQL 注入吗?

Am1*_*3zA 85 postgresql security sql-injection

存储过程真的可以防止针对 PostgreSQL 数据库的 SQL 注入攻击吗?我做了一点研究,发现即使我们只使用存储过程,SQL Server、Oracle 和 MySQL 也不能安全地抵御 SQL 注入。但是,这个问题在 PostgreSQL 中不存在。

PostgreSQL 核心中的存储过程实现是防止 SQL 注入攻击还是其他什么?或者即使我们只使用存储过程,PostgreSQL 是否也容易受到 SQL 注入的影响?如果是这样,请给我举个例子(例如书籍、网站、论文等)。

小智 74

不,存储过程不能防止 SQL 注入。这是一个存储过程的实际示例(来自我工作的某人创建的内部应用程序),不幸的是它允许 SQL 注入:

这个sql服务器代码:

CREATE PROCEDURE [dbo].[sp_colunmName2]   
    @columnName as nvarchar(30),
    @type as nvarchar(30), 
    @searchText as nvarchar(30)           
AS
BEGIN
    DECLARE @SQLStatement NVARCHAR(4000)
    BEGIN
        SELECT @SQLStatement = 'select * from Stations where ' 
            + @columnName + ' ' + @type + ' ' + '''' + @searchText + '''' 
        EXEC(@SQLStatement)
    END      
END
GO
Run Code Online (Sandbox Code Playgroud)

大致相当于 postgres:

CREATE or replace FUNCTION public.sp_colunmName2 (
    columnName  varchar(30),
    type varchar(30), 
    searchText  varchar(30) ) RETURNS SETOF stations LANGUAGE plpgsql            
AS
$$
DECLARE SQLStatement VARCHAR(4000);
BEGIN
    SQLStatement = 'select * from Stations where ' 
            || columnName || ' ' || type || ' ' || ''''|| searchText || '''';
    RETURN QUERY EXECUTE  SQLStatement;
END
$$;
Run Code Online (Sandbox Code Playgroud)

开发人员的想法是创建一个通用的搜索过程,但结果是 WHERE 子句可以包含用户想要的任何内容,从而允许来自小 Bobby Tables的访问。

使用 SQL 语句还是存储过程并不重要。重要的是您的 SQL 是使用参数还是连接字符串。参数防止SQL注入;连接的字符串允许 SQL 注入。


Bri*_*ton 46

SQL 注入攻击是将不受信任的输入直接附加到查询中的攻击,允许用户有效地执行任意代码,如这个规范的 XKCD 漫画所示。

于是,我们得到了这样的情况:

userInput = getFromHTML # "Robert ') 删除表学生;--"

Query = "Select * from Students where studentName = " + userInput

通常,存储过程是针对 SQL 注入攻击的良好防御,因为从不解析传入的参数。

在存储过程中,在大多数 DB(和程序,不要忘记预编译查询算作存储过程)中,如下所示:

 

创建存储过程 foo (
从学生名 = :1 的学生中选择 *
);

然后,当程序需要访问时,它会调用foo(userInput)并愉快地检索结果。

存储过程并不是针对 SQL 注入的神奇防御,因为人们完全能够编写出错误的存储过程。但是,如果您了解 SQL 注入的工作原理,预编译的查询,无论是存储在数据库中还是程序中,都更难打开安全漏洞

您可以阅读有关 SQL 注入的更多信息:


Cod*_*awk 29

是的,在某种程度上。
单独的存储过程不会阻止 SQL 注入。

让我先引用一下OWASP 的SQL 注入

SQL 注入攻击包括通过从客户端到应用程序的输入数据插入或“注入”SQL 查询。成功的 SQL 注入漏洞可以从数据库读取敏感数据、修改数据库数据(插入/更新/删除)、对数据库执行管理操作(例如关闭 DBMS)、恢复 DBMS 文件中存在的给定文件的内容系统并在某些情况下向操作系统发出命令。SQL 注入攻击是一种注入攻击,其中 SQL 命令被注入到数据平面输入中,以影响预定义 SQL 命令的执行。

即使您正在使用存储过程,您也必须清理用户输入并且不要连接 SQL 语句。

Jeff Attwood 在“给我参数化 SQL,否则给我死”中解释了连接 sql 的后果

以下是每当我听到 SQL 注入时就会想到的有趣卡通 替代文字 我想你明白了:-)

看一看SQL Injection Prevention Cheat Sheet,预防方法被巧妙地解释了......


gbn*_*gbn 13

字符串连接是 SQL 注入的原因。使用参数化可以避免这种情况。

存储过程通过在连接时强制执行无效语法来增加额外的安全层,但如果在其中使用动态 SQL,则不是“更安全”。

所以,你上面的代码是由这些字符串的连接引起的

  • exec sp_GetUser '
  • x' AND 1=(SELECT COUNT(*) FROM Client); --
  • ' , '
  • monkey
  • '

幸运的是,这给出了无效的语法

参数化它会给

exec sp_GetUser 'x'' AND 1=(SELECT COUNT(*) FROM Client); --' , 'monkey'
Run Code Online (Sandbox Code Playgroud)

这意味着

  • @UserName = x' AND 1=(SELECT COUNT(*) FROM Client); --
  • @Password = monkey

现在,在上面的代码中你不会得到任何行,因为我假设你没有用户 x' AND 1=(SELECT COUNT(*) FROM Client); --

如果存储过程看起来像这样(使用连接的动态 SQL),那么您的参数化存储过程调用仍将允许 SQL 注入

...
SET @sql = 'SELECT userName from users where userName = ''' + 
               @UserName + 
               ''' and userPass = ''' +
               @Password +
               ''''
EXEC (@sql)
....
Run Code Online (Sandbox Code Playgroud)

因此,正如演示的那样,字符串连接是 SQL 注入的主要敌人

存储过程确实增加了封装、事务处理、减少权限等,但它们仍然可能被滥用于 SQL 注入。

你可以在 Stack Overflow 上查看更多关于参数化的信息


小智 10

“SQL注入攻击发生时用户输入的编码错误。典型地,所述用户输入是一些数据的用户和她的查询发送,在IE值$_GET$_POST$_COOKIE$_REQUEST,或$_SERVER阵列。然而,用户输入也来自各种其他源,如套接字、远程网站、文件等。因此,您应该真正将除常量(如'foobar')以外的所有内容都视为用户输入。”

我最近一直在彻底调查这个主题,并想与其他人分享非常有趣的材料,从而使这篇文章更加完整和对每个人都有启发。



来自 YouTube


来自维基百科


来自 OWASP


来自 PHP 手册


来自微软和甲骨文


堆栈溢出


SQL注入扫描器