• 重新整理 .net core 实践篇————cookie 安全问题[三十八]


    前言

    简单整理一下cookie的跨站攻击,这个其实现在不常见,因为很多公司都明确声明不再用cookie存储重要信息,不过对于老站点还是有的。

    正文

    攻击原理:

    这种攻击要达到3个条件:

    1. 用户访问了我们的站点。

    2. 用户通过cookie存储和传递身份信息

    3. 用户访问了坏站点

    1和3根本控制不了,那么控制的就只有2,就是不使用cookie。

    但是有些站点改动太大,那么是否还有其他方式呢?

    防御方式:

    1. 不使用cookie存储和传输身份认证

    2. 使用antiforgerytoken,anti-forgery 防伪。

    3. 避免使用Get作为业务操作的请求方式

    那么从上面看可以在2上做文章,因为3只是说让低级黑客被阻挡。

    同样antiforgerytoken 方式也有两种:

    1. validateAntiForgeryToken
    2. AntoValidateAntiforgeryToken

    那么就来演示一下:

    下面问我们的站点,提供的cookie身份认证方式:

    var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["SecurityKey"]));
    services.AddSingleton(securityKey);
    services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    	.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
    	{
    
    	}).AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
    	{
    		options.TokenValidationParameters = new TokenValidationParameters
    		{
    			ValidateIssuer = true,
    			ValidateAudience = true,
    			ValidateLifetime = true,
    			ClockSkew = TimeSpan.FromSeconds(30),
    			ValidateIssuerSigningKey = true,
    			ValidAudience = "localhost",
    			ValidIssuer = "localhost",
    			IssuerSigningKey = securityKey
    		};
    	});
    

    上面是cookie和jwt的认证方式哈。

    那么下面这个是cookie登录:

    [HttpGet]
    public async Task<IActionResult> CookieLogin(string userName)
    {
    	var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
    	identity.AddClaim(new Claim("Name", userName));
    	await this.HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,new ClaimsPrincipal(identity));
    	return Content("login");
    }
    

    那么有一个接口是购买接口:

    [ApiController]
    [Route("[controller]")]
    public class OrderController : Controller
    {
    	[HttpPost]
    	[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme+","+CookieAuthenticationDefaults.AuthenticationScheme)]
    	public IActionResult Pay()
    	{
    		return Content(User.FindFirst("name").Value+"买买买");
    	}
    }
    

    上面认证方式有cookie和jwt了。

    那么我们先使用cookie进行登录一下,调用CookieLogin这个接口。

    https://localhost:5001/Account?username=aomaomao
    

    以看到前台有cookie信息。

    在另外一个站点有这样一个东西:

    <form action="https://localhost:5001/order" method="post">
        <label>打折购买:</label>
        <label>1块钱</label>
        <input type="submit" value="提交"/>
    </form>
    

    那么点击一下这个提交后:

    可以看到这样就被攻击了。

    那么可能有人就会说,如果自己看了一眼网站地址应该就不会出现问题吧。

    其实一般攻击站点一般不给你点击的机会。

    <script>
      document.form[0].submit()
    </script>
    

    这一段代码在进入网站的时候就自动帮你点击了。

    services.AddAntiforgery(options =>
    {
    	options.HeaderName = "X-CSRF-TOKEN";
    });
    services.AddMvc(options => options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()));
    

    上面这个代码进行Antiforgery验证,通过header里面的X-CSRF-TOKEN的值。options => options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()是自我判断是否应该验证的机制。

    可以看下AutoValidateAntiforgeryTokenAttribute的源码:

    public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
    {
      return (IFilterMetadata) serviceProvider.GetRequiredService<AutoValidateAntiforgeryTokenAuthorizationFilter>();
    }
    

    那么继续看AutoValidateAntiforgeryTokenAuthorizationFilter:

      internal class AutoValidateAntiforgeryTokenAuthorizationFilter : ValidateAntiforgeryTokenAuthorizationFilter
      {
        public AutoValidateAntiforgeryTokenAuthorizationFilter(
          IAntiforgery antiforgery,
          ILoggerFactory loggerFactory)
          : base(antiforgery, loggerFactory)
        {
        }
    
        protected override bool ShouldValidate(AuthorizationFilterContext context)
        {
          if (context == null)
            throw new ArgumentNullException(nameof (context));
          string method = context.HttpContext.Request.Method;
          return !string.Equals("GET", method, StringComparison.OrdinalIgnoreCase) && !string.Equals("HEAD", method, StringComparison.OrdinalIgnoreCase) && (!string.Equals("TRACE", method, StringComparison.OrdinalIgnoreCase) && !string.Equals("OPTIONS", method, StringComparison.OrdinalIgnoreCase));
        }
      }
    

    看ShouldValidate,里面说明了get,head,trace,options都不会进行验证,post delete等其他的才会验证。

    如果你怕这个把握不住的话,那么你可以设置属性:

    [HttpPost]
    [ValidateAntiForgeryToken]
    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme+","+CookieAuthenticationDefaults.AuthenticationScheme)]
    public IActionResult Pay()
    {
    	return Content(User.FindFirst("name").Value+"买买买");
    }
    

    直接在方法上加入ValidateAntiForgeryToken即可。

    那么我们还是按照前面的方法进行演示一下。

    这里表示的就是400了,bad request。

    先这样,细节篇会介绍是具体是如何验证的,在DefaultAntiforgery这个类里面。

    下一节重定向攻击。

  • 相关阅读:
    bzoj4105: [Thu Summer Camp 2015]平方运算
    bzoj4035: [HAOI2015]数组游戏
    bzoj1022: [SHOI2008]小约翰的游戏John
    bzoj4665: 小w的喜糖
    CodeChef:Little Elephant and Colored Coins
    bzoj4664: Count
    bzoj4498: 魔法的碰撞
    bzoj4230: 倒计时
    bzoj4532: [BeiJing2014 WinterCamp] 珠链
    python 画正态曲线
  • 原文地址:https://www.cnblogs.com/aoximin/p/14984428.html
Copyright © 2020-2023  润新知