http://secappdev.org/handouts/2012/Jim%20Manico%20%26%20%20Eoin%20Keary/Final%20-%20Access%20Control%20Module%20v4.1.pdf
什么是access control/authorization?
authorization is the process where a system determines if a specific user has access to a particular resource.
在上面的定义中有几个关键词: process, specific user, particular resource
authorization的目的是ensure that a user only access system functionality to which he is entitled.也就是说让用户具有已经赋予他的权利来访问他可以访问的资源
凡是网站有用户就有访问控制的需求,传统上基于RBAC(Role based access control)可以实现粗放的访问控制,但是RBAC也有非常明显的问题:就是控制粒度太大,无法动态对某个资源来实现控制,要么可以访问,要么不能访问,而现实中很多情况下是:可以读访问部分资源,读写自己创建的资源,这种情况下RBAC就无能为力了。总的来说,RBAC无法解决水平访问控制的问题(horizontal access control)
对访问控制的恶意攻击
1. Vertical access control attacks
一个低权限的用户访问高权限功能(a standard user accessing administration functionality)
2. Horizontal access control attacks
相同角色的用户去访问其他用户的私有数据(same role, but accessing another user‘s private data)
3. Business logic access control attacks
abuse of workflow
访问控制的issues
1. 需要application仅实现了一个"all or nother" approach:一旦authenticated那么所有用户都有相同的权限
2. authorization logic通常依赖于默认环境是安全的并且会假设:用户不会找到unlinked functionality或者说是hidden path/functionality, 用户不会找到并且篡改那些隐藏的客户端参数(比如:hidden form filed, cookies等)
3. 在应用中一旦有了多个permission level/roles这总会增加permission set间权限冲突可能从而使得权限系统工作紊乱
典型的权限控制不好的实现实践
1. 在application code中hard-coded role check
void editProfile(User u, EditUser eu) { if (u.isManager()) { editUser(eu) } }
带来的问题: what needs to occur in order to change the access control policy of this feature?
a. 使得证明我们已经实现了应用的授权策略非常困难
b. 任何时候访问控制策略policy需要变更,那么就必须修改代码
c. 脆弱而易于犯错误
d. 无法实现自动化,需要在每一个application feature上来做hand-coded
2. 缺乏集中的访问控制逻辑
看看下面的分散参数控制情况:
http://example.com/buy?action=chooseDataPackage
http://example.com/buy?action=customizePackage
http://example.com/buy?action=makePayment
http://example.com/buy?action=downloadData
攻击者可以通过concurrency就可能获取不应有的权限
3. 不可信数据却驱动着访问控制决策
a. 永远不要信任从客户端来的数据做访问控制决策
b. 永远不要在javascript中做访问控制决策
c. 永远不要只基于以下信息来做访问控制决策:
c.1: hidden fields
c.2: cookie value
c.3: form parameters
c.4: url parameters
d. 永远不要依赖于客户端发送过来参数值的顺序来做决策
4. 访问控制遵循了"open by default”的原则,这将开放不必要的权限
很多administrative interfaces仅仅需要一个密码就授权了。共享帐号而又缺乏auditing和logging会导致区分好人和坏人非常困难。admin interface往往不如user-level interface那么安全因为总是假设administrators是值得信任的用户
5. 缺乏解决水平访问控制的标准方法
6. access contro逻辑必须手工地加到每一个endpoin中
攻击访问控制系统
1. elevation of privileges
2. 披露敏感信息: 比如admin-level的帐号往往能够访问一个用户的私密信息
3. 数据篡改: 特权级别往往对于那些可以查看数据的用户和可以修改用户的数据不加以区分
testing for broken access control
试图作为一个匿名用户或者一个普通用户来访问admin components/functions:修改html hidden form fields, 测试web accessible directory structure for names,比如admin,administrator,manager等等:即直接访问那些受限的资源
试图摸清administrator是如何被authenticated的。我们需要确保充足的鉴权渠道被使用,甚至可以加上普通密码加上注册手机得到的临时密码来鉴权
对于每一个user role,需要确保适当的pages或者components可以被那个role所访问
Access control best practices:
1. 通过role based access control来对用户assign permissions以实现vertical access control requirements;
2. 通过data-contextual access control在特定data items上下文环境中授权给特定用户以实现horizontal access control requirements
3. 避免直接对单个用户来做assign permissions动作
4. 对应用的所有pages都执行一致的authorization checking routings;
5. 如果可能,在最后应用apply DENY, case-by-case来 issue allow privilege
6. 实现一个集中的access control mechanism
7. code to the activity(permission), not the role
8. 集中access control logic
9. 将access control作为一个filter或者说middleware
10. Deny by default, fail securely
11. 将相同的核心授权逻辑应用到presentation(view视图)层和server-side access-control decisions中
12. server-side受信数据应该作为驱动access-control的数据源头
13. 可以在实时运行时修改一个用户的role
14. build grouping capability for users and permissions
Code to the activity/permission
// 不再像下面的 if ((user.isManager() || user.isAdministrator() || user.isEditor() || user.isUser() && user.id() != 1132)) { //execute action} // 而应该像这样: if (AC.hasAccess(ARTICLE_EDIT)) { //execute activity}
code it once, never needs to change again
implies policy is persisted/centralized in some way
requires more design/work up front to get right
定义一个centralized ACL Controller:定义一个集中的ACL Controller
ACLService.isAuthorized(ACTION_CONSTANT) ACLService.assertAuthorized(ACTION_CONSTANT)
所有的access control decision都通过这些简单的api来实现
集中的授权逻辑驱动policy behavir and persistence
可能包含data-driven access control policy information
如何使用一个centralized access controller
1. 在视图presntation layer:
if (isAuthorized(VIEW_LOG_PANEL)){ <h2>Here are the logs</h2> <%=getLogs();%/> }
2. 在控制层controller中:
try (assertAuthorized(DELETE_USER)){ deleteUser(); }
永远在server端验证policy:
1. 将user id verification放在session中;
2. 从受信任的server端数据源头来加载entitlements
3. 对所有的requests都强制authorization check: 包括js文件发起的request,mage, ajax, flash request都要强制authorization check, 最好通过一个通用的middleware来实现这个强制鉴权功能