介绍 Broken Authorization(也称为破坏访问控制或特权升级)是由于用于指定用户访问特权的授权检查的无效而产生的一系列缺陷的简称。 根据用户指定的角色和相应的特权,在经过设计和实现的授权框架中允许或拒绝不同的用户访问各种内容和功能。例如,在web应用程序中,授权主要用于身份验证和会话管理。然而,跨动态系统设计授权就比较复杂了,并且可能会随着应用程序的发展而导致各系统的机制不一致:身份验证库和协议发生变化、用户角色发生变化、新用户的注册、老用户注销,用户权限删除等等。访问控制设计不仅仅是由技术决定的,而是由人决定的,因此发生错误的可能性很高,而且一直存在。 这种性质的漏洞可能会影响很多现有的web应用程序、数据库、操作系统和其他依赖于授权控制的技术基础设施中的各类软件。 影响及危害 攻击成功后黑客可能能够访问未经授权的内容,更改或删除内容,执行恶意代码,甚至完全控制管理站点。一旦遭受到这种程度的入侵,攻击的损失往往取决于被冒充的受害者账号赋予的特权范围有多大。 之前有一家名为CloudPets的玩具制造公司,他们发生的信息泄露事件就是由于上述人的为错误造成的。在这案例中,没有对授权进行控制导致了儿童语音信息的泄露,而且随后发生还发生勒索时间,这些语音信息是通过云记录的,并直接被存储在云中。 场景 从用户的角度来看,有两大类授权控件需要考虑: 横向授权控件 垂直授权控件 横向授权控件绕过 横向授权控制绕过描述了无特权用户访问拥有同等权限的其他用户帐户的行为。 例如,想象一个应用程序在方法调用下游中接受未经验证的数据以检索帐户信息。攻击者可以很容易地修改HTTP Request中的accountId参数,用一个甚至多个其他用户的帐户检索数据。 应用程序在方法调用下游中使用未经验证的数据来检索帐户信息: http://vulnerablexxx.com/user/account?accountId=7800001 http://vulnerablexxx.com/user/account?accountId=7800002 etc. 另外一个场景是不安全的直接对象引用(IDOR),指的是使用用户提供的输入直接访问对象。 垂直授权控件绕过 垂直授权控制绕过描述用户提权访问不被允许的数据或应用。也就是说,具有特定级别特权的用户越权访问了需要拥有更高级别访问权限(如管理级别访问权限)才能访问的数据或应用。 在本例中,攻击者作为一个普通用户却浏览到一个管理URL,在这里需要管理员权限才能访问管理页面。 http://vulnerablexxx.com/user/account http://vulnerablexxx.com/admin/panel 如果应用程序不检查会话用户的角色是否与访问资源所需的角色匹配,那么没有管理特权的用户将能够通过知道/猜测目标URL并浏览到它来访问页面。 如何防护 开发人员可以采取许多基本步骤来防止破坏授权控制攻击,首先对应用程序的访问控制需求进行评估,然后根据评估结果制定适当的安全策略。这应该包括一个访问控制矩阵,明确哪些类型的用户可以访问系统,以及这些用户可以或不可以做什么。使用基于角色的访问控制(RBAC)在适当的边界上强制执行。 对于web应用程序,确保在服务器端每个页面和API端点上正确执行访问控制机制。用户不应该通过请求直接访问页面或对象来访问任何未经授权的功能或信息。 代码示例(JAVA) 例如,应用程序在方法调用下游中使用未经验证的数据来检索帐户信息,导致了水平授权绕过: http://vulnerablexxx.com/user/account?accountId=7865000321http://vulnerablexxx.com/user/account?accountId=7865000321 攻击者可以修改HTTP请求中的accountId参数,伪装成任何用户的帐户,发起检索信息请求。 防护措施 Spring Spring Security在web和method级别都支持授权语义。可以限制哪些角色能够执行特定的方法,这是实施垂直授权控制的好方法: @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity security) throws Exception { http .authorizeRequests() .antMatchers("/admin/**").hasRole("ROLE_ADMIN"); } ... } 通过使用注释,安全表达式也可以用于在method级别保护业务功能。@PreAuthorize和@PostAuthorize注解支持Spring表达式语言(SpEL),并提供基于表达式的访问控制:@Service public class AdminService { @PreAuthorize("hasRole("ROLE_ADMIN")") public ListfindAllOrganizations() { ... } ... }