我正在使用Codeigniter
并通过其CSRF
文件启用config.php
...
$config['csrf_protection'] = TRUE;
$config['csrf_token_name'] = 'csrf_token_name';
$config['csrf_cookie_name'] = 'csrf_cookie_name';
然后在我的ajax请求中我得到了cookie name
var cct = $.cookie('csrf_cookie_name');
和parameters
:
csrf_token_name : cct
我的问题:我是否需要做其他事情或那就是它?
答案 0 :(得分:7)
好的,CSRF的大多数common case(或最容易实现)是这样的:
<img src="http://bank.example.com/withdraw?account=bob&amount=1000000&for=Fred" />
因此,如果您假设您已登录bank.example.com
,那么您的Cookie是“活着的”并将随请求一起发送,因此请求将执行攻击者想要的操作,因此:
你能做什么:
尽可能多地通过POST
发送请求(无需打扰用户),尤其是编辑,创建和删除。将安全性隐藏到input type='hidden'
比隐藏到URL更容易。
检查referrer(是的,这件小事阻止了几乎所有来自外部网站的CSRF攻击):
$url = parse_url( isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '');
if( isset( $url['host']) && ($url['host'] == $_SERVER['SERVER_NAME'])){
// Request have a go
}
将临时安全令牌添加到此/article/delete/25/axdefm
...
如果您花了一些时间生成不错的网址,那么您将被发送,因为这只会搞砸它们,这会带来一些问题,例如:
您可以为安全令牌创建表格,例如:
tokens (
id INT,
user_id INT,
created DATETIME,
expires DATETIME, -- One of those two should be enough
value CHAR(30),
PRIMARY (id),
FOREIGN KEY (user_id) ...
);
当某些操作需要授权令牌时,您将从数据库中加载最后一个或创建新令牌,假设只有当所有可用的令牌都超过15分钟时才会创建新令牌:
function getToken( $userId, $eventIdentificator){
// Hope this is self explanatory :)
$db->deleteExpiredTokens();
// Try to load token newer than 15 minutes
$row = $db->fetchRow( 'SELECT value FROM tokens WHERE created >= ADD_INTERVAL( NOW(), -15 MINUTES) AND user_id = ?', array( $userId));
// createToken will return `value` directly
if( !$row){
$row = createNewToken( $userId);
} else {
$row = $row['value'];
}
// Real token will be created as sha1( 'abacd' . 'delete_article_8');
return sha1( $row . $eventIdentificator);
}
echo 'url?token=' . getToken( $userId, 'delete_article_' . $article['id']);
这将如何行动:
如何检查令牌?
function checkToken( $userId, $eventIdentificator, $token){
$db->deleteExpiredTokens();
// Just find matching token with brute force
$rs = $db->fetch_rowset( 'SELECT value FROM tokens WHERE created >= ADD_INTERVAL( NOW(), -15 MINUTES) AND user_id = ?', array( $userId));
while( $row = $rs->fetch_row){
if( $token == sha1( $row['value'] . $eventIdentificator)){
return true;
}
}
return false;
}
如果你不确定动作不会发生两次(例如编辑文章,这适用于删除)只需添加revision_number
或类似于$eventIdentificator
的内容。)< / p>
尝试思考如果会发生什么:
我会使用上面提到的令牌系统,感觉就像用户舒适度/实现复杂性和安全性之间的平衡解决方案,预期的意见和注释的评论:)
答案 1 :(得分:4)
防止跨站点请求伪造(CSRF)攻击的最常用方法是将不可预测的质询标记附加到每个请求并将其与用户的会话关联。
CodeIgniter中的CSRF保护为您完成,所以我认为没关系; - )