AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 127
Accepted
Am1rr3zA
Am1rr3zA
Asked: 2011-01-04 23:24:30 +0800 CST2011-01-04 23:24:30 +0800 CST 2011-01-04 23:24:30 +0800 CST

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

  • 772

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

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

postgresql security
  • 6 6 个回答
  • 12348 Views

6 个回答

  • Voted
  1. Best Answer
    Kyralessa
    2011-02-10T10:15:19+08:002011-02-10T10:15:19+08:00

    不,存储过程不会阻止 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
    

    大致相当于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
    $$;
    

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

    无论您使用 SQL 语句还是存储过程都无关紧要。重要的是您的 SQL 是使用参数还是连接字符串。参数防止SQL注入;串联的字符串允许 SQL 注入。

    • 76
  2. Brian Ballsun-Stanton
    2011-01-05T01:09:58+08:002011-01-05T01:09:58+08:00

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

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

    userInput = getFromHTML # "Robert ') Drop table students; --"
    
    Query = "Select * from students where studentName = " + userInput
    

    存储过程通常可以很好地防御 SQL 注入攻击,因为从不解析传入的参数。

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

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

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

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

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

    • 在 Jeff Atwood 的讨论中
    • 预防备忘单
    • 如何攻击您自己的代码(确保您的 QA 包括安全测试。如果没有,您的站点将由外部进行安全测试。这是一件坏事。)
    • 47
  3. CoderHawk
    2011-01-05T01:03:36+08:002011-01-05T01:03:36+08:00

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

    让我首先引用OWASP的 SQL 注入

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

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

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

    以下是每当我听到 SQL 注入时我脑海中浮现的有趣漫画, 替代文字 我认为你明白了 :-)

    看一下SQL Injection Prevention Cheat Sheet,预防方法被整齐地解释...

    • 29
  4. gbn
    2012-05-08T23:08:41+08:002012-05-08T23:08:41+08:00

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

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

    因此,您上面的代码是由这些字符串的串联引起的

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

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

    参数化它会给

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

    这表示

    • @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)
    ....
    

    因此,如所示,字符串连接是 SQL 注入的主要敌人

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

    您可以查看 Stack Overflow 以了解有关参数化的更多信息

    • 13
  5. Ilia
    2012-08-29T00:22:54+08:002012-08-29T00:22:54+08:00

    “当用户输入编码不正确时,就会发生 SQL 注入攻击。通常,用户输入是用户通过查询发送的一些数据,即 , , , 或数组中的值$_GET。$_POST但是$_COOKIE,$_REQUEST用户$_SERVER输入也可以来自各种其他源,如套接字、远程网站、文件等。因此,您应该真正将除常量(如'foobar')之外的所有内容都视为用户输入。”

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

    • John Nebel 用 PHP 防止 SQL 注入
    • 安全角 - Chris Shiflett 的 SQL 注入
    • Alexander Andonov 的意外 SQL 注入
    • Mysql_real_escape_string() 与 Ilia Alshanetsky 的 Prepared Statements
    • Sagar Joshi 的 SQL 注入攻击和防御
    • Jim Whitehead 教授的 SQL 注入攻击
    • 克里斯·希夫莱特的addlashes() vs mysql_real_escape_string()
    • Joel Spolsky 的 SQL 注入错误是什么

    • MySQL - SQL 注入预防
    • SQL 注入演练
    • SQL 注入备忘单
    • PHP 和 MySQLi 中的预处理语句


    来自 YouTube

    • SQL 注入神话和谬误:Bill Karwin 的最佳防御实践
    • PHP 教程:安全性 - SQL 注入
    • 如何在 Backtrack5 RC1 上使用 SQLMAP 进行 SQL 注入

    来自维基百科

    • 维基百科 - SQL 注入
    • 维基百科 - SQL

    来自 OWASP

    • SQL 注入
    • SQL 注入指南
    • OWASP - 避免 SQL 注入
    • SQL 注入预防备忘单
    • 测试 SQL 注入

    来自 PHP 手册

    • SQL 注入
    • PDO 类 - 准备好的语句和存储过程
    • MySQL 改进扩展
    • mysql_real_escape_string()

    来自微软和甲骨文

    • 微软在 PHP 脚本中防止 SQL 注入的正确方法是什么
    • 在他们阻止你之前阻止 SQL 注入攻击由 Microsoft
    • 防御 Oracle 的 SQL 注入攻击

    堆栈溢出

    • SQL 注入和 ADOdb 库!带有示例的一般 PHP 网站安全性
    • 在 PHP 中防止 SQL 注入的最佳方法
    • XKCD SQL 注入——请解释一下
    • 避免 SQL 注入攻击的最佳方法是什么?
    • 什么是 SQL 注入?
    • INSERT 上的 SQL 注入
    • 如何保护此函数免受 SQL 注入?
    • 参数真的足以防止 Sql 注入吗?
    • SQL 注入今天有风险吗?
    • SQL 注入
    • SQL 注入道德黑客
    • 此代码是否防止 SQL 注入?

    SQL 注入扫描器

    • 前 15 个 SQL 注入扫描器
    • Netsparker 社区版,免费的 SQL 注入扫描器和 XSS 扫描器
    • 11
  6. MWDB
    2015-08-10T19:50:52+08:002015-08-10T19:50:52+08:00

    存储过程不会神奇地阻止 SQL 注入,但它们确实使阻止它变得容易得多。您所要做的就是如下所示(Postgres 示例):

    CREATE OR REPLACE FUNCTION my_func (
      IN in_user_id INT 
    )
    [snip]
      SELECT user_id, name, address FROM my_table WHERE user_id = in_user_id; --BAM! SQL INJECTION IMMUNE!!
    [snip]
    

    而已!只有在通过字符串连接(即动态 SQL)形成查询时才会出现问题,即使在这些情况下,您也可以绑定!(取决于数据库。)

    如何在动态查询中避免 SQL 注入:

    第 1 步)问问自己是否真的需要动态查询。如果您只是为了设置输入而将字符串粘在一起,那么您可能做错了。(这个规则有例外——一个例外是报告对某些数据库的查询,如果你不强制它在每次执行时编译一个新查询,你可能会遇到性能问题。但是在你跳进去之前研究这个问题。 )

    步骤 2) 研究为您的特定 RDBMS 设置变量的正确方法。例如,Oracle 允许您执行以下操作(引用他们的文档):

    sql_stmt := 'UPDATE employees SET salary = salary + :1 WHERE ' 
               || v_column || ' = :2';
    EXECUTE IMMEDIATE sql_stmt USING amount, column_value; --INJECTION IMMUNE!!
    

    在这里,您仍然没有连接输入。您已安全绑定!万岁!

    如果您的数据库不支持上述内容(希望它们都不是那么糟糕,但我不会感到惊讶) - 或者如果您仍然真的必须连接您的输入(例如在“有时”报告查询的情况下我在上面暗示过),那么你必须使用适当的转义函数。不要自己写。例如 postgres 提供了 quote_literal() 函数。所以你会运行:

    sql_stmt := 'SELECT salary FROM employees WHERE name = ' || quote_literal(in_name);
    

    这样,如果 in_name 是像 '[snip] 或 1=1' (“或 1=1” 部分意味着选择所有行,允许用户看到他不应该看到的薪水!),那么 quote_literal 会节省你的屁股制作结果字符串:

    SELECT salary FROM employees WHERE name = '[snip] or 1=1'
    

    不会找到任何结果(除非您有一些名字非常奇怪的员工。)

    这就是它的要点!现在让我为您提供 Oracle 专家 Tom Kyte 关于 SQL 注入主题的经典帖子的链接,让您明白这一点:Linky

    • 2

相关问题

  • 保护数据库密码

  • PostgreSQL 中 UniProt 的生物序列

  • PostgreSQL 9.0 Replication 和 Slony-I 有什么区别?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    您如何显示在 Oracle 数据库上执行的 SQL?

    • 2 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    我可以查看在 SQL Server 数据库上运行的历史查询吗?

    • 6 个回答
  • Marko Smith

    如何在 PostgreSQL 中使用 currval() 来获取最后插入的 id?

    • 10 个回答
  • Marko Smith

    如何在 Mac OS X 上运行 psql?

    • 11 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Marko Smith

    将数组参数传递给存储过程

    • 12 个回答
  • Martin Hope
    Manuel Leduc PostgreSQL 多列唯一约束和 NULL 值 2011-12-28 01:10:21 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Stuart Blackler 什么时候应该将主键声明为非聚集的? 2011-11-11 13:31:59 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    BrunoLM Guid vs INT - 哪个更好作为主键? 2011-01-05 23:46:34 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST
  • Martin Hope
    Patrick 如何优化大型数据库的 mysqldump? 2011-01-04 13:13:48 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve