×

Loading...
Ad by
  • 推荐 OXIO 加拿大高速网络,最低月费仅$40. 使用推荐码 RCR37MB 可获得一个月的免费服务
Ad by
  • 推荐 OXIO 加拿大高速网络,最低月费仅$40. 使用推荐码 RCR37MB 可获得一个月的免费服务

俺也贡献一下吧。补充一个,不仅限于SP,适合所有Web Application中的query。

输入的参数永远当作字串类型引用。

简单例子:

错误
SELECT id, name FROM product WHERE id = %para%

正确
SELECT id, name FROM product WHERE id = '%para%'

正常情况下%para%是一个整数,比如101,实际query是
SELECT id, name FROM product WHERE id = '101'
没有问题。

恶意攻击情况下,%para%可能是一个SQL命令,比方0 DELETE TABLE product

错误方法下,query成为
SELECT id, name FROM product WHERE id = 0 DELETE TABLE product

正确方法下,query成为
SELECT id, name FROM product WHERE id = '0 DELETE TABLE product'
Query出错,不会被执行。
Report

Replies, comments and Discussions:

  • 工作学习 / 专业技术讨论 / 存储过程(stored procedure)在web应用中如何避免攻击
    本文发表在 rolia.net 枫下论坛前几天有个关于存储过程(stored procedure)在web应用中的讨论。有篇文章这样反驳sp的安全性:
    http://www.tonymarston.net/php-mysql/stored-procedures-are-evil.html
    It is also said that stored procedures are more secure because they prevent SQL injection attacks. This argument is false for the simple reason that it is possible to have a stored procedure which concatenates strings together and therefore open itself up to sql injection attacks (generally seen in systems which use procedures and have to offer some sort of general search routine), while the use of parameterized queries removes this vulnerability as no value can end up as being part of the actually query string.

    幸亏不是每个DB程序员都这样蠢。这里是一些避免攻击应该掌握的原则,欢迎大家补充!
    1.输入的参数只能用作绑定变量;永远不要用输入的东西拼装动态SQL。这样就避免了SQL注入攻击。这个原则哪怕不用存储过程也应该坚持。
    2.只给予AS连接DB用户有限的权限。除了执行某些存储过程之外,回收大部分表的读写权限。最多保留某些不重要的表和视图的读权限。这样子注入的SQL也执行不了。
    3.对于重要的操作在SP入口处再次验证用户身份更多精彩文章及讨论,请光临枫下论坛 rolia.net
    • good
    • 俺也贡献一下吧。补充一个,不仅限于SP,适合所有Web Application中的query。
      输入的参数永远当作字串类型引用。

      简单例子:

      错误
      SELECT id, name FROM product WHERE id = %para%

      正确
      SELECT id, name FROM product WHERE id = '%para%'

      正常情况下%para%是一个整数,比如101,实际query是
      SELECT id, name FROM product WHERE id = '101'
      没有问题。

      恶意攻击情况下,%para%可能是一个SQL命令,比方0 DELETE TABLE product

      错误方法下,query成为
      SELECT id, name FROM product WHERE id = 0 DELETE TABLE product

      正确方法下,query成为
      SELECT id, name FROM product WHERE id = '0 DELETE TABLE product'
      Query出错,不会被执行。
      • 开始抬杠
        我看不太懂语法,但你的正确方法似乎没有用绑定变量,还是在拼装SQL.

        假如攻击者穿入这个东西呢?

        0' DELETE TABLE product WHERE ID = '123

        那么你拼装后变成:

        SELECT id, name FROM product WHERE id = '0' DELETE TABLE product WHERE ID = '123'
        • 这single quote自打到了服务器开始就应该过滤掉了。
        • 现在大部分AS在准备query的时候,都会自动对变量中的特殊字符qualify。你的例子最后送到DB的query是:SELECT id, name FROM product WHERE id = '0'' DELETE TABLE product WHERE ID = ''123' 。所以DB仍旧是安全的。
          是的,我说的是拼装SQL,这也是大多数Web Application用到query的情况。该不会一个简单的SELECT也要通过SP来实现吧?
          • 拼装SQL就有可能注入。也许还有什么东西没有过滤掉但现在没考虑到。而且你交给SQL引擎的全是不一样的SQL,它会不停地解释、生成同样的计划,浪费资源。用绑定变量 SELECT ... FROM ... WHERE id = ? 以后只要传入不同的变量,DB就知道这是同一个SQL没有必要再解释。
            • 问题是,难道要把Web Application(WA)里面的所有Query都用一个对应的SP来取代么?High Traffic WA对DB的访问应该都用简单query,我不认为会多花多少系统资源来”不停地解释、生成同样的计划“。
              • 我第一点已经说了:哪怕不用存储过程也要坚持用绑定变量。SQL引擎不能辨认 WHERE ID=123 和 WHERE ID=456,它会认为是两个不同SQL。试想如果几万个用户同时在线会产生多少类似的SQL.如果你不想用垃圾把SQL CACHE塞满就必须用绑定变量。请GOOGLE bind variable
              • bind variable 又叫 Placeholders,这下该听说过了吧。B大虾有些言论让我大跌眼镜……跑一个你的例子,让你们DBA检查一下SQL的CACHE,看是不是在重复地解释。
                • 你真的是来抬杠的呀。这里是在讨论performance还是在讨论sql injection的问题?我也没有否认DB Engine会”重复地解释“呀。我说的是,对于简单query,用bind variable不见得能有什么performance gain。这是就MS SQL来说的。
                  如果一定要用bind variable,对于MS SQL来说实际上还是当SP来处理,省了Bind Variable的一点点好处,但多了处理SP的开销。还要定义变量,给变量赋值。这些都有开销。不知道Oracle是如何处理的。另外,你好好狗一下,bind variable用的比较多的还是Oracle和Oracle developer。这本不是新的东西,不知道为什么其它vendor不跟进,应该是有理由的吧。
                  • 拼装SQL就会有sql injection问题,虽然我一下子举不出例子(咱也不是黑客出身)。performance是附带谈到的。我不是没有狗过的,SQL SERVER仍然应该用BIND VARIABLE(或PLACEHOLDER),为了安全和性能。如果我是你的话,我会搞几个压力测试来比较一下结果。
                    • 用我那方法,绝对可以杜绝sql injection。那是经过实际检验的。
                      • Relying on application server? You must be kidding. Do you mind tell us which application server you are using and what is the data access layer?
                        • You must be kidding.
    • Always replace single quote with double single quote of parameters user entered is efficient approach to prevent from SQL injection and attack.
      • 那要是客户要求输入的数据确实有单引号(而且是合法数据,比如非英语姓名拼写)怎么办?你不能私自篡改数据。用绑定变量就可以把这个数据正确传入了。
        • I do not know SQL server... is there bind variable in SQL Server too?
          • 随便google一下就知道了:
            http://www.akadia.com/services/ora_bind_variables.html
            Bind variables - The key to application performance

            ...Support for bind variables isn't just limited to Oracle - it's common to other RDBMS platforms such as Microsoft SQL Server...
            • great! thanks for infoing me this
        • In SQL server, if there is single quote in user's input and you don't replace it with two quote, it causes sql injection. Actually the first quote escape the second one.
        • BTW, how do you enter quote in Oracle?
          • 如果写在常量里就是两个单引号。如果从变量传进来,我并不需要escape.为了安全和提高性能请坚持使用绑定变量,哪怕不用存储过程。
        • auto qualified by AS. #3868366