不安全的直接对象引用:你的 ASP.NET 应用数据是否安全? 已翻译 100%

oschina 投递于 2015/03/12 18:57 (共 24 段, 翻译完成于 04-14)
阅读 4051
收藏 40
5
加载中

介绍

作为一个在X94的航空工程师,你的老板要求你从2号楼的工程图中检索出一个特定的专利。不幸的是,进入大楼需要你出示你具有进入大楼的资格的证明,然后你迅速地以徽章的形式出示给了保安。到了十三楼,进入建筑师工程师图纸库要求通过他们的生物鉴定系统来验证你是你声称的那个人。最后在你的目的地,你提供给库管理员一串对你毫无意义的字母数字代码,但是在合适的人手上,它可以转换成哪里可以找的你需要的工程图的真实索引。

社会主义好
翻译于 2015/03/12 21:59
1

在上面的比喻中,我们可以很容易地确定适当的安全措施来保护敏感数据的访问。除了个人访问所需验证,一个附加的可能不是很明显的安全措施就是以字母数字码的形式混淆技术文档身份,并间接映射到真实的文档身份和库中的位置。   

形象地说,这个比喻是一流行的被称为“非安全的直接对象引用”的Web应用安全漏洞的解答,该漏洞在OWASP最关键漏洞Top10中排第四。但如果这就是答案的话, 你接下来自然会问“关于我Web应用的具体问题是什么且该如何去解决?”

Parser7
翻译于 2015/03/14 16:07
1

不安全的直接对象引用

我们对在我们网站上展示商品的想法都很熟悉。用户通过发起请求来查看商品详情,向他们的购物车里添加商品,或进行类似的活动。你很有可能会利用商品的ID去标识用户正在请求哪件商品的详细信息,标识添加进他们购物车的商品等等。最重要的是,这个ID很有可能是存储商品信息的数据库表的主键。如果真是这样,那么我们就拥有了一个直接对象引用。在网页上展示的某个商品(对象)被特定的ID标识,而这个ID是对数据库中相同标识的直接引用。

霍啸林
翻译于 2015/03/12 22:42
1

“说的不错,但那又如何?”是这样,在简单的商家对顾客场景下,上文所讲的情况不是什么问题。但假定这是一个金融类服务应用,比方说是你最常用的网上银行,上面有你的各个活期、定期储蓄账户和其他敏感数据,那将会怎样呢?想象一下,你在你的账户页面选择查看 ID 为 1344573490 的存款账户的详细信息:

作为一个经过身份核实的名为Mary Wiggins的用户,网站显示了针对你存款账户的信息:

我们可以直接看出这个支票户头就是我们拥有的账户,同时也能确认这是一个直接引用。但要是你决定把 accountNumber 参数从 1344573490 改为 1344573491,那将会发生什么呢?

霍啸林
翻译于 2015/03/13 11:40
1

Erin Maley,谁是Erin Maley?那不是我们。我们作为Mary Wiggins是已经明确被认证过的。我们所有所做的事情就是顺序地增加账户号直到下一个可能的值,并且我们可以看到一个不是我们所持有的账户信息。在这个例子中,我们有一个直接关联的账户,它可以被定义为系统内任何地方被标识的账户号。更进一步说,我们演习了一个潜在的问题,曝光一个直接相关的账户是简单的数据工程。

溪边九节
翻译于 2015/03/12 22:14
1

如果你自己觉得这不是直接引用惹的祸,而是身份验证上出了差错,那么你只对了一半。我们讨论不安全直接对象引用所造成的缺陷时,实际上看到了两个问题。我发现下图能够更清楚的描述这个缺陷究竟是什么:

如果不安全的直接对象引用涉及以下两方面……

  1. 泄露敏感数据

  2. 缺乏合理的访问控制

……那么我们对于弥补这个缺陷的看法是什么,以及我们应该何时采取行动?接下来,我们首先解决影响最大范围最广的问题——合理的访问控制。

霍啸林
翻译于 2015/03/13 13:34
1

多层级的访问控制

就像文章开头举的例子,多层级的访问控制是必须的。虽然我们有权进入大楼,但进入楼内某些区域需要特定的权限。当我们考虑在Web应用中保护资源时,可以使用这样的准则来达到目的。

通过路由进行访问控制

首先,当前合法用户是否有权请求资源?在我们对该用户一无所知的情况下,该如何确定当前用户可以被允许发起这个请求?因此第一步我们要做的是,在和用户交互时,通过添加访问控制来保护资源。

霍啸林
翻译于 2015/03/13 14:02
1

在ASP.NET中,用户交互通过控制器动作(controller action)完成。我们可以在ASP.NET MVC控制器上使用[Authorize]特性(attribute)来确保用户只有先经过系统核实身份才能执行控制器上的动作,而匿名用户将被拒绝。

[Authorize]
public class AccountsController : Controller
{
    [HttpGet]
    public ActionResult Details(long accountNumber)
    {
        //...

这样就确保了API无法被公开使用,根据你的ASP.NET配置,用户会被重定向到登录页面(默认行为)。[Authorize]特性通过额外的约束来匹配特定的用户和角色:

[Authorize(Roles = "Admin, Manager")]
public class AccountsController : Controller
{
    //..

[Authorize]特性除了可以被应用到控制器动作上外,还能进行更多粒度的控制。例如在控制器上放置身份验证约束,同时在控制器的不同动作上使用基于角色的访问控制。

霍啸林
翻译于 2015/03/13 14:31
1

在我们的银行账户例子中,只对用户进行身份验证是不够的,因为我们(只经过身份验证的用户)竟然能访问另一个用户的支票账户信息。对于像银行账户例子中看到的这种滥用行为,通常被称作为横向权限提升,用户可以访问其他相同等级的用户信息。然而,有权发起对某个资源的请求与拥有对实际资源的权限是完全不同的概念。

霍啸林
翻译于 2015/03/13 14:51
1

数据访问控制

因此,我们必须采取的第二层也是最重要访问控制就是,保证用户被授权访问资源。在基于角色的访问控制的情况下,这就跟确保用户属于合理的角色一样容易。如果被请求的资源只需要某个提升的权限,你可以利用之前演示的[Authorize]的Role属性来搞定。

[Authorize(Roles = "Admin")]
public class AccountsController : Controller
{
    //..

但是更多的时候,你被要求在数据层面对用户进行权限验证,以保证其有权访问所请求的资源。考虑到受许多不同因素的影响,解决方案多种多样,就上文提到的查看银行账户详情的案例,我们可以验证用户是否为其所请求账户的拥有者:

[Authorize]
public class AccountsController : Controller
{
    [HttpGet]
    public ActionResult Details(long accountNumber)
    {
        Account account = _accountRepository.Find(accountNumber);
        if (account.UserId != User.Identity.GetUserId())
        {
            return new HttpUnauthorizedResult("User is not Authorized.");
        }
        //...

记得我们已经在控制器级别使用了[Authorize]特性,所以没必要在动作级别画蛇添足。

霍啸林
翻译于 2015/03/13 15:58
1
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(12)

浔__
浔__
这不能说是asp.net的问题,是web项目都该注意的事情
Pader
Pader
什么鬼,搞那么复杂。
Glitter
Glitter
学习了~
开源中国最大五毛
开源中国最大五毛
不安全的直接对象引用

说白了不就是。。

权限控制没做好么
caltrop
caltrop
程序设计需要特别注意的地方
假正经哥哥
假正经哥哥
这个问题 在安全性要求较高的 项目上应该要注意
懒懒想睡觉

引用来自“懒懒想睡觉”的评论

看到X94莫名的停顿了一下。

引用来自“大雨夹雪”的评论

那是什么
我想这是x86它哥吗。。请无视我。。
程序员乙
程序员乙
早就注意到了修改参数的问题,从来也没找过解决方案,今天被我撞上了!
巴拉巴拉啦啦
巴拉巴拉啦啦

引用来自“懒懒想睡觉”的评论

看到X94莫名的停顿了一下。
那是什么
懒懒想睡觉
看到X94莫名的停顿了一下。
返回顶部
顶部