【问题标题】:Typical normalization security issue in web applicationsWeb 应用程序中的典型规范化安全问题
【发布时间】:2010-11-17 09:53:01
【问题描述】:

我目前遇到了一个问题,我想很多人以前都遇到过,我想知道你是如何处理的。

因此,假设您的应用上有 10.000 个用户。 (每个人都有自己的用户/密码登录来管理他的东西)。 进一步想象,您在后端有一个不断增长的标准化 SQL 表结构,其中包含以下表:用户、订单、订单位置、发票等。

因此,要显示/编辑/删除不是用户表本身的表的内容,您可能会有这样的链接,让 ypur 用户与应用程序交互。

~/Orders/EditOrder?id=12    
~/Orders/ShowOrderPosition?orderId=12&posId=443

好的,现在问题来了:

如何以“不复杂”的方式防止用户 A 访问(显示/编辑/删除)用户 B 的数据。

例子:

用户 B 调用:

~/Orders/ShowOrderPosition?orderId=12&posId=443

这是用户A的订单,所以用户B应该无权访问它。

因此,在我的代码中,我需要在每个 SQL 语句之前或之内进行 UserIdentity-check,例如:

select * from OrderPosition op, Order o, User u 
   where op.Id = :orderId 
     and op.Fk_OrderId = :orderpositionId
     and o.Id = :orderId
     and o.Fk_User = :userId

只有这样我才能确保数据属于请求用户。

要访问用户表当然会变得更加复杂,用户表连接在规范化中“埋藏”得越深(想象像付款或发票这样的表,连接到订单表...)

问题:

您的处理方法是什么,考虑:低复杂性、DRY 和性能

(希望你明白我的意思;))

【问题讨论】:

    标签: sql security web-applications normalization


    【解决方案1】:

    这有点像多租户应用程序 - 我已经沿着这条路线走,并将 ID 非规范化到所有需要这种检查的表上(在您的情况下,租户 ID 听起来像用户 ID)。

    然后,我创建了一个仅包含此字段的接口,并将其应用于模型层中需要此访问权限的所有类。

    在我的基本数据访问(存储库)类中,所有选择/更新/删除调用都经过,然后我检查该类是否属于该接口的类型,然后检查当前访问是否匹配那个ID。


    当然,这取决于您的代码的结构,以及进行这种全局更改的简单/复杂程度...

    【讨论】:

    • 正是我们所做的。 “在所有这些表上” - 对我们来说意味着典型的 Order 表而不是 OrderDetail 表,因为我们之前从未在没有加入 Order 表的情况下访问过 OrderDetail。
    • 我同意。除了导致混淆的“非规范化 ID”标签:如果需要,它不是“非规范化”。实际上,PK 应该将 user_id 作为最后一列,如果首先对表进行了规范化,而没有 Id iot 列,它就会有。这些表是非规范化的,您只是更正了它们。非规范化意味着您有一个正确规范化的数据库,并且您反转了该过程。人们需要习惯复合键。
    【解决方案2】:

    永远不要暴露 ID。

    如果你必须:加密它们。

    【讨论】:

    • 为什么不呢?当然,加密只是一点点“默默无闻的安全”
    • 是的,我在这里有稻谷...毕竟没有“真正的”安全
    • 嗯,在安全方面,每一点都很重要。不暴露 ID 可以增加一些针对未来安全漏洞的保护。例如,如果您假设 webapp 得到了适当的保护,那么不知道 ID 将使某人更难利用新发现的 OP 提到的类型的安全漏洞(当然,如果有人植根于系统或数据库,它将没有任何效果) .换句话说 - 如果有人错误地暴露了绕过常规 webapp 安全层的不安全 URL,那么不知道 ID 可能会在成功利用和触发某些蜜罐之间产生重大影响。
    【解决方案3】:

    性能

    • 为了获得最终性能,您必须将非规范化到读取行并与某些应用程序级别变量进行比较的程度,这样您就可以知道用户拥有什么样的权限(这相当快,如果您的 DAO/BAO 级别组织良好,将其插入将使其保持相对干燥和相对较低的复杂性。)注意:复杂性也是您的安全模型的一个功能,一旦您开始实施可继承的、积极的和消极的、基于角色的访问规则,那么它就不能真的很简单。

    干燥

    • 另一条途径(现在很少采用)是使用您的数据库角色来管理安全性;这可能会变得复杂,但会提供无与伦比的安全性(因为它将在数据库级别而不是应用程序级别得到保证。如果您设法将所有访问路径封装到 VIEWS 中,那么在应用程序代码级别,复杂性应该会降低,这可能需要在数据库级别进行相当多的重新调整。但是(!),可能只需对应用程序代码进行很少的更改即可实现安全模型 - 通过重命名现有表并用安全视图替换它们)

    【讨论】:

      【解决方案4】:

      不要使用你的内部 ID 列,无论是否加密,它总有一天会回来咬你。

      创建一个随机的、唯一的字符串(GUID,等等),其中包含用户和他请求的数据之间的链接。因此,对于用户 34567,而不是拥有:

      <a href="~/Orders/EditOrder?id=12">Edit order</a>
      

      在临时表中创建一条记录 {"5dsfwe8frf823jrf",34567,12} 并显示:

      <a href="~/Orders/EditOrder?txn=5dsfwe8frf823jrf">Edit order</a>
      

      当用户点击链接时,从您的临时表中获取34567,12

      字符串5dsfwe8frf823jrf 无法猜测 = 没有安全风险。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-01-04
        • 1970-01-01
        • 1970-01-01
        • 2011-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-13
        相关资源
        最近更新 更多