代码之家  ›  专栏  ›  技术社区  ›  bovium

避免在MSSQL服务器上从C代码注入SQL的算法?

  •  10
  • bovium  · 技术社区  · 15 年前

    在C.NET平台上避免SQL注入的最佳方法是什么?

    如果有,请发布一个C实现。

    2 回复  |  直到 15 年前
        1
  •  13
  •   mspmsp    15 年前

    为了安全我们能做的十件事中没有一件能做到这一切。

    1. 采用“所有数据都是邪恶的”的概念,所有数据,甚至存储在数据库或文件系统中的数据都是可疑的。不仅仅是来自防火墙外应用程序的数据输入,如查询字符串、表单字段、cookie等。任何东西都可以用来破坏系统。

    2. 不要依赖于JavaScript或HTML字段长度的客户端验证,甚至 使用客户端验证的服务器端Web API。使用它来提高可用性,但不要把它作为唯一的保护。了解API提供的验证程序(如NET)是如何工作的。别以为他们是理所当然的。他们周围有很多路。

    3. 进行正匹配以在数据进入时捕获所有数据。如果数据与正则表达式的字符范围匹配,那么就可以了。这不允许在我们的数据库中使用奇怪的Unicode字符,因为这些字符可能会意外地限定SQL中的某些内容,或者造成其他问题,如同形XSS/网络钓鱼攻击。相反,负匹配需要所有坏字符的列表,它们似乎一直在增长。这是一个糟糕的方法。正匹配更好。我们拒绝坏数据,不清理或逃避它。

    4. 如果可能,考虑使用“更新”、“删除”、“删除”、“选择”、“更改”等筛选、标记或捕获字符串数据。考虑到字符串的性质,这可能是不可能的。1212 Lemondrop ln、“Waltersburg,PA”和“Table Rock,NE”是有效的地址字段。每天对所有表数据进行一次扫描,查找与这些字段匹配的字段,可能会发现延迟的攻击或漏洞。此外,日志记录、IP禁止、电子邮件警报等也可以在数据传入时使用。

    5. 尽可能使用存储过程和/或参数化查询。避免在数据库客户端代码和SQL中使用动态SQL。(避免在存储过程中使用带有外部节的动态代码的exec语句!!!!)参数化将转义字符串终止符,如撇号、捕获字段长度和类型检查。我们不能总是依赖提供参数化的API,但是它们是由比我们大多数人更了解数据库特性的人编写的。

    6. 确保世界可读/可执行的Web目录中没有杂散代码。如果它不是活动站点的一部分,请将其存档到安全的地方并从公共视图中删除。未使用的存储过程也是如此。

    7. 了解数据库API的最新信息。在某些API中执行SQL语句的某些方法不如其他方法安全。

    8. 使用单向加密安全存储密码。这样,一个包含用户名和密码的表转储应该仍然可以让人远离。

    9. 用所有常见的方法加固服务器。例如,在可能的情况下,对数据库表赋予最少的权限。将Web服务器数据库帐户的访问权限严格限制在相关表中。尽可能使用只读。创建多个帐户,在公共和内部/受信任流量的访问权限之间创建一个分隔。

    10. 优雅地捕捉错误。这适用于所有代码,而不仅仅是使用数据库的代码。但是,SQL注入攻击特别依赖于错误消息,因此需要尽可能多地对数据库进行隐藏,以防公开。始终以普通方式编写处理异常或空数据集的代码,以便尽可能少地显示我们正在使用的数据库类型、表中的字段以及我们正在运行的查询类型。在服务器上记录错误。即使在非数据库代码中,最好对第三方组件、文件文件夹结构、我们可能正在运行的其他服务等保持沉默。尽可能少地向恶意用户提供信息是保持他们不了解的关键。

    并且11,总是重新访问/修改这个列表。始终保持最新。积极主动。把它作为一个预先的优先事项和要求,而不是事后的考虑。

        2
  •  31
  •   Greg Beech    15 年前

    不需要任何算法-只是不要使用字符串连接来构建SQL语句。请改用sqlcommand.parameters集合。这将执行所有必要的值转义(例如替换 ' 具有 '' )并确保该命令是安全的,因为其他人(如微软)已经完成了所有测试。

    例如,调用存储过程:

    using (var connection = new SqlConnection("..."))
    using (var command = new SqlCommand("MySprocName", connection))
    {
        command.CommandType = CommandType.StoredProcedure;
        command.Parameters.AddWithValue("@Param1", param1Value);
        return command.ExecuteReader();
    }
    

    这种技术也适用于内联SQL语句,例如

    var sql = "SELECT * FROM MyTable WHERE MyColumn = @Param1";
    using (var connection = new SqlConnection("..."))
    using (var command = new SqlCommand(sql, connection))
    {
        command.Parameters.AddWithValue("@Param1", param1Value);
        return command.ExecuteReader();
    }