代码之家  ›  专栏  ›  技术社区  ›  Epaga Alex Reynolds

坏代码:为什么这么危险?[复制品]

  •  19
  • Epaga Alex Reynolds  · 技术社区  · 15 年前

    可能重复:
    Can I protect against SQL Injection by escaping single-quote and surrounding user input with single-quotes?

         String badInput = rawInput.replace("'","''");
         ResultSet rs = statement.executeQuery("SELECT * FROM records WHERE col1 = '"+badInput+"'";
    

    有什么办法可以做到吗? Bobby Tables “-像攻击这个代码?

    8 回复  |  直到 15 年前
        1
  •  10
  •   David Hedlund    15 年前

    根据解释命令的不同步骤,可能会有一些可能通过 %27 (例如)并让它作为一个单引号,通过您的替换传递未被注意到。

    但是,即使所有这些案件都能被涵盖,而且对这个问题实际上是安全的,但缺乏统一执行的能力。其他人可能会过来想补充 AND int1 = var1 并注意到您已经考虑过SQL注入,所以它们只是以您所拥有的完全相同的方式修改代码。

    String badInput = rawInput.replace("'","''");
    String badInteger = rawInteger.replace("'","''");
    ResultSet rs = statement.executeQuery("SELECT * FROM records WHERE" +
     "int1 = " + badInteger + " OR col1 = '"+badInput+"'");
    

    …只有整数才不再是你想要保护自己的引号!在这里,很明显任何事情都可能出错。所以,尽管这是一个需要有人很糟糕地实现它的问题,但我认为这是设计中最大的问题——它只覆盖了一组很小的情况。

    最好能说“以下是一个变量”。无论它包含什么,都要将其视为一个值,不要试图将其部分用作代码并执行该代码。”

        2
  •  4
  •   Chris Diver    15 年前

    在MySQL中如果 NO_BACKSLASH_ESCAPES 选项没有设置,我相信这是可能的。

    \'); DROP 
    

    或者类似的东西。您的代码将使 ' . 第一 将由反斜杠转义,第二个将关闭允许SQL注入的字符串。

    为了安全起见,我通常倾向于坚持事先准备好的声明。

        3
  •  3
  •   JeremyP    15 年前

    我最近向我哥哥介绍了准备声明。在当前项目中实现了它之后,他发现

    • 他可以摆脱所有乱七八糟的逃跑。
    • 他可以摆脱所有混乱的字符串连接
    • 他的代码运行得更快。

    为什么会有人 使用准备?

        4
  •  2
  •   rsp    15 年前

    你可以试试:

    badInput = "\\'; drop records; --";
    

    如果你的转义符恰好被设置为 '\' .

        5
  •  2
  •   James Hart    15 年前

    也许吧。取决于那是什么 replace 方法实际上是这样的,特别是当它遇到Unicode代理项对或组合标记时,以及类似地,数据库访问技术如何处理这些对。如果 代替 在char级别下工作,那么如果攻击者向您提供一个有效的高代理,后跟一个单引号字符,那么您可能会用一对单引号替换该单引号-实际上,在某个可能稍后通过编码并被解释为无效代理对的内容之后附加一个单引号,从而留下赤裸裸的单引号字符。

    也许吧。

    您是否足够了解这个replace方法的Unicode特性以及您的代码和数据库连接另一端的SQL执行引擎之间的每个中间字符串处理库?

    你觉得幸运吗?

    使用参数化查询。

        6
  •  0
  •   nsmyself    15 年前

    我不是安全专家,但不会 char() 有效地绕过你的安全措施?

    从记录表中获取所有信息

    SELECT * FROM records WHERE col1 = char(39,97,39)
    

    例如2:将信息写入没有单引号的文件

    SELECT * FROM records WHERE col1 = concat(char(39),char(97),char(100),char(109),char(105),char(110),char( 39)) into outfile concat(char(39),char(97),char(100),char(109),char(105),char(110),char( 39))
    

    来源: SQL Injection Cheat Sheet

        7
  •  0
  •   GvS    15 年前

    因为只有一个黑客发明了一种方法,以我们今天无法想到的方式绕过“替代品”。(访问数据库的一个层中的一个小错误???)

        8
  •  0
  •   Zo Has    15 年前

    这是容易发生的,并且总是会引起注射攻击。