第7章 成員資格、授權和安全性 7.1 安全性 ASP.NET MVC 提供了許多內置的保護機制(預設利用 HTML 輔助方法和Razor 語法進行 HTML編碼以及請求驗證等功能特性,以及通過基架構建的控制器白名單表單元素來防止重覆提交攻擊) 永遠不要相信用戶提交的任何數據。 實際的例子 每次渲染 ...
第7章 成員資格、授權和安全性
7.1 安全性
ASP.NET MVC 提供了許多內置的保護機制(預設利用 HTML 輔助方法和Razor 語法進行 HTML編碼以及請求驗證等功能特性,以及通過基架構建的控制器白名單表單元素來防止重覆提交攻擊)
永遠不要相信用戶提交的任何數據。
實際的例子
- 每次渲染用戶提交的數據的時候對其進行編碼。
- 考慮好網站哪些部分允許用戶匿名訪問,哪些部分需要認證訪問。
- 不要試圖自己凈化用戶的HTML 輸入,否則就會失敗。
- 在不需要通過客戶端腳本訪問cookie時,使用HTTP-only cookie
- 請記住外部輸入不只是顯式的表單域。
- 建議使用AntiXSS 編碼器。
黑客、解密高手、垃圾郵件發送者、病毒、惡意軟體——它們都想進入計算讀查看裡面的數據。在閱讀本段內容時,我們的電子郵箱很可能已經轉發了很多封電子郵件。我們的埠遭到了掃描,而一個自動化的蠕蟲病毒很有可能正在嘗試通過多種操作系統漏洞找到進入PC的途徑。由於這些攻擊都是自動的,因此它們在不斷地探索,尋找一個開放的系統。
應用程式的構建基於這樣一種假設,即只有特定用戶才能執行某些操作,而其它用戶則不能執行這些操作。
7.2 使用Authorize 特性登錄
保護應用程式安全的第一步,同時也是最簡單的一步,就是要求用戶只有登錄系統才能訪問應用程式的特定部分。 Authorize Attribute 是ASP.NET MVC 自帶的預設授權過濾器,可用來限制用戶對操作方法的訪問。
Tips:身份驗證和授權
身份驗證是指通過某種形式的登錄機制(包括用戶名/密碼、OpenID、OAuth 等說明自已身份的項)來核實用戶身份。
授權驗證是用來核實登錄站點的用戶是否在他們的許可權內執行操作。這通常使用一些基於聲明的系統來實現。
Authorize 特性不帶任何參數,只要求用戶以某種角色登錄網站。它禁止匿名訪問。
7.2.1 保護控制器操作
實現安全性的一個好方法是,始終使安全性檢查儘可能的貼近要保護的對象。可能有其它更高層的檢查,但始終都要確保實際資源的安全。
7.2.2 Authorize 特性在表單身份驗證和AccountController 控制器中的用法
基本驗證信息
IPrincipal user=httpContext.User; if(!user.Identity.IsAuthenticated) {return false;} if(_usersSplit.Length>0&&!_usersSplit.Contains(user.Identity.Name,StringComparer.OrdinalIgnoreCase)) {return false;} if(_rolesSplit.Length>0&&!_rolesSplit.Any(user.IsInRole)) {return false;} return true;
如果用戶身份驗證失敗,就會返回一個HttpUnauthorizedResult 操作結果,它產生了一個 HTTP 401(未授權)的狀態碼。
7.2.3 Windows Authentication
為使用Intranet 驗證選項,我們需要啟用Windows 驗證,禁用 Anonymous 驗證。
使用全局授權過濾器保障整個應用程式安全
MVC 4中新添加了AllowAnonymous 特性。如果把AuthorizeAttribute 註冊為全局過濾器,並且有些方法需要外部訪問,那麼這些方法只需要使用4中新添加了AllowAnonymous 特性裝飾即可。AllowAnonymous 僅對標準的AuthorizeAttribute 有效;對於自定義的授權過濾器,則不一定起作用。全局授權僅對MVC 是全局的
7.3 要求角色成員使用Authorize 特性
Authorize 特性允許指定角色和用戶。
Roles 參數可以有多個角色,我們用‘,’分割:
7.4 擴展用戶身份
7.4.1 存儲用戶額外的信息
Code First 模式下只需要在用戶類中添加屬性。
7.5 通過OAuth 和 OpenID 的外部登錄
OAuth 和 OpenID 是開放的標準。這些協議允許用戶使用他們已有的賬戶登錄我們的網站。
配置網站以支持OAuth 和 OpenID是非常難以實現的,協議複雜,頂級提供器對這兩種協議的實現方式不一樣。MVC 通過在使用Individual User Accounts 身份驗證的項目模板中內置支持OAuth 和 OpenID 極大的簡化了這一點。
7.5.1 註冊外部登錄提供器
使用OAuth 提供器的網站要求我們把網站註冊為一個應用程式。這樣它們會提供給我們一個客戶端id 和一個口令。我們利用OAuth 提供器根據這些信息就可以進行驗證。
7.5.2 配置OpenID提供器
因為不用註冊,不用填寫參數,配置OAuth 提供器是非常簡單的。
7.5.3 配置OAuth提供器
7.5.4 外部登錄的安全性
1,可信的外部登錄器
2,要求SSL 登錄
從外部提供器到我們網站的回調中包含擁有用戶信息的安全令牌,這些令牌允許訪問我們的網站。當令牌在Internet 中傳遞時,使用HTTPS 傳輸是非常重要的,因為這樣可以訪問信息攔截。
為訪問AccountController 的Login Get 方法並執行HTTPS,支持外部登錄的應用程式應該使用 RequireHttps 特性來使用HTTPS
// //GET:/Account/login [RequireHttps] [AllowAnonymous] pulic ActionResult Login(string returnUrl) { ViewBag.ReturnUrl=returnUrl; return View(); }
7.6 Web 應用程式中安全向量
因為Web 應用程式運行在標準的、基於文本的協議(像HTTP和HTML)之上,所以它們特別容易受到自動攻擊的傷害。
7.6.1 威脅:跨站腳本(XSS)
1,威脅概述
有兩種方法可以實現XSS,一種方法是通過用戶將惡意腳本輸入到網站中,而這些網站又可以接收“不幹凈”(unsanitized)的用戶輸入。另一種方法是通過直接在頁面上顯示用戶的輸入。第一種情況被稱為“被動註入”(Passive Injection)。用戶把“不幹凈的”的 內容輸入到文本框,並把這些數據保存在資料庫中,以後再重新在頁面上顯示。第二種方法稱為“主動註入”,涉及用戶直接把“不幹凈”的內容輸入到文本框中,這些輸入的內容會立刻被顯示出來。
2,被動註入
eg:
"></a><script src="hackScript.js"></script><a href="
3,主動註入
eg:
http://www.meishizouqi.com?Search=<form action=""><input type="text" name="name" /><input type="password" name="password" /><input type="submit" value="登錄" />
4,阻止 XSS
1)對所有內容進行HTML 編碼
頁面上每一個輸出都應該是經過HTML 編碼或HTML 特性編碼。
2)Html.AttributeEncode 和 Url.Encode
謹記:永遠不要信任用戶能夠接觸到或者使用的一切數據,其中包括所有的表單值、URL、cookie或來自第三方源(如OpenID)的個人信息。此外網站所訪問的資料庫或服務可能沒有經過編碼,所以不要輕易相信輸入應用程式的任何數據,要儘可能的對其編碼。
3)JavaScript 編碼
黑客可以很隨意的利用十六進位轉義碼隨意的向輸入內容中插入JavaScript 腳本代碼
4)將AntiXSS 庫作為ASP.NET 的預設編碼器
- AntiXSS 使用的是一個信任字元的白名單,ASP.NET 預設實現一個有限的不信任字元的黑名單。
- AntiXSS 的重點是阻止應用程式的漏洞,ASP.NET 關註的是防止HTML 頁面顯示不被破壞。
在.NET 4.5及更高版本包含 MicroSoft WPL(Web Protection Library)的AntiXSS 編碼器。要使用AntiXSS 庫需要在 Web.config 的 httpRunTime 中添加以下代碼:< httpRuntime ... encoderType="System.Web.Security.AntiXss.AntiXssEncoder,System.Web,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d59a3a"/>
7.6.2 威脅:跨站請求偽造
跨站請求偽造(Cross-Site Request Forgery,CSRF,有時也寫作XSRF 表示)要比簡單的跨站腳本攻擊更具有危險性。
1,威脅概述
eg:
用戶退出登錄方法為:/account/Logout
用戶將評論中提交這樣一個標簽<img src="/account/Logout">
瀏覽器將自動向該地址發送Get 請求。
2,阻止 CSRF 攻擊
ASP.NET MVC 提供了阻止 CSRF 攻擊的方法。
1)令牌驗證
Html.AntiForgeryToken 輔助方法會生成一個加密值作為隱藏的輸入元素。
該值會與作為會話cookie 存儲在用戶瀏覽器的另一個值相匹配。在提交表單時,ActionFilter 會驗證這兩個值是否相匹配。這種方法可以阻止大部分的CSRF 攻擊。
2)冪等的GET 請求
一個冪等操作的特點是執行一次和執行多次的效果是一樣的。
一般來說,僅通過POST 修改資料庫中或網站上的內容可以有效防禦全部的CSRF 攻擊。
3) HttpReferrer 驗證
HttpReferrer 驗證通過使用ActionFilter 處理。這種情況下可以查看提交表單值的客戶段是否在目標站點上。
7.6.3 威脅:cookie 盜竊
如果能夠竊取某人在一個網站上的身份驗證Cookie,就可以在該網站上冒充他,執行他許可權內的所有操作。這種攻擊依賴於 XSS 漏洞。攻擊者需要在目標站點上註入一些腳本,才能竊取 Cookie
StackOverflow.com 允許在評論中包含提交一定數量的HTML 標記
可以停止腳本對站點中cookie 的訪問,需要設置一個簡單的標誌:HttpOnly
可以在 web.config 文件中對所有的Cookie 設置,也可以為編寫的每個Cookie 單獨設置。
7.6.4 威脅:重覆提交
重覆提交:惡意用戶向查詢字元串或提交的表單添加超出用戶最終操作許可權的值。
防禦重覆提交最簡單的一個方法是使用[Bind] 特性顯式的控制需要由模型綁定器綁定的屬性。也可以用 UpdateModel 或 TryUpdateModel 方法的一個重載版本接受一個綁定列表。
7.6.5 威脅:開放重定向
1.威脅概述
那些通過請求(如查詢字元串和表單數據)指向重定向URL 的WEB 應用程式可能被篡改,而把用戶重定向到外部的惡意URL。這種篡改就被稱為開放重定向攻擊(open redirection attack)。
可以調用 IsLocalUrl()方法對 returnUrl 參數進行驗證。
7.7 適當的錯誤報告和堆棧跟蹤
customErrors 模式有3 個可選設置項,分別是:
- On:伺服器開發最安全選項,因為它總是隱藏錯誤提示消息。
- RemoteOnly:向大多數用戶展示一般的錯誤信息,但向擁有伺服器訪問許可權的用戶展示完整的錯誤提示消息。
- Off:最容易受到攻擊的選項,它向每一個網站的訪問者展示詳細的錯誤處理。
7.7.1 使用配置轉換
使用RemoteOnly 模式替換掉customError 模式。
7.7.2 在生產環境下使用Retail 部署配置
部署配置的是伺服器環境下一的 machine.config 文件中的一個簡單開關,用來標識ASP.Net 是否在Retail 部署模式下運行。
將deployment/retail 設置為true ,將影響以下幾項設置
- 設置為On,就是最安全的設置
- 禁用跟蹤輸出
- 禁用調試
這些設置可以覆蓋Web.config 文件中所有應用程式級別的設置
7.9 小結
Web 應用程式中安全問題總是可以歸結為開發人員一方的簡單問題:不當的假設、錯誤信息及缺乏訓練等。