我在我的应用程序中构建了CSRF保护,只需在每个页面加载时生成随机令牌,将其置于会话中,然后将令牌绑定到<body>标记属性,如:
<body data-csrf-token="csrf_GeJf53caJD6Q5WzwAzfy">
Run Code Online (Sandbox Code Playgroud)
然后在每个表单操作或ajax请求中,我只需从body标签中获取令牌并将其发送出去.
除了一个巨大的问题,这很好用.用户正在打开应用程序的多个选项卡,我看到令牌冲突.例如,用户加载第一页并生成令牌,然后他们切换选项卡,加载另一页,生成新令牌.最后,他们切换回第一页并提交格式化操作.这会导致无效的CSRF令牌错误.
重新构建此选项以防止与多个选项卡发生冲突的最佳方法是什么,同时尽可能保证其安全.
只是在登录正确的解决方案时生成单个令牌,而不是在每个页面加载时生成新令牌?
我的Rails应用程序不时抛出一个ActionController :: InvalidAuthenticityToken.它每个月左右自发发生一次.因为我不认为有其他网站在尝试CSRF攻击,所以我开始对这些罕见的事件做出我的想法.我的结论到目前为止:
是否有其他原因造成这种误报拒绝?
请不要解释CSRF是什么;-)
这是一些日志......
F, [2016-12-06T16:03:59.050673 #15136] FATAL -- :
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
actionpack (4.2.7) lib/action_controller/metal/request_forgery_protection.rb:181:in `handle_unverified_request'
actionpack (4.2.7) lib/action_controller/metal/request_forgery_protection.rb:209:in `handle_unverified_request'
devise (4.2.0) lib/devise/controllers/helpers.rb:253:in `handle_unverified_request'
actionpack (4.2.7) lib/action_controller/metal/request_forgery_protection.rb:204:in `verify_authenticity_token'
activesupport (4.2.7) lib/active_support/callbacks.rb:432:in `block in make_lambda'
activesupport (4.2.7) lib/active_support/callbacks.rb:164:in `block in halting'
activesupport (4.2.7) lib/active_support/callbacks.rb:504:in `block in call'
activesupport (4.2.7) lib/active_support/callbacks.rb:504:in `each'
activesupport (4.2.7) lib/active_support/callbacks.rb:504:in `call'
activesupport (4.2.7) lib/active_support/callbacks.rb:92:in `__run_callbacks__'
activesupport (4.2.7) lib/active_support/callbacks.rb:778:in `_run_process_action_callbacks'
activesupport (4.2.7) lib/active_support/callbacks.rb:81:in `run_callbacks'
actionpack (4.2.7) lib/abstract_controller/callbacks.rb:19:in `process_action'
actionpack (4.2.7) lib/action_controller/metal/rescue.rb:29:in `process_action'
actionpack (4.2.7) …Run Code Online (Sandbox Code Playgroud) 我正在编写功能测试,我需要发出ajax post请求."CSRF令牌无效.请尝试重新提交表单".如何在功能测试中获取令牌?
$crawler = $this->client->request(
'POST',
$url,
array(
'element_add' => array(
'_token' => '????',
'name' => 'bla',
)
),
array(),
array('HTTP_X-Requested-With' => 'XMLHttpRequest')
);
Run Code Online (Sandbox Code Playgroud) 我想通过AJAX发送登录数据来验证用户身份,但由于CSRF,这是不可能的.你能告诉我在我的代码中添加什么来让它变得更好吗?
我的JavaScript文件:
$("#login").live("click", function() {
var username = $(".login_username").val();
var password = $(".login_password").val();
$.ajax({
url: "/login",
type: "POST",
data: {
username: username,
password: password
},
cache: false,
success: function(tekst) {
alert(tekst);
}
});
});
Run Code Online (Sandbox Code Playgroud) 我有两个Web应用程序,一个用于AngularJS中的Web UI,另一个用于Java中的REST Web服务.两者都部署在不同的域上.
应用程序使用cookie进行身份验证.每当用户输入有效的用户名和密码时,服务器返回包含令牌的仅http cookie,并且cookie将在所有请求中传递.我在两个应用程序上启用了CORS,这就是会话cookie正常工作的原因.
现在,我正在尝试为此添加CSRF保护.我试图使用csrf cookie,在服务器中将发送csrf cookie(而不是httponly)作为REST响应的一部分,UI将从cookie读取值并将其传递到csrf令牌头中以用于其他REST调用.
我面临的这种方法的问题是,由于服务器位于不同的域中,我无法使用AngularJs中的$ cookies读取cookie.有没有办法读取该cookie的值?如果没有,那么我可以用其他方式实现CSRF吗?
我还尝试在浏览器中在Web UI上实现csrf cookie的创建,但是浏览器不会将cookie作为其在不同域中的web服务发送.
那么,我的问题是如何为这种情况实施csrf保护?
我有一个用户无需登录即可发布的表单.但是,如果他的电子邮件被识别,则需要输入密码.密码表单通过Ajax验证,如果成功,则提交主表单.两种形式都需要有效的AntiForgeryToken.
问题是,密码检查作为副产品也签署了用户(来自客户的要求).这使令牌无效,并且无法发送主表单.
我已尝试以编程方式生成新令牌,但我无法让它工作.
关于如何解决这个问题的任何想法?
最终解决方案
我发现这个问题有助于输入反射.但是,这就是为什么在正常情况下你会避免黑客攻击内部类型的主要原因,这些类型是在版本之间的程序集之间进行的.正如贝蒂建议的那样,使用ILSpy来寻找东西.
这是最终的代码.
if (signIn)
FormsAuth.SignIn(user.Email, false);
var mvcAssembly = typeof(AntiForgery).Assembly;
var afdType = mvcAssembly.GetType("System.Web.Helpers.AntiForgeryData");
string fieldName = Convert.ToString(afdType.InvokeMember(
"GetAntiForgeryTokenName",
BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod,
null,
null,
new object[] { null }));
var serializerType = mvcAssembly.GetType("System.Web.Helpers.AntiForgeryDataSerializer");
var serializerCtor = serializerType.GetConstructor(new Type[0]);
object serializer = serializerCtor.Invoke(new object[0]);
string text = HttpContext.Request.Form[fieldName];
object antiForgeryData = serializerType.InvokeMember("Deserialize", BindingFlags.InvokeMethod, null, serializer, new object[] { text });
afdType.GetProperty("Username").SetValue(antiForgeryData,
signIn ? user.Email : string.Empty,
null);
string newToken = Convert.ToString(serializerType.InvokeMember(
"Serialize", …Run Code Online (Sandbox Code Playgroud) 我有一个Symfony 3.3.13系统,有各种形式.
以这些形式实现"深层联系",即.能够点击电子邮件链接,登录然后被重定向到我添加了以下更改的表单:
config.yml
framework:
secret: "%secret%"
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: ~
form: ~
csrf_protection: ~
...
more
...
Run Code Online (Sandbox Code Playgroud)
security.yml
security:
providers:
zog:
id: app.zog_user_provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
logout:
path: /logout
target: /
guard:
authenticators:
- app.legacy_token_authenticator
- app.token_authenticator
entry_point: app.legacy_token_authenticator
form_login: <--this line alone breaks CSRF
use_referer: true <--I tried partial combinations, none seems to make CSRF work
login_path: /security/login
use_forward: true
success_handler: login_handler
csrf_token_generator: security.csrf.token_manager <--added based on answer, doesn't help
Run Code Online (Sandbox Code Playgroud)
SRC …
X-CSRF-Token在隐藏字段中使用标头或令牌有什么区别 ?
当使用隐藏字段和使用标题时为什么?
我想那X-CSRF-Token是我正在使用javascript/ajax,但我不确定
Flask-WTForms提供CSRF保护.使用普通HTML表单时效果很好,但使用AJAX时过程不太清楚.我的表单中有文件上传,我用AJAX将进程分成两部分:文件进入upload端点,而表单的其余部分进入submit端点.由于文件是使用AJAX发布的,因此它不会获得CSRF令牌,但我希望保护upload端点免受攻击.如何在使用AJAX时生成CSRF令牌?
@app.route('/submit', methods=["GET","POST"])
@login_required
def submit():
form = MyForm()
if request.method == "POST" and form.validate():
# success, csrf checks out and data is validated
# do stuff
csrf_for_uploads = # generate csrf?
return render_template('some_form.html', form=form, csrf_for_uploads=csrf_for_uploads)
@app.route('/upload', methods=["POST"])
@login_required
def upload():
myfile = request.files['file']
# How do I verify CSRF now?
Run Code Online (Sandbox Code Playgroud) 我想在jQuery的更改事件上上传服务器上的图像但是使用codeigniter csrf我只能上传图像一次.如何使用ajax为多个请求上传图像.请在设置时记住
config['csrf_protection'] = FALSE;
Run Code Online (Sandbox Code Playgroud)
然后我能够发送多个请求jQuery onchange事件,但是当csrf_protection将为false时,我认为没有csrf的优势.所以问题是如何在启用csrf_protection时使用ajax发送多个请求.我的jquery代码如下
$("#avatar").change(function(){
var link = $("#avatar").val();
$.ajax({
url : "<?php echo base_url('main/test'); ?>",
type: 'post',
data: {'<?php echo $this->security->get_csrf_token_name(); ?>':'<?php echo $this->security->get_csrf_hash(); ?>',"id":"hello","link":link},
success : function(data)
{
alert(data);
}
});
});
Run Code Online (Sandbox Code Playgroud) csrf-protection ×10
csrf ×4
php ×4
ajax ×2
security ×2
symfony ×2
angularjs ×1
asp.net-mvc ×1
codeigniter ×1
cookies ×1
cross-domain ×1
django ×1
flask ×1
javascript ×1
jquery ×1
python ×1
testing ×1