在談水平權(quán)限和垂直權(quán)限設(shè)計(jì)之前需要清楚以下幾個(gè)概念。
權(quán)限: 其實(shí)主要是針對(duì)用戶和管理員這兩大類角色的操作,這是一種賦予的能力,對(duì)權(quán)限進(jìn)行合理分配與設(shè)計(jì),是安全設(shè)計(jì)的核心。
認(rèn)證(Authentication): 認(rèn)證的目的是為了 認(rèn)出用戶是什么人?或者說角色,能夠解決我是誰的問題。
授權(quán)(Authorization):顧名思義,是為了讓用戶能夠做什么的操作,授予用戶權(quán)限。
系統(tǒng)對(duì)某個(gè)用戶需要進(jìn)行哪些操作,對(duì)這些操作的控制就是權(quán)限控制。在一個(gè)安全的系統(tǒng)中,通過認(rèn)證來確認(rèn)主體的身份。客體是一種資源,是主體發(fā)起請(qǐng)求的對(duì)象。主體所能做什么,就是權(quán)限,權(quán)限可以細(xì)分為不同的能力,例如:在Linux文件系統(tǒng)中,將權(quán)限分為 讀、寫、執(zhí)行 三種能力。"基于角色的訪問控制"和"基于數(shù)據(jù)的訪問控制"是進(jìn)行系統(tǒng)安全設(shè)計(jì)時(shí)經(jīng)常用到的兩種控制方式。
垂直權(quán)限(功能權(quán)限)
訪問控制是建立用戶與權(quán)限之間的關(guān)系,目前常用的一種是基于RBAC模型,也稱為垂直權(quán)限。也就是用戶之間所屬的角色的權(quán)限沒有交互。
例如: 在一個(gè)論壇中,有admin、普通用戶、匿名用戶三種角色,admin有刪除、編輯、置頂帖子的權(quán)限,普通用戶有評(píng)論和瀏覽帖子的權(quán)限,匿名用戶只有瀏覽帖子的權(quán)限。目前已有 Shiro,Spring Security 等基于 RBAC 模型的成熟框架來處理功能權(quán)限管理和鑒權(quán)的問題。
垂直權(quán)限的漏洞舉例:Web應(yīng)用程序在服務(wù)端沒有做權(quán)限控制,只是在前端菜單顯示上將部分頁面隱藏了。此時(shí),惡意用戶可以猜測(cè)其他管理頁面的 URL,就可以訪問或控制其他角色擁有的數(shù)據(jù)或頁面,達(dá)到越權(quán)操作的目的,可能會(huì)使得普通用戶擁有了管理員的權(quán)限。
垂直權(quán)限漏洞是指Web應(yīng)用沒有做權(quán)限控制,或僅僅在菜單上做了權(quán)限控制,導(dǎo)致惡意用戶只要猜到了其他頁面的URL,就可以訪問或控制其他角色擁有的數(shù)據(jù)或頁面,達(dá)到權(quán)限提升的目的。
解決:對(duì)管理員所見的管理界面 URL,每次用戶訪問時(shí),都要判定該用戶是否有訪問此 URL 的權(quán)限。推薦使用成熟的權(quán)限解決方案框架。
水平權(quán)限
用戶A和用戶B可能同屬于一個(gè)角色 RoleX,但用戶 A 和用戶 B 都各自有一些私有數(shù)據(jù),正常情況下,用戶自己只能訪問自己的私有數(shù)據(jù),例如:你有刪除郵件的功能(操作權(quán)限),但只能刪除自己的郵件,不能誤刪其他人的郵件(數(shù)據(jù)權(quán)限)。但在 RBAC 模型下,系統(tǒng)只會(huì)驗(yàn)證用戶A是否屬于角色 RoleX,而不會(huì)判斷用戶A是否能訪問只屬于用戶B的數(shù)據(jù) DataB,此時(shí)就可能發(fā)生越權(quán)訪問。
這種問題,稱之為『水平權(quán)限管理問題』,又可以稱之為『基于數(shù)據(jù)的訪問控制』:相比垂直權(quán)限管理來說,水平權(quán)限問題出現(xiàn)在同一個(gè)角色上,系統(tǒng)只驗(yàn)證了能訪問數(shù)據(jù)的角色,沒有對(duì)數(shù)據(jù)的子集做細(xì)分,因此缺乏了一個(gè)用戶到數(shù)據(jù)級(jí)之間的對(duì)應(yīng)關(guān)系。對(duì)于數(shù)據(jù)的訪問控制,與業(yè)務(wù)結(jié)合的比較緊密,目前還沒有統(tǒng)一的數(shù)據(jù)級(jí)權(quán)限管理框架,一般是具體問題具體解決。
數(shù)據(jù)權(quán)限就是控制訪問數(shù)據(jù)的可見范圍,表現(xiàn)形式是:當(dāng)某用戶有操作權(quán)限時(shí)候,不代表對(duì)所有數(shù)據(jù)都有查看或管理的權(quán)限。一般表現(xiàn)為行權(quán)限和列權(quán)限:
行權(quán)限:限制用戶對(duì)某些行的訪問,例如:只能對(duì)某人、某部門的數(shù)據(jù)進(jìn)行訪問;也可以是根據(jù)數(shù)據(jù)的范圍進(jìn)行限制,例如:按合同額大小限制用戶對(duì)數(shù)據(jù)的訪問
列權(quán)限:限制用戶對(duì)某些列的訪問,例如:某些內(nèi)容的摘要可以被查閱,但詳細(xì)內(nèi)容只有 VIP 用戶能查閱
水平權(quán)限的漏洞案例:Web應(yīng)用程序接受用戶的請(qǐng)求,修改某條數(shù)據(jù)id(資源的唯一編號(hào))時(shí),而沒有判斷當(dāng)前用戶是否可以訪問該條記錄,導(dǎo)致惡意用戶可以修改本不屬于自己的數(shù)據(jù)。例如:/api/v1/blog?blogId=xxx [DELETE]
這是刪除博客內(nèi)容的url,當(dāng)用戶改變 blogId 時(shí),后端如果未校驗(yàn)博客的所屬人是否是當(dāng)前用戶,則可以刪除其他人的博客內(nèi)容。
解決方案:
用戶做出相應(yīng)動(dòng)作時(shí)(新建、刪除、更新等)時(shí),需要對(duì)其會(huì)話身份進(jìn)行驗(yàn)證(可采用Cookie機(jī)制),并且對(duì)用戶訪問的對(duì)象記錄校驗(yàn)數(shù)據(jù)權(quán)限是否ok(按業(yè)務(wù)場(chǎng)景)。
水平權(quán)限參數(shù)不要用自增值,用id加密、隨機(jī)數(shù)或GUID,但搜索引擎或攻擊者可以同樣用這個(gè)隨機(jī)數(shù)和連接去進(jìn)行操作
web層檢查發(fā)起請(qǐng)求的用戶權(quán)限,比如從session信息中獲取
數(shù)據(jù)庫表增加ownerId字段,增刪改查詢時(shí)加上其作為where語句條件(即每一個(gè)信息增加一個(gè)發(fā)布人的字段,修改的人必須與發(fā)布的人為同一個(gè)人才可以訪問)
橫向越權(quán)與縱向越權(quán)
橫向越權(quán):橫向越權(quán)指的是攻擊者嘗試訪問與他擁有相同權(quán)限的用戶的資源
縱向越權(quán):縱向越權(quán)指的是一個(gè)低級(jí)別攻擊者嘗試訪問高級(jí)別用戶的資源
如何防止橫向越權(quán)漏洞:
可通過建立用戶和可操作資源的綁定關(guān)系,用戶對(duì)任何資源進(jìn)行操作時(shí),通過該綁定關(guān)系確保該資源是屬于該用戶所有的。對(duì)請(qǐng)求中的關(guān)鍵參數(shù)進(jìn)行間接映射,避免使用原始關(guān)鍵參數(shù)名,比如使用索引1代替id值123等
如何防止縱向越權(quán)漏洞:
建議使用基于角色訪問控制機(jī)制來防止縱向越權(quán)攻擊,即預(yù)先定義不同的權(quán)限角色,為每個(gè)角色分配不同的權(quán)限,每個(gè)用戶都屬于特定的角色,即擁有固定的權(quán)限,當(dāng)用戶執(zhí)行某個(gè)動(dòng)作或產(chǎn)生某種行為時(shí),通過用戶所在的角色判定該動(dòng)作或者行為是否允許。