yetiforce / csrf-magic
跨站请求伪造安全库
Requires
- php: >=7.1.0
README
将以下行添加到所有可访问的PHP页面的顶部。如果您有一个所有内容都包含的通用文件,请将其放在那里。
include_once '/path/to/csrf-magic.php';
执行、测试,然后忘记它。如果没有发生任何坏事,csrf-magic正在保护您。如果遇到问题,请继续阅读。
TABLE OF CONTENTS
+ ------------------- +
1. TIPS AND TRICKS
2. AJAX
3. CONFIGURE
4. THANKS
5. FOOTNOTES
+ ------------------- +
-
技巧和技巧
-
如果您的JavaScript和AJAX持续出现错误,请检查下面的AJAX部分以了解如何修复。
-
CSS覆盖保护使在frame/iframe元素中显示您的网站变得不可能。您可以在csrf_startup()函数中使用csrf_conf('frame-breaker', false)来禁用它。
-
csrf-magic将启动一个会话。要禁用,请在csrf_startup()函数中使用csrf_conf('auto-session', false)。
-
默认的错误信息对用户不够友好。请编写自己的函数输出错误信息,并在csrf_startup()函数中设置csrf_conf('callback', 'myCallbackFunction')。
-
请确保csrf_conf('secret', 'ABCDEFG')中包含一些随机内容。如果csrf-magic.php所在的目录可写,csrf-magic将在csrf-secret.php文件中为您生成一个密钥。
-
请记住,您可以使用auto_prepend在所有页面上包含csrf-magic.php。您可能想创建一个占位文件,该文件可以包含csrf-magic.php以及执行配置。
-
令牌的默认过期时间为两小时。如果预期用户需要更长时间来填写表单,请确保在令牌无效时启用双提交。
-
-
AJAX
csrf-magic具有动态重写使用XMLHttpRequest的AJAX请求的能力。然而,由于此过程的侵略性,默认情况下它未启用。您可以通过在包含csrf-magic.php之前添加此代码来启用它。
function csrf_startup() {
csrf_conf('rewrite-js', '/web/path/to/Csrf.js');
}
// include_once '/path/to/csrf-magic.php';
(确保将Csrf.js放在可访问的Web位置)。
Csrf Magic用于重写AJAX请求的默认方法仅适用于支持XmlHttpRequest.prototype的浏览器(这排除了所有版本的Internet Explorer)。有关更多信息,请参阅此页面:http://stackoverflow.com/questions/664315/internet-explorer-8-prototypes-and-xmlhttprequest
Csrf.js将自动检测并友好地与以下JavaScript框架协同工作
* jQuery
* Prototype
* MooTools
* Ext
* Dojo
(注意:2013-07-16:这个手册支持已经很久没有更新了,一些JavaScript库已经将它们的XHR副本放在闭包中的局部变量中,这使得我们难以自动修补。)
要使用Csrf.js重写自己的JavaScript库,您应该修改生成XMLHttpRequest的函数,并在末尾添加以下内容
return new CsrfMagic(xhrObject);
与xhrObject相关。如果您的代码中有实际的XMLHttpRequest实例,请找到并替换 ''new XMLHttpRequest'' 为 ''new CsrfMagic''(CsrfMagic将根据需要以跨平台方式自动实例化XMLHttpRequest对象)。
如果您不希望csrf-magic篡改您的XMLHttpRequest对象,您可以手动重写您的AJAX代码以包含该变量。重要信息存储在全局变量csrfMagicName和csrfMagicToken中。CsrfMagic.process也可能很有用,因为它接受一个参数,即查询字符串,并将其附加到值的前面。
- 配置
csrf-magic 具有一些配置选项,您可以在 csrf_startup() 函数内设置。它们在 csrf-magic.php 中有描述,您可以使用便利函数 csrf_conf($name, $value) 来设置。
例如,这是一个推荐的配置
/**
* This is a function that gets called if a csrf check fails. csrf-magic will
* then exit afterwards.
*/
function my_csrf_callback() {
echo "You're doing bad things young man!";
}
function csrf_startup() {
// While csrf-magic has a handy little heuristic for determining whether
// or not the content in the buffer is HTML or not, you should really
// give it a nudge and turn rewriting *off* when the content is
// not HTML. Implementation details will vary.
if (isset($_POST['ajax'])) csrf_conf('rewrite', false);
// This is a secret value that must be set in order to enable username
// and IP based checks. Don't show this to anyone. A secret id will
// automatically be generated for you if the directory csrf-magic.php
// is placed in is writable.
csrf_conf('secret', 'ABCDEFG123456');
// This enables JavaScript rewriting and will ensure your AJAX calls
// don't stop working.
csrf_conf('rewrite-js', '/Csrf.js');
// This makes csrf-magic call my_csrf_callback() before exiting when
// there is a bad csrf token. This lets me customize the error page.
csrf_conf('callback', 'my_csrf_callback');
// While this is enabled by default to boost backwards compatibility,
// for security purposes it should ideally be off. Some users can be
// NATted or have dialup addresses which rotate frequently. Cookies
// are much more reliable.
csrf_conf('allow-ip', false);
}
// Finally, include the library
include_once '/path/to/csrf-magic.php';
配置存储在 $GLOBALS['csrf'] 数组中。
- 感谢
我要感谢 Chris Shiflett,他无意中启发了这个想法,并告诉我 Bob 和 Mallory 故事的原版,以及 Django CSRF 中间件作者,他们在我想之前就想到了这个。Gareth Heyes 建议 使用 frame-breaker 选项来防止 CSS 遮罩攻击。