在旧的经典ASP网站中清理mysql的好方法是什么?

时间:2015-07-07 13:49:08

标签: mysql security vbscript asp-classic sql-injection

我是电子制造商的一个非常古老,非常大且写得非常糟糕的经典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。逃避斜线也无济于事,因为攻击非常复杂:

product.asp?id=999999.9+UnIoN+AlL+SeLeCt+0x393133353134353632312e39,0x393133353134353632322e39,0x393133353134353632332e39,0x393133353134353632342e39,0x393133353134353632352e39,0x393133353134353632362e39

上面的url(从访问日志中获取的任意尝试)给出了网站的回复:

Microsoft OLE DB Provider for ODBC Drivers error '80004005'

[MySQL][ODBC 5.3(w) Driver][mysqld-5.1.42-community]
The used SELECT statements have a different number of columns

/product.asp, line 14

这意味着注入完成但在这种情况下没有成功获取任何数据。然而,其他人则这样做。

该网站由数百个ASP文件组成,其中意大利面条代码总计达数千行而没有太多结构。因此,不能选择参数化查询。这项工作将是巨大的,也容易出错。

但有一件好事是代码中的所有输入参数都始终通过txtval函数传递,因此通过增加函数可以更好地完成这一操作。此外,由于所有SQL调用都是使用conn.execute(SQL)完成的,所以用例如搜索和替换它是非常简单的。 conn.execute(sanitize(SQL))所以这里也有机会对此采取行动。

鉴于这种情况,我有哪些选择来阻止或至少最小化SQL注入的风险?

非常感谢任何输入。

更新

1。 我明白参数化查询是处理问题的正确方法。我在创建网站时自己使用它。但考虑到网站的构建方式和大小,它需要1-2个月的时间来修改,测试和调试它。即使这是我们最终的结果(我怀疑),我现在需要做点什么。

2。 用html实体替换不是拼写错误。它用其html实体替换单引号。 (我没有制作代码!)

3。 在上面的具体示例中,使用CInt(id)可以解决问题,但它可以是任何东西,而不仅仅是数字输入。

更新2:

好的,我知道我不是要求正确的解决方案。我从一开始就知道。这就是为什么我写“鉴于情况”。

但是,对selectunion等mysql关键字的过滤输入至少会使其变得更好。不好,但好一点。这就是我要求的,让它变得更好的想法。

虽然我感谢您的评论,但告诉我唯一不错的选择是使用参数化查询并没有多大帮助。 因为我已经知道了:)

2 个答案:

答案 0 :(得分:4)

我不会放弃参数化查询。它们是您可以用来保护自己免受SQL注入的最佳工具。如果您的计划是替换所有这些电话:

conn.execute(SQL)

对这些电话:

conn.execute(sanitize(SQL))

然后您已经在考虑修改与SQL的每次交互(BTW,不要忘记Command.Execute()Recordset.Open(),这也可能用于运行SQL语句)。由于您已经计划更改这些调用,请考虑调用自定义函数来运行语句。例如,替换:

set rs = conn.execute(SQL)

使用:

set rs = MyExecute(SQL)

然后使用您的自定义函数来设置使用Command对象的正确参数化查询。您需要巧妙地解析此自定义函数中的SQL语句。确定where子句中的值,确定它们的类型(可能您可以查询表模式),并相应地添加参数。但它可以做到。

您也可以借此机会消毒输入。例如,使用RegExp对象快速从数字字段中删除[^0-9\.]

但是,您仍然有机会从此函数返回记录集,该记录集将用于直接将值写入页面而不首先进行HTML编码。这是一个真正的问题,特别是因为它听起来像您的网站过去已成为目标。我不会信任来自您数据库的任何数据。我在这里看到的唯一选项(不会涉及触摸每一页)就是返回一个" clean",HTML编码的记录集而不是默认的记录集。

不幸的是,你还没有走出困境。 XSS攻击可以通过QueryString参数,cookie和表单控件完成。在"修复"之后你会感到多么安全? SQL注入问题知道XSS仍然是一个非常现实的可能性吗?

我的建议?向您的主管解释困扰您网站的安全威胁,并说服他/她需要彻底审查或完全重写。在一个旧的,已经在工作的网站上投入可能看起来很多资源"但是当有人污损你的网站或截断你的数据库表时,你会希望你投入时间。

答案 1 :(得分:0)

此攻击应该只影响SQL中传递的数值。

根据相同的txtval函数是否用于数值和字符串值(以及其他类似日期),可能有也可能没有快速修复。

如果txtval仅用于数值(可能不太可能),那么您可以通过在值周围添加单引号来保护,例如:

Function txtval(data)
    txtval = replace(data,"'","'")
    txtval = "'" & trim(txtval) & "'"
End Function

如果它用于所有值类型,那么您唯一的选择可能是搜索所有代码并且:或者

1)为所有数字SQL添加单引号,例如:

SQL = "SELECT * FROM products WHERE id = '" & productid & "'"

2)创建一个新功能,仅用于清理数字值,然后更改所有查询以使用它(不是快速修复),例如:

Function numval(data)
    If IsNumeric(data) Then
        numvalue = CDbl(data)
    Else
        numvalue = 0 'or NULL?
    End If
End Function

然后更改您的查询,例如:

productid = numval(Request.QueryString("id"))
SQL = "SELECT * FROM products WHERE id = " & productid

是否有公共代码(即在包含文件中)用于打开数据库并创建示例代码中使用的conn变量?

如果是这样,那么您只需替换该代码并使用OpenCloseExecute函数(至少)创建自己的类。如果在代码中使用它们,您可能还需要其他方法。

通过这种方式,您可以有效地覆盖execute等行中的Set rs = conn.execute(SQL)

例如:

Class MyDatabase
    Private m_conn

    Public Sub Open(connString)
        Set m_conn = Server.CreateObject("ADODB.Connection")
        m_conn.Open connString
    End Sub

    Public Sub Close()
        m_conn.Close
        Set m_conn = Nothing
    End Sub

    Public Function Execute(sql)
        'Sanitize input here (sql), simple example just for this type of attack
        If InStr(sql, "UnIoN AlL SeLeCt") <> 0 Then sql = ""
        'return a RecordSet
        Set Execute = m_conn.Execute(sql)
    End Property
End Class

然后改变你的共同conn声明......(例如)

Set conn = Server.CreateObject("ADODB.Connection")

...到...

Set conn = New MyDatabase

如果你保留txtval函数,我也会更新它以逃避斜杠和单引号,例如:

Function txtval(data)
    txtval = Replace(Replace(strValue, "'", "''"), "\", "\\")
    txtval = trim(txtval)
End Function

希望这里的某些内容可能会有所帮助。