【问题标题】:Are sql injection attacks only a threat on a page that has a form?sql 注入攻击是否只是对具有表单的页面的威胁?
【发布时间】:2009-11-11 17:56:57
【问题描述】:

我知道这是一个简单的问题,但在我所阅读的所有内容中,我从未见过具体说明这一点。

如果在页面上做查询,是否需要担心 SQL 注入攻击?还是只有当您要求用户输入时才会出现问题?

谢谢!

【问题讨论】:

  • 我看到的大多数答案都是关于用户输入的。那将需要某种形式,不是吗?我的问题是,如果我不收集页面上的用户输入,我是否需要担心注入攻击?
  • 是的。 “用户输入”实际上应该是“作为请求的一部分进入您的服务器的任何内容”。我已经演示了基于更改 UserAgent 请求标头的值的攻击;-)
  • 即使它不可能成为攻击的源头,它仍然可以成为注入攻击的目标。其他人拥有您的网页的严重程度取决于您的网站。

标签: sql security web-applications sql-injection


【解决方案1】:

您无需用户输入即可遭受 SQL 注入攻击。

假设您有一个使用如下 URL 调用的产品页面:

product.aspx?ID=123

在您的代码中,您构建了一个查询,如下所示:

string sql = "SELECT * FROM Products WHERE ID = " + Request.Querystring["ID"];

有人可以通过此网址调用您的页面:

product.aspx?ID=123;DROP Table Students;

然后 bam,你刚刚被拥有了。

除了可以通过用户、查询字符串、帖子、cookie、浏览器变量等传递的任何内容之外。我认为始终使用参数只是一个好习惯,即使您的代码中有文字。例如:

if(SomeCondition)
{
    sql = "Select * from myTable where someCol = 'foo'";
}
else
{
    sql = "Select * from myTable where someCol = 'bar'";
}

这可能是注入安全的,但您的 RDBMS 会将它们缓存为两个不同的查询。 如果您将其修改为:

sql = "Select * from myTable where someCol = @myParam";
if(SomeCondition)
{
   myCommand.Parameters.Add("@myParam").value = "foo";
}
else
{
   myCommand.Parameters.Add("@myParam").value = "bar";
}

您获得了相同的结果,但 RDBMS 只会将其缓存为一个查询,在运行时替换参数。我使用它作为一个经验法则,总是使用参数化查询,只是为了保持一致,更不用说缓存的轻微改进了。

【讨论】:

  • 您必须记住在将查询发送到数据库之前对其进行预编译,并且它必须在同一个打开的连接上。
  • 好答案。 @Middletone:对于 SQL Server,没有预编译和计划之类的东西是独立于连接的。
  • 我的经验是,除非您预编译一个语句,否则它不会保存在内存中,除非它是存储过程的一部分。我在查询方面做了很多工作,这是一个一致的模式。在 asp.net 代码中,预编译语句对查询执行时间有很大的影响。
  • Middletone,你说的是什么数据库服务器?
  • @Middletone:如果你有信心,请向我演示如何预编译 SQL Server 语句。
【解决方案2】:

SQL 注入是由未经清理的数据引起的。您应该始终始终清理进入数据库的数据。不仅用于 SQL 注入,还用于使您的应用正常运行。

例如,某些系统不会使用我的名字,因为它有一个 ' 字符,并且它们的数据库没有经过清理。我没有输入我的名字,我的名字来自另一个数据库。没关系——应该对数据进行清理。

【讨论】:

    【解决方案3】:

    SQL 注入 sn-ps 也可以从使用 GET 方法传入的 QueryString(又名“URL 参数”)进来。

    正如 Billy O'Neal [单引号 ;-) ] 所暗示的,任何不是程序(或其非常受信任的后端)固有的数据都应该被“清理”。 消毒这个词似乎暗示了一个复杂的过程,但实际上它通常意味着:
    [可能因您的特定 SQL 服务器品牌而异]

    • 删除(或转义)嵌入在字符串中的单引号字符
    • 从字符串观察超出了基础 SQL 列的长度(特别是如果这样的长度很长)

    HTTP 表单将成为 SQL 注入 sn-ps 的唯一来源的一个可能原因是,一个有效的建议是确保从请求的表单中获取用户提供的提交文本。一些 Web 应用程序框架将 HTTP 请求公开为一个对象,默认情况下,该对象公开来自 QueryString、来自表单甚至来自 cookie 的所有键值对,可从单个哈希访问。虽然这对于有时从表单获取信息、有时从查询字符串获取信息的应用程序来说是实用的,但这可以促进潜在注入器的工作,因为创建 URL 比创建表单更容易。 (但使用适当的工具,也可以伪造一个 POST 请求......)

    【讨论】:

      【解决方案4】:

      不,还有其他几种情况。例如,您可能将一些变量作为查询字符串传递到 php 页面。 “用户”可以修改该字符串以包含一些狡猾的脚本。

      http://en.wikipedia.org/wiki/SQL_injection 包含大量关于漏洞类型以及如何有效应对它们的部分。

      【讨论】:

        【解决方案5】:

        总而言之 - SQL 查询中使用的任何类型的用户输入都是 sql 注入的潜在目标

        【讨论】:

          【解决方案6】:

          还要考虑防止cross-site-scripting ("XSS")

          【讨论】:

            【解决方案7】:

            如果您使用来自浏览器的任何类型的数据,SQL 注入是可能的。它可以是表单数据、查询字符串数据、cookie 值,甚至是请求标头中的数据。

            显而易见且简单的方法是表单数据和查询字符串数据,但来自浏览器的任何内容都可能被欺骗。

            【讨论】:

              【解决方案8】:

              代码从 HTTP 请求中获取的任何输入都可以是 SQL 注入向量:

              • POST/PUT 内容
              • 获取网址参数
              • Cookie

              在更高的级别上,这些显示为 $_REQUEST 或 Page.Request 值、会话变量,这一切都取决于许多因素。但归根结底,只是 POST 表单。虽然可能最流行的向量是表单 POST 内容和 GET URL 变量。

              【讨论】:

                【解决方案9】:

                当用户可以修改查询参数的值时,它就可能成为威胁。

                【讨论】:

                  【解决方案10】:

                  如果您在页面上显示的数据来自用户提交的数据,则在这种情况下您需要担心cross site scripting (XSS) 攻击。

                  转义输入,过滤器输出

                  【讨论】:

                    【解决方案11】:

                    我担心你永远不应该相信这些变量:$_POST、$_GET、$_REQUEST、$_COOKIE 甚至 $_SERVER 都可能包含恶意代码。因此,请始终确保插入的数据符合您的期望。 例如,作为验证电子邮件地址的额外偏执措施,您可以使用 md5 加密电子邮件地址,如下所示:

                    "SELECT username FROM users WHERE MD5(email)='" . md5($_POST['email']) . "' AND active=1"
                    

                    【讨论】:

                      【解决方案12】:

                      作为一般规则,应始终使用参数化查询。

                      1. 它可以防止对您的数据库执行恶意用户输入(SQL 注入攻击)。 [您还应该进行用户输入验证,以确保页面上不会呈现恶意代码,并且可以针对您的服务器运行 JavaScript。]
                      2. 它使您能够重复使用您的查询。
                      3. 您可以预编译查询。
                      4. 它可以组织您的输入并使其更具可读性。您可能希望在多个位置使用相同的参数。
                      5. 对日期、字符串等不同的数据类型有更好的支持。使用参数化查询时,您不会遇到奇怪字符的问题。

                      在我的用例中,我总是生成基于参数的查询。我有一个总是编译它们的包装器,这样如果第二个查询在同一个请求路径中执行,它会在同一个连接上运行得更快。这需要相当多的工作来设置,但值得在任何中型到企业级系统中获得性能提升。

                      【讨论】:

                        【解决方案13】:

                        我同意参数化是最好的方法。

                        作为替代方案(可能更容易在您的代码中进行改造,至少最初是这样)将字符串中的单引号加倍将防止 SQL 注入。

                        以尼尔 N 为例:

                        sql = "Select * From Products Where ID = " + Request.Querystring["ID"]; 
                        

                        将变量包裹在双引号的函数中,并用单引号包裹变量。

                        sql = "Select * From Products Where ID = " 
                            + fnSQLSafeParam(Request.Querystring["ID"]);
                        

                        函数类似于(VBscript 示例):

                        Function fnSQLSafeParam(ByVal strStr)
                          If IsNull(strStr) or IsEmpty(strStr) then strStr = ""
                          fnSQLSafeParam = "'" & replace(Trim(CStr(strStr)), "'", "''") & "'"
                        End Function
                        

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2011-02-24
                          • 2019-07-10
                          • 1970-01-01
                          • 2015-04-23
                          • 2016-11-05
                          • 2016-01-02
                          • 2012-08-01
                          • 2011-03-27
                          相关资源
                          最近更新 更多