通过依赖注入创建AntiForgeryToken

发布于 2024-08-10 12:18:55 字数 1685 浏览 6 评论 0原文

我正在努力提高公司网站的安全性,并希望创建一个令牌来防止伪造尝试,并且可以轻松维护,这就是我想到的。

public class AntiForgeryToken
{
    private readonly string _referenceToken;

    public AntiForgeryToken()
    {
        _referenceToken = Guid.NewGuid().ToString();
    }
    public string ReferenceToken
    {
        get { return _referenceToken; }
    }
}

在我的 MasterPage 的基类中,我有一个 HiddenField ,其中包含名为: ReferenceToken 的属性,

protected virtual void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        InjectToken();
    }

    ValidateToken();
}

private void InjectToken()
{
    var token = ObjectFactory.GetInstance<AntiForgeryToken>();
    ReferenceToken = token.ReferenceToken;
}

private void ValidateToken()
{
    var token = ObjectFactory.GetInstance<AntiForgeryToken>();
    if (ReferenceToken.Equals(token.ReferenceToken, SC.InvariantCultureIgnoreCase)) 
            return;
    ...do stuff for failed token
}

我有 StructureMap 句柄将令牌存储在 Session 内,因此它会在每个用户会话中保留,所有这些都是有效的实现吗防伪方案?

编辑:我的问题似乎有些混乱,是的,我了解 ASP.NET MVC 有一个内置的 AntiForgeryToken 方案,这个问题明确是关于如何为 WebForms 重新创建它> 防止使用 CSRF 攻击(跨站请求伪造)。我理解这并不意味着不需要对用户权限进行适当的授权。

我要提出 @Neal 和 @solairaja 发布的链接: 使用 ASP.NET MVC 的 AntiForgeryToken() 帮助程序防止跨站点请求伪造 (CSRF)。本文详细解释了 CSRF 攻击是什么以及 MVC 如何阻止它,但是他们的解决方案不适用于 Web 表单,这就是我开始实施自己的解决方案的原因。

看到@Neal 的回复后,我认为这很可能是公认的答案,因为我没有意识到我可以从 MVC 工具获取实际的源代码,这很可能会取代 guid 创建。但我会保留这个问题,以防其他人有一些有价值的信息需要补充。

I'm working on improving the security of my company's website and wanted to create a token to prevent forgery attempts that could be easily maintained this is what I came up with.

public class AntiForgeryToken
{
    private readonly string _referenceToken;

    public AntiForgeryToken()
    {
        _referenceToken = Guid.NewGuid().ToString();
    }
    public string ReferenceToken
    {
        get { return _referenceToken; }
    }
}

In my base class for my MasterPage I have a HiddenField wrapped with property named: ReferenceToken

protected virtual void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        InjectToken();
    }

    ValidateToken();
}

private void InjectToken()
{
    var token = ObjectFactory.GetInstance<AntiForgeryToken>();
    ReferenceToken = token.ReferenceToken;
}

private void ValidateToken()
{
    var token = ObjectFactory.GetInstance<AntiForgeryToken>();
    if (ReferenceToken.Equals(token.ReferenceToken, SC.InvariantCultureIgnoreCase)) 
            return;
    ...do stuff for failed token
}

I have StructureMap handle storing the token inside the Session so it's persisted per user session, would all of this be a valid implementation of an AntiForgery scheme?

Edit: There seems to be some confusion on my question, yes I understand ASP.NET MVC has a built in AntiForgeryToken scheme, this question is explicitly about how to recreate this for WebForms to prevent the usage of a CSRF attack (Cross Site Request Forgery). I understand this in no means removes the need for proper authorization of user rights.

I was going to bring up the very link that @Neal and @solairaja posted: Prevent Cross-Site Request Forgery (CSRF) using ASP.NET MVC’s AntiForgeryToken() helper. This article explains more of what the CSRF attack is and how MVC stops it however their solution isn't applicable to webforms which is why I went about implementing my own.

After seeing the response from @Neal I think that will most likely be the accepted answer since I didn't realize I could just get the actual source code from the MVC tool which will most likely replace the guid creation. But I'll leave the question open incase anyone else has some valuable information to add.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

一袭白衣梦中忆 2024-08-17 12:18:56

我不会像这样使用防伪令牌,而是验证经过身份验证的用户实际上具有进行所请求的修改的必要权限。

例如,网页是“创建用户页面”,我会检查经过身份验证的用户是否有权创建新用户。该页面是“编辑用户X页面”吗?我会检查经过身份验证的用户是否有权修改用户X。也许因为他本人是用户X,或者是管理用户。

也就是说,使用 GUID 并不是很安全。指南是根据为唯一性而非随机性而编写的算法生成的。据我所知,存在三种有效的算法:基于名称的算法、基于时间的算法和随机算法。如果系统使用的 Guid 算法(可能会在未来的 .NET 版本中更改)是基于时间的,那么猜测有效的 Guid 并不是很困难。

Instead of using anti forgery tokens like that I would validate that the authenticated user actually has the necessary rights to make the requested modifications.

E.g. is the web page a "create user page", I would check that the authenticated user has authorization to create new users. Is the page an "edit user X page", I would check that the authenticated user has authorization to modify user X. Maybe because he himself is user X, or an administrative user.

That said, using GUIDs is not very secure. Guids are generated based on an algorithm written for uniqueness, not randomness. AFAIK there are three valid algorithms, name based, time based, and random. If the Guid algorithm used by the system (which could be changed by a future .NET version) is time based, then guessing valid Guids is not very difficult.

嘦怹 2024-08-17 12:18:55

Chris,

您的方法或多或少模仿了 MVC 中的防伪造方法,只不过它们使用从 RNGCryptoServiceProvider 生成的 Base64 编码字节数组并将令牌存储在页面(隐藏表单字段)和 cookie 中。我建议将更多逻辑移至令牌实现中(例如,将大部分验证逻辑封装在令牌内)。

MVC 实现的代码可以在 http:// aspnet.codeplex.com/sourcecontrol/changeset/view/23011?projectName=aspnet#391757 如果可能的话,您应该查看一下 http://blog.codeville.net/2008/09/01/ Prevent-cross-site-request-forgery-csrf-using-aspnet-mvcs-antiforgerytoken-helper/ 进行分析+想法。

Chris,

your approach more or less mimics the anti-forgery approach in MVC, except they use a base64 encoded byte array generated from RNGCryptoServiceProvider and store the token both in the page ( hidden form field ) and in a cookie. I would recommend moving more of the logic into the token implementation ( e.g. encapsulate most of the validation logic inside the token ).

The code for the MVC implementation is freely accessible at http://aspnet.codeplex.com/sourcecontrol/changeset/view/23011?projectName=aspnet#391757 if possible you should probably review that as well as http://blog.codeville.net/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnet-mvcs-antiforgerytoken-helper/ for an analysis + ideas.

素手挽清风 2024-08-17 12:18:55

如果您使用视图状态,ASP.NET Web 窗体默认会立即阻止 CSRF 攻击。除非您在应用程序中有效地禁用了视图状态,否则您将添加代码来解决您没有的问题。

视图状态可防止 CSRF 攻击
.Net CSRF 防护 - OWASP

ASP.NET Web Forms prevents CSRF attacks out of the box by default if you are using View State. Unless if you have effectively disabled view state in your application, you are adding code to solve a problem you don't have.

View State prevents CSRF Attacks
.Net CSRF Guard - OWASP

幽梦紫曦~ 2024-08-17 12:18:55

首先,我想我应该问……“防伪”的真正含义是什么?对于被伪造,您担心什么?接下来的其余内容只是浮现在脑海中的一些一般信息...

我要更改的一件事是不使用 Guid.NewGuid。关于它是否是随机的、因此不适合安全目的存在争议。也就是说,我认为这将是一次非常难以实现的攻击。

查看 RNGCryptoServiceProvider 的 GetBytes 方法,了解应该更好地生成随机令牌的方法。除了更好的随机性之外,这样做的另一个优点是您可以将其设置为任何您想要的大小。

你是通过 ssl 执行此操作吗?首先,ssl 是中间人攻击的第一道防线。对于每种需求来说,它可能不够安全(其他人可能会对此进行争论),但如果您担心这些事情,那么它就是起点。如果没有,您如何确保您从正确的机器获得响应,而不是从首先响应的中间人获得响应?如果没有 SSL 或同等技术,您的令牌就像您所做的任何其他事情一样容易被盗。

需要考虑添加的另一件事是让您的代币仅适用于一次旅行,并在下一次旅行时生成一个新的代币返回给客户。尝试重用它失败了。

如果您这么想的话,我不会尝试用您自己设计的其他东西来替换 SSL。如果您担心重放,一次性令牌生成是阻止重放的一种方法。如果您担心用户两次提交相同的表单数据,这是一回事。如果您担心这一点,我也会考虑您的整体应用程序设计。许多重播和类似的场景可以通过业务逻辑的合理设计来解决,例如不信任客户端向您发送敏感信息,例如购物车中商品的价格。

另请查看有关 ASP.NET 和 IIS 安全性的各种 microsoft 指南(即 Google ASP.NET 或 IIS 安全站点:microsoft.com)作为起点。很多聪明人已经为我们解决了很多问题。

First, I suppose I should ask... what do you really mean by "AntiForgery"? What are you concerned about being forged? The rest of what follows is just some general info that pops into mind...

One thing I would change is to not use Guid.NewGuid. There's debate about whether it is random or not and thus not suitable for security purposes. That said, I think it would be a very hard attack to pull off.

Look at RNGCryptoServiceProvider for the GetBytes method for something that should be better for generating a random token. In addition to better randomness, another advantage to this is you can make it whatever size you want.

Are you doing this over ssl though? First off, ssl is line of defense number one for man in the middle attacks. It may not be secure enough (and others can debate about that) for every need, but if you're concerned about such things, it's the starting point if nothing else. If not, how do you ensure that you are getting a response from the right machine and not a man-in-the-middle who is responding first? Without SSL or an equivalent, your token is just as easily stolen as anything else you do.

One additional thing to consider adding is having your tokens be only good for one trip and you generate a new one back to the client on the next trip. Trying to reuse it fails.

I would not try to replace SSL with something else of your own contrivance if that is what you are thinking. If you are concerned about replay though, one time token generation is one way to stop it. If you're worried about a user submitting the same form data twice, this is one thing to do. I would also consider your overall application design if you're concerned about that. Many replay and similar scenarios can be defeated by sound design of your business logic such as not trusting the client to send you sensitive information like the price of an item in a shopping cart.

Please also check out the various microsoft guidance on ASP.NET and IIS security (i.e. Google ASP.NET or IIS security site:microsoft.com) as a starting point. A lot smart people have solved many issues already for us.

匿名。 2024-08-17 12:18:55

这一切都是有效的吗?
防伪的实施
方案?

据我所知,您似乎正在将 GUID 插入到页面上,然后在页面返回时查找相同的 GUID。

我不知道你的要求是什么,所以我不能说这个方案是否真的“有效”。不过,我可以指出一些事情:

  1. 如果 GUID 仅存在于页面上,那么什么会阻止用户在一台计算机上阅读页面并从另一台计算机提交表单?如果您还没有将其与 cookie 或会话(也使用 cookie)关联起来,那就太好了。
  2. 如果 GUID 作为静态隐藏 字段写入页面,则机器人可以读取并提交表单。您可以通过要求页面上的脚本在提交之前处理令牌来解决这个问题。
  3. 您使用 ViewState 吗?如果是这样,您可能会考虑将 ViewStateUserKey 设置为每个客户端唯一的可重复值;它执行与您在此处描述的类似的功能。

would all of this be a valid
implementation of an AntiForgery
scheme?

As far as I can tell, it looks like you are inserting a GUID onto a page, and then looking for the same GUID when the page comes back.

I don't know what your requirements are, so I can't say if the scheme is really "valid." However, I can point out a few things:

  1. If the GUID only lives on the page, then what would prevent a user from reading the page on one machine, and submitting the form from another? It would be good to associate it with a cookie or a session (which also uses a cookie), if you aren't already.
  2. If the GUID is written into the page as a static hidden <input> field, then the form could be read and submitted by bots. You can get around that by requiring script on the page to process the token, before submitting it.
  3. Are you using ViewState? If so, you might consider just setting ViewStateUserKey to some repeatable value that's unique per client; it performs a similar function to what you've described here.
薄凉少年不暖心 2024-08-17 12:18:55

正如 NICK 所说,对我来说,您给出的代码看起来像是在页面上插入一个 GUID,然后在页面返回时查找相同的 GUID。当您使用存储到会话中的结构图时,这也是个好主意。

但是有一些内置方法可用于此防伪概念。

请先参考以下链接并了解

http://blog.maartenballiauw.be/post/2008/09/01/ASPNET-MVC-preview-5s-AntiForgeryToken-helper-method-and-attribute.aspx

现在,

请检查以下链接以获取详细说明和接近方法。

http://msdn.microsoft.com/en- us/library/system.web.mvc.htmlhelper_methods.aspx

http://blog.codeville.net/2008/09/01/prevent-cross-site-request-forgery-csrf-using-% 20aspnet-mvcs-antiforgerytoken-helper/

谢谢!!

As NICK told, for me too the code which you have given, looks like you are inserting a GUID onto a page, and then looking for the same GUID when the page comes back. Thats good idea too when ur using a structure map storing into the session.

But there are some inbuilt methods are available for this AntiForgery concepts.

Kindly refer to the below link first and understand

http://blog.maartenballiauw.be/post/2008/09/01/ASPNET-MVC-preview-5s-AntiForgeryToken-helper-method-and-attribute.aspx

Now,

Check the below link for the details descriptions and methodology of approaching.

http://msdn.microsoft.com/en-us/library/system.web.mvc.htmlhelper_methods.aspx

http://blog.codeville.net/2008/09/01/prevent-cross-site-request-forgery-csrf-using-%20aspnet-mvcs-antiforgerytoken-helper/

Thank you !!

一身骄傲 2024-08-17 12:18:55

在我看来,好像每个请求都会生成一个金丝雀。现在,如果用户打开多个选项卡会发生什么? :)

您的方法(以及 ASP.NET MVC 实现)的问题是它依赖于开发人员来实现它。像这样的安全应该是选择退出,而不是选择加入。当我编写 AntiCSRF 模块 时,我最终使用了 ASP.NET 页面生命周期,这意味着没有对底层代码,除非开发人员想要选择将某个页面排除在 CSRF 检查之外。您会注意到,它使用单个令牌,该令牌在该用户的浏览器会话的生命周期内持续存在 - 实际上不需要在每个请求中更改令牌。

现在,我编写该模块主要是为了说明我即将出版的书的一些概念(此处插入广告grin),您当然可以使用ViewStateUserKey,但这又是选择加入,而不是选择退出。

That looks to me as if it's generating a canary with every request. Now what happens if a user opens multiple tabs? :)

The problem with your approach (and the ASP.NET MVC implementation) is it relies on developers to implement it. Security like this should be opt-out, not opt-in. When I wrote a AntiCSRF module I ended up using the ASP.NET page lifecycle instead, which mean no changes to the underlying code, unless a developer wanted to opt a page out of the CSRF checks. You'll note that it uses a single token which lasts for the lifetime of that user's browser session - there's no actual need to change the token with every request.

Now I wrote the module mainly as a way to illustrate some concepts for my forth coming book (insert advertisement here grin), you could of course use the ViewStateUserKey, but again this is opt-in, rather than opt-out.

情魔剑神 2024-08-17 12:18:55

安全第一条规则:不要尝试推出自己的安全

据我了解您的描述,这不是有效的防伪方案。攻击者需要规避的只是使用浏览器的“查看源代码”功能来查找令牌。然后,他或她可以发布任何他们喜欢的内容,只要他们记得发布该令牌,并且您的代码不会知道其中的区别。

如果我完全误解了你的描述,我深表歉意......

First rule of security: Don't try to roll your own security

As I understand your description, that wouldn't be a valid anti-forgery scheme. All an attacker would need to circumvent it would be to use the View Source feature of his or her browser to find the token. Then he or she could post whatever they like as long as they remember to post that token, and your code wouldn't know the difference.

Apologies if I completely misunderstood your description...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文