|
1. 什么是访问控制?
访问控制是应用程序限制用户可以访问哪些资源,可以做哪些操作。在web应用的环境中,访问控制依赖于认证和会话管理:
身份验证,识别用户并确认他们就是他们所说的那个人。(they are who they say they are)
会话管理,标识由同一用户发出的后续HTTP请求。
访问控制,确定是否允许用户执行他们试图执行的操作。
有缺陷的访问控制是一个常见且通常是严重的安全漏洞。访问控制的设计和管理是一个复杂和动态的问题,它将业务、组织结构和规则约束应用于技术实现。访问控制设计决策必须由人而不是技术做出,出错的可能性很高。
从用户的角度来看,访问控制可以分为以下几类:
垂直的访问控制
水平的访问控制
上下文相关的访问控制
1.1 垂直访问控制
垂直访问控制是限制对其他类型用户不可用的敏感功能访问的机制。
通过垂直访问控制,不同类型的用户可以访问不同的应用程序功能。例如,管理员能够修改或删除任何用户的帐户,而普通用户没有访问这些操作的权限。垂直访问控制可以是安全模型的更细粒度的实现,这些安全模型旨在强制执行业务策略,如权限分离和最少权限。
1.2 水平访问控制
水平访问控制限制了同一种类型用户也只能访问自己的资源,而不能访问其他用户资源。
通过水平访问控制,不同的用户可以访问同一类型的资源子集。例如,银行应用程序将允许用户从自己的账户查看交易和支付,而不是从任何其他用户的账户。
1.3 上下文相关的访问控制
依赖上下文的访问控制基于应用程序的状态或用户与应用程序的交互来限制对功能和资源的访问。
依赖上下文的访问控制可以防止用户以错误的顺序执行操作。例如,购物网站会阻止用户在付款后修改购物车的内容。
2. 有缺陷的访问控制举例
当用户实际上可以访问某些资源或执行一些他们不应该访问的操作时,就存在缺陷的访问控制漏洞。
2.1 垂直权限提升
如果用户可以访问他们不被允许访问的功能,那么这就是垂直权限提升。例如,如果一个非管理用户实际上可以获得一个管理页面的访问权,在该页面上他们可以删除用户帐户,那么这就是垂直的权限提升。
2.1.1 无防护的功能
在最基本的情况下,当应用程序没有对敏感功能实施任何保护时,就会出现垂直权限提升。例如,虽然管理功能可以从管理员的欢迎页面链接到,从用户的欢迎页面无法链接到。但是,用户可以通过直接浏览相关的管理URL来访问管理功能。
例如,一个网站可能在以下URL中包含敏感功能:
https://insecure-website.com/admin
实际上,任何用户都可以访问该功能,而不仅仅是在用户界面中拥有该功能链接的管理用户。在某些情况下,管理URL可能在其他位置被公开,例如robots.txt文件:
https://insecure-website.com/robots.txt
即使URL没有在任何地方被公开,攻击者也可以使用字典列表来破解,获取敏感功能的位置。
在某些情况下,敏感的功能并没有得到可靠的保护,而是通过提供一个难以预测的URL来隐藏起来: 即所谓的隐蔽性安全。仅仅隐藏敏感的功能并不能提供有效的访问控制,因为用户仍然可能以各种方式发现混淆的URL。
例如,考虑一个在以下URL中托管管理功能的应用程序:
https://insecure-website.com/administrator-panel-yb556
攻击者可能无法直接猜到这一点。但是,应用程序仍然可能将URL泄漏给用户。例如,URL可能在JavaScript中公开,它基于用户的角色构造用户界面:
<script>
var isAdmin = false;
if (isAdmin) {
...
var adminPanelTag = document.createElement('a');
adminPanelTag.setAttribute('https://insecure-website.com/administrator-panel-yb556');
adminPanelTag.innerText = 'Admin panel';
...
}
</script>
如果用户是管理用户,该脚本将向用户的UI添加链接。但是,包含URL的脚本对所有用户都是可见的,而不管他们的角色是什么。
2.1.2 基于参数的访问控制
有些应用程序在登录时确定用户的访问权限或角色,然后将这些信息存储在用户可控的位置,如隐藏字段、cookie或预置查询字符串参数。应用程序根据提交的值做出后续的访问控制决策。例如:
https://insecure-website.com/login/home.jsp?admin=true
https://insecure-website.com/login/home.jsp?role=1
这种方法从根本上来说是不安全的,因为用户可以简单地修改值并获得对未授权功能的访问权,比如管理功能。
2.1.3 由于平台配置错误而导致的访问控制缺陷
一些应用程序根据用户的角色限制对特定url和HTTP方法的访问,从而在平台层实施访问控制。例如,应用程序可能会配置如下规则:
DENY: POST, /admin/deleteUser, managers
该规则禁止manager组中的用户访问URL /admin/deleteUser上的POST方法。在这种情况下,各种事情都可能出错,导致访问控制绕过。
一些应用框架支持各种非标准HTTP头,可以用于覆盖原始请求中的URL,如X-Original-URL和X-Rewrite-URL。如果一个网站使用严格的前端控制来限制基于URL的访问,但应用程序允许URL通过请求头被覆盖,那么它可能会被使用如下请求绕过访问控制:
POST / HTTP/1.1
X-Original-URL: /admin/deleteUser
...
另一种攻击与请求中使用的HTTP方法有关。上述前端应用基于URL和HTTP方法限制访问。有些网站在执行操作时允许其他HTTP请求方法。如果攻击者可以使用GET(或其他)方法对受限制的URL执行操作,那么他们就可以绕过在平台层实现的访问控制。
2.2 水平权限提升
当用户能够访问属于另一个用户的资源,而不仅是他们自己的资源时,就会出现水平权限提升。例如,一个员工应该只能访问自己的档案和工资记录,如果他也可以访问其他员工的,那么这就是水平权限提升。
水平权限提升攻击可能使用与垂直权限提升类似的利用方法。例如,用户通常可以使用如下URL访问自己的帐户页面:
https://insecure-website.com/myaccount?id=123
现在,如果攻击者将id参数值修改为另一个用户的id参数值,那么攻击者就可以访问另一个用户的帐户页面,以及相关的数据和函数。
在某些应用程序中,可利用参数不是可预测的值。例如,应用程序可以使用全局唯一标识符(GUIDs)来标识用户,而不是使用递增的数字。在这里,攻击者可能无法猜测或预测另一个用户的标识符。但是,属于其他用户的guid可能在应用程序的其他地方公开,比如用户留言或评论。
在某些情况下,应用程序检测到用户访问没有权限的资源时,会返回一个重定向到登录页面。但是,包含重定向的响应可能仍然包含一些属于目标用户的敏感数据,因此攻击仍然是成功的。
2.3 水平到垂直的权限提升
通常,水平权限提升攻击可以通过攻击更多权限的用户而转变为垂直权限提升。例如,水平升级可能允许攻击者重置或捕获属于另一个用户的密码。如果攻击者以管理用户为目标并危及他们的帐户,那么他们可以获得管理访问权,从而执行垂直权限升级。
例如,攻击者可能使用水平权限提升的参数篡改技术访问另一个用户的帐户页面:
https://insecure-website.com/myaccount?id=456
如果目标用户是应用程序管理员,则攻击者将获得对管理帐户页面的访问权。这个页面可能会公开管理员的密码,或者提供更改密码的方法,或者提供对特权功能的直接访问。
2.4 不安全对象的直接引用
不安全对象直接引用(IDOR)是访问控制漏洞的一个子类。当应用程序使用用户提供的输入直接访问对象,并且攻击者可以修改输入以获得未经授权的访问时,就会出现IDOR。虽然它只是导致访问控制被绕过的许多实现错误中的一个例子,但它因出现在OWASP 2007十大中而流行起来。
2.5 多步骤流程中的访问控制漏洞
许多网站通过一系列步骤实现重要的功能。当需要捕获各种输入或选择项时,或者当用户需要在执行操作之前检查和确认细节时,通常会这样做。例如,更新用户详细信息的管理功能可能涉及以下步骤:
加载包含特定用户详细信息的表单。
提交更改。
审核变更并确认。
有时,网站会对其中一些步骤实施严格的访问控制,但忽略其他步骤。例如,假设访问控制正确地应用于第一步和第二步,而不是第三步。实际上,网站假设用户只有在已经完成了第一步的情况下才会到达第三步,而第一步是被正确控制的。在这里,攻击者可以跳过前两步,直接使用所需的参数提交第三步的请求,从而获得对功能的未经授权访问。
2.6 基于Referer头的访问控制
有些网站基于HTTP请求中提交的Referer头进行访问控制。浏览器通常将Referer头添加到请求中,以指示请求是从哪个页面发起的。
例如,假设应用程序对/admin的访问进行了严格限制,但对于/admin/deleteUser这样的子页面,只检查Referer头。如果Referer头包含 /admin URL,则允许请求。
在这种情况下,由于Referer头可以完全由攻击者控制,他们可以伪造对敏感子页面的直接请求,提供所需的Referer头,从而获得未经授权的访问。
2.7 基于位置的访问控制
有些网站根据用户的地理位置对资源实施访问控制。例如,这适用于银行应用程序或媒体服务。这些访问控制通常可以通过使用web代理、vpn或篡改客户端的定位来绕过。
3. 如何防止访问控制漏洞
访问控制漏洞通常可以通过采取纵深防御的方法并应用以下原则来预防:
永远不要仅仅依靠对参数做混淆来进行访问控制。
除非资源是公开可访问的,否则默认拒绝访问。
尽可能使用单一的应用程序的机制来实施访问控制。
在代码级别,强制开发人员声明,每个资源允许访问的规则,并在默认情况下拒绝访问。
充分审计和测试访问控制,以确保它们按照设计工作。 |