【发布时间】:2015-07-07 13:49:08
【问题描述】:
我是一家电子制造商的一个非常古老、非常大且写得非常糟糕的经典 ASP 网站的维护者(但幸好不是创建者)。
安全是个笑话。这是在输入 MySQL 之前对输入进行清理的唯一方法:
Function txtval(data)
txtval = replace(data,"'","'")
txtval = trim(txtval)
End Function
productid = txtval(Request.QueryString("id"))
SQL = "SELECT * FROM products WHERE id = " & productid
Set rs = conn.execute(SQL)
因此,该网站不幸(但也许并不令人惊讶)成为 SQL 注入攻击的受害者,其中一些攻击成功了。
上面采取的简单方法是远远不够的。也没有使用Server.HTMLEncode。由于攻击非常复杂,因此转义斜线也无济于事:
上面的 url(从访问日志中获取的任意尝试)给出了来自站点的以下响应:
用于 ODBC 驱动程序的 Microsoft OLE DB 提供程序错误“80004005” [MySQL][ODBC 5.3(w) 驱动程序][mysqld-5.1.42-community] 使用的 SELECT 语句具有不同的列数 /product.asp,第 14 行这意味着注入成功了,但在这种情况下没有成功获取任何数据。但是,其他人会这样做。
该站点由数百个带有意大利面条代码的 ASP 文件组成,代码总计数千行,没有太多结构。因此,它不是参数化查询的选择。工作量很大,而且容易出错。
一件好事是代码中的所有输入参数始终通过txtval 函数传递,所以这里有机会通过扩充函数来做得更好。此外,由于所有 SQL 调用都是使用 conn.execute(SQL) 完成的,因此搜索和替换例如非常简单。 conn.execute(sanitize(SQL)) 所以这里也有机会做点什么。
鉴于这种情况,我有哪些选择可以防止或至少将 SQL 注入的风险降到最低?
非常感谢任何意见。
更新:
1。 我明白参数化查询是处理问题的正确方法。我在创建网站时自己使用它。但考虑到网站的搭建方式和规模,修改、测试和调试需要1-2个月的时间。即使这就是我们最终的结果(我对此表示怀疑),我现在也需要做点什么。
2。 用 html 实体替换不是错字。它用它的 html 实体替换单引号。 (代码不是我写的!)
3。 在上面的具体示例中,使用 CInt(id) 可以解决问题,但它可以是任何东西,而不仅仅是数字输入。
更新 2:
好的,我知道我不是在寻求正确的解决方案。我从一开始就知道这一点。这就是我写“鉴于情况”的原因。
但是,过滤 mysql 关键字(如 select、union 等)的输入至少会使它变得更好。不好,但好一点。这就是我所要求的,让它变得更好一点的想法。
虽然我很欣赏您的 cmets,但告诉我唯一好的选择是使用参数化查询并没有真正的帮助。 因为我已经知道了:)
【问题讨论】:
-
我知道您说过它们不是一个选项,但请理解这是保护此类查询免受 SQL 注入攻击的基础之一:参数化查询,例如“从 id 的产品中选择 * =@Id",然后在执行之前在代码中构建/添加 ID 参数。我想,它不会让你变得比现在更糟糕。随处手动添加清理代码不会减少劳动强度或不易出错。
-
咬紧牙关,正确修复网站。从长远来看,创可贴解决方案永远不会奏效......
-
没有“快速修复”,就像@DavidW 说的那样,您尝试的任何解决方法都可能需要很长时间才能实施,而且不会那么健壮。
-
你的困境应该被用作广告,说明为什么使用参数化查询应该是一个起点,为什么在开发过程中需要关注安全性,而不是需要关注的问题稍后解决,最后附上。很多次我都看到关于“我现在不关心 sql 注入”或“我是唯一的用户”或“这只是一个学习项目”的回应。快进到你所处的困境:“参数化查询不是一个选择——工作量很大”)。
-
你不会找到任何“临时快速修复”来处理大量的错误/不安全代码。这就是重点。也许真正的解决方案是加速重写并将目前用于不存在的“快速修复”的资源投入到应用程序的“新”版本中正确编写的数据库代码中。
标签: mysql security vbscript asp-classic sql-injection