通过依赖注入创建AntiForgeryToken
-
19-09-2019 - |
题
我正在努力提高公司网站的安全性,并希望创建一个令牌来防止伪造尝试,并且可以轻松维护,这就是我想到的。
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 句柄将令牌存储在会话中,因此它会在每个用户会话中保留,所有这些都是防伪方案的有效实现吗?
编辑: 我的问题似乎有些混乱,是的,我了解 ASP.NET MVC 有一个内置的 AntiForgeryToken 方案,这个问题明确是关于如何重新创建它的 网页表格 防止使用 CSRF 攻击(跨站请求伪造)。我理解这并不意味着不需要对用户权限进行适当的授权。
我打算提出 @Neal 和 @solairaja 发布的链接: 使用 ASP.NET MVC 的 AntiForgeryToken() 帮助程序防止跨站点请求伪造 (CSRF). 。本文详细解释了 CSRF 攻击是什么以及 MVC 如何阻止它,但是他们的解决方案不适用于 Web 表单,这就是我开始实施自己的解决方案的原因。
看到@Neal 的回复后,我认为这很可能是公认的答案,因为我没有意识到我可以从 MVC 工具获取实际的源代码,这很可能会取代 guid 创建。但我会保留这个问题,以防其他人有一些有价值的信息需要补充。
解决方案
克里斯,
您的方法或多或少模仿了 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/ 分析+想法。
其他提示
ASP.NET Web表单可防止CSRF攻击在使用视图状态的情况下默认情况下。除非您有效地禁用了应用程序中的查看状态,否则您正在添加代码来解决您没有的问题。
查看状态阻止CSRF攻击
.NET CSRF GUARD -OWASP
首先,我想我应该问...“抗试验”是什么意思?您担心被伪造的东西?接下来的其余部分只是一些脑海中浮现的一般信息...
我要更改的一件事是不使用Guid.NewGuid。关于它是否是随机的,因此存在争论,因此不适合安全目的。也就是说,我认为要进行的攻击将是非常艰难的攻击。
查看rngcryptoserviceprovider for getBytes方法,以便可以更好地生成随机令牌。除了更好的随机性外,这是另一个优点,即您可以将其制成任何尺寸。
您是否在SSL上这样做?首先,SSL是中间攻击中人类第一的防守线。对于每种需求,它可能还不够安全(其他人可以对此进行辩论),但是如果您担心这样的事情,那就是起点,如果没有别的。如果没有,您如何确保您从正确的机器中得到回应,而不是首先回应的中间人?如果没有SSL或同等标准,您的代币与您所做的任何事情一样容易被盗。
要考虑添加的另外一件事是让您的令牌仅适合一次旅行,然后在下一次旅行中将新的代币返回给客户。试图重复使用它失败。
我会 不是 如果您在想的话,请尝试用自己的其他因素替换SSL。但是,如果您担心重播,一次令牌生成是阻止它的一种方法。如果您担心用户两次提交相同表单数据,这是一回事。如果您担心的话,我还将考虑您的整体应用程序设计。许多重播和类似的场景都可以通过您的业务逻辑的声音设计来打败,例如不信任客户向您发送敏感信息,例如购物车中的商品价格。
另外,请查看ASP.NET和IIS安全性的各种Microsoft指南(即Google ASP.NET或IIS安全网站:Microsoft.com)作为起点。许多聪明的人已经为我们解决了许多问题。
所有这些都会是抗试验计划的有效实施吗?
据我所知,看来您正在将GUID插入页面上,然后在页面返回时寻找相同的GUID。
我不知道您的要求是什么,所以我不能说该计划是否真的“有效”。但是,我可以指出一些事情:
- 如果GUID仅生活在页面上,那么什么会阻止用户在一台计算机上读取页面并从另一台计算机上提交表格?如果还没有,将其与cookie或会话(也使用cookie)相关联会很好。
- 如果将GUID写入页面上,则是静态隐藏的
<input>
字段,然后可以通过机器人读取和提交表单。您可以通过在提交之前的页面上的脚本来处理令牌来解决这个问题。 - 您正在使用ViewState吗?如果是这样,您可能会考虑仅设置
ViewStateUserKey
对于每个客户端独特的可重复价值;它执行与您所描述的功能相似的功能。
正如尼克所说的那样,对我来说,您给出的代码也看起来像是将GUID插入页面上,然后在页面返回时寻找相同的GUID。当您使用将结构图存储到会话中时,这也是个好主意。
但是,有一些内置方法可用于这种抗试验概念。
请先参考以下链接并理解
现在,
检查以下链接以获取详细信息描述和接近的方法。
http://msdn.microsoft.com/en-us/library/system.web.mvc.htmlhelper_methods.aspx
谢谢 !!
在我看来,它似乎是在每个请求中生成金丝雀。现在,如果用户打开多个选项卡,会发生什么? :)
您的方法(以及ASP.NET MVC实施)的问题在于它依赖开发人员来实施它。这样的安全性应该退出,而不是选择加入。当我写一个 ANTICSRF模块 我最终使用了ASP.NET页面生命周期,这意味着对基础代码没有更改,除非开发人员想从CSRF检查中选择一个页面。您会注意到,它使用的单个令牌可以持续该用户的浏览器会话的寿命 - 实际上,每次请求都没有实际更改令牌。
现在,我写了该模块,主要是为我的第四本书说明一些概念的方式(在此处插入广告 笑),您当然可以使用 ViewStateUserKey, ,但这再次是选择加入,而不是选择退出。
安全的第一个规则: 不要试图滚动自己的安全
据我了解您的描述,这不是一个有效的反对计划。所有攻击者都需要规避它将使用 查看源 他或她的浏览器的功能可以找到令牌。然后,只要他们记得发布该令牌,他或她就可以发布自己喜欢的任何内容,而您的代码也不知道区别。
抱歉,如果我完全误解了您的描述...
而不是使用像这样的反伪造令牌,我会证明身份验证的用户实际上具有进行所需修改的必要权利。
例如,网页是“创建用户”页面,我将检查身份验证的用户是否已授权创建新用户。页面是“编辑用户X页”,我将检查身份验证的用户是否有权修改用户X。也许因为他本人是用户X或管理用户。
也就是说,使用GUIDS不是很安全。 GUID是基于为独特而不是随机性编写的算法生成的。 AFAIK有三种有效的算法,基于名称,基于时间和随机。如果系统使用的GUID算法(可以通过未来的.NET版本更改)是基于时间的,那么猜测有效的GUID并不是很困难。