CSRF及XSS基础知识
定义(个人理解)
CSRF(Cross Site Request Forgery 跨站请求伪造),用户(客户端)登录了A网站(被攻击者),然后打开了B网站(攻击者),B在页面内嵌有某个A的资源URL,诱导用户点击或页面加载时自动调用,浏览器会自动把保存的cookie也一并发送过去,B的操作请求就被服务端误认为是用户自己发起的。
XSS(Cross Site Scriping 跨站脚本),重点在脚本,不一定是跨站的,具体可以分为好几种。常见比如 input 框中输入脚本,浏览器编辑运行脚本,在网站上嵌入脚本通过document.cookie()
获取cookie等。
这俩有点类似,都是利用客户端进行攻击。区别在于 XSS利用站点内的信任用户进行脚本操作,包括但不限于获取用户cookie进行下一步操作。而CSRF本质上是借用用户cookie执行非用户本意的操作,但攻击方本身并未获取用户cookie。
防范措施
CSRF:
- 涉及到资源修改的操作,一定要用POST而不是GET
- 可对请求增加
csrf_token
(CI和Laravel都用的这种) - 后端关键操作前判断referrer(若客户端浏览器有漏洞,可伪造referrer,因而不完全可靠)
XSS:
- 关键 cookie,要设置 http-only,禁止通过 JS 获取(在
php.ini
可设置 PHP session 的属性)
; Whether or not to add the httpOnly flag to the cookie, which makes it inaccessible to browser scripting languages such as JavaScript.
; http://php.net/session.cookie-httponly
session.cookie_httponly = 1
- 不信任用户输入,对所有输入和参数进行过滤
相关阅读
CI - 安全类
csrf攻击、为关键cookie设置httpOnly属性(防止xss攻击)安全问题
CSRF的详细介绍与token的分析
CSRF 攻击的应对之道(讲的很清晰就是时间略久远)
前端安全之XSS攻击
CI - CSRF
基本思路:在表单中增加隐藏input,值为随机hash值,提交到服务端后与cookie中的hash值进行比对。每次提交后,重新生成token和cookie中的值。这里以CI为例,Laravel中的思路也基本相同。
配置
/*
|--------------------------------------------------------------------------
| Cross Site Request Forgery
|--------------------------------------------------------------------------
| Enables a CSRF cookie token to be set. When set to TRUE, token will be
| checked on a submitted form. If you are accepting user data, it is strongly
| recommended CSRF protection be enabled.
|
| 'csrf_token_name' = The token name
| 'csrf_cookie_name' = The cookie name
| 'csrf_expire' = The number in seconds the token should expire.
*/
config.php
表单
/**
* Form Declaration
*
* Creates the opening portion of the form.
*
* @access public
* @param string the URI segments of the form destination
* @param array a key/value pair of attributes
* @param array a key/value pair hidden data
* @return string
*/
if ( ! function_exists('form_open'))
{
function form_open($action = '', $attributes = '', $hidden = array())
{
$CI =& get_instance();
if ($attributes == '')
{
$attributes = 'method="post"';
}
// If an action is not a full URL then turn it into one
if ($action && strpos($action, '://') === FALSE)
{
$action = $CI->config->site_url($action);
}
// If no action is provided then set to the current url
$action OR $action = $CI->config->site_url($CI->uri->uri_string());
$form = '<form action="'.$action.'"';
$form .= _attributes_to_string($attributes, TRUE);
$form .= '>';
// Add CSRF field if enabled, but leave it out for GET requests and requests to external websites
if ($CI->config->item('csrf_protection') === TRUE AND ! (strpos($action, $CI->config->base_url()) === FALSE OR strpos($form, 'method="get"')))
{
$hidden[$CI->security->get_csrf_token_name()] = $CI->security->get_csrf_hash();
}
if (is_array