前言:
最近有一份招聘,引起了我对网络安全的极大兴趣。非常感兴趣的决定研究下yii中的安全特性。在应用yii开发的时候知道怎么用安全特性,但一些原理没有去理会过。参考:http://blog.csdn.net/baidu_zhongce/article/details/50394178
防SQL注入
SQL 注入虽然是最低级的Web安全内容了。但还是说一下吧,yii中我们采用
Model::find->where('param=:param',[':param'=>$param]);
来处理sql注入。于是我查看where的代码,本以为是yii获取了这个$param值之后先做了处理,比如转义之类的。但实际上并没有,只是mysql数据库查询占位符本身可以防sql,数据库厂商对占位符做了转义。
http://blog.csdn.net/yan465942872/article/details/6753957
参考这篇文章,虽然他说的是java中jdk提供接口,yii中应该也是同样原理。
防XSS 跨站脚本攻击(Cross Site Scripting)
http://netsecurity.51cto.com/art/201408/448305.htm
XSS原理请参考这篇文章,非常详细明确。
这种漏洞的主要危害就是攻击者提交了一个js代码在网站上(比如留言板之类的),js虽然操作不了服务端,但在客户端可做的事情可多了。当网站使用者(登录用户)登录时,会运行这段js代码,相信各位做开发的童鞋们已经想到怎么用一段js获取客户端的cookie,然后再异步提交到自己的某个服务器数据库。。对,然后再通过cookie欺骗获得登录。
yii的防护原理:
1. 通过yii/helper/Html继承BaseHtml的encode方法对代码进行html实体编码,所有js代码都会变成html代码,我们看下源码:
/**
* Encodes special characters into HTML entities.
* The [[\yii\base\Application::charset|application charset]] will be used for encoding.
* @param string $content the content to be encoded
* @param bool $doubleEncode whether to encode HTML entities in `$content`. If false,
* HTML entities in `$content` will not be further encoded.
* @return string the encoded content
* @see decode()
* @see http://www.php.net/manual/en/function.htmlspecialchars.php
*/
public static function encode($content, $doubleEncode = true)
{
return htmlspecialchars($content, ENT_QUOTES | ENT_SUBSTITUTE, Yii::$app ? Yii::$app->charset : 'UTF-8', $doubleEncode);
}
- 利用yii/helper/HtmlPurifier 继承的BaseHtmlPurifier的process方法来对代码进行过滤,去除掉js代码。利用的是lexer词法分析。
/**
* Passes markup through HTMLPurifier making it safe to output to end user
*
* @param string $content The HTML content to purify
* @param array|\Closure|null $config The config to use for HtmlPurifier.
* If not specified or `null` the default config will be used.
* You can use an array or an anonymous function to provide configuration options:
*
* - An array will be passed to the `HTMLPurifier_Config::create()` method.
* - An anonymous function will be called after the config was created.
* The signature should be: `function($config)` where `$config` will be an
* instance of `HTMLPurifier_Config`.
*
* Here is a usage example of such a function:
*
* ```php
* // Allow the HTML5 data attribute `data-type` on `img` elements.
* $content = HtmlPurifier::process($content, function ($config) {
* $config->getHTMLDefinition(true)
* ->addAttribute('img', 'data-type', 'Text');
* });
* ```
*
* @return string the purified HTML content.
*/
public static function process($content, $config = null)
{
$configInstance = \HTMLPurifier_Config::create($config instanceof \Closure ? null : $config);
$configInstance->autoFinalize = false;
$purifier = \HTMLPurifier::instance($configInstance);
$purifier->config->set('Cache.SerializerPath', \Yii::$app->getRuntimePath());
$purifier->config->set('Cache.SerializerPermissions', 0775);
static::configure($configInstance);
if ($config instanceof \Closure) {
call_user_func($config, $configInstance);
}
return $purifier->purify($content);
}
CSRF (Cross-site request forgery)跨站请求伪造
https://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html
CSRF 的原理解析可以参考这篇文章。
主要问题在于:CSRF攻击是源于WEB的隐式身份验证机制!WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的。即一个用户访问某个危险网站的时候,存在客户端的其他网页的cookie可能被这个网站利用。
防护:
1. 首先是注意代码中不要使用$_REQUEST
来获取表单提交的数据,否则会使得GET请求也能替代POST请求,这点在文章中提示过。yii中基本上是用Yii::$app->request->post
来获取表单提交的数据,就不会出现这个问题。另外GET请求只允许做查询,不允许做其他修改,这个要注意。
2. POST请求中加入一些可以被服务器识别的随机数值,用来保证数据的来源和运行结果发送去向是相同的。这点Yii2.0实现了一个CSRF防范机制,
'components' => [
'request' => [
'csrfParam' => '_csrf-frontend',
],
],
机制的核心是:从cookie或者session里取出token(没有的话就要先初始化,设置这个token)随机产生CSRF_MASK_LENGTH(Yii2里默认是8位)长度的字符串 mask,再对mask和token进行加密,生成csrf。解密的时候主要是从csrfToken里取出token 然后和会话里的token比较,当然要经过解密和分离随机数。
<input type="hidden" name="_csrf-frontend" value="QScHjSiIXMrE81FaXNTCoXd4ZMLlwXLQfTOlsBGd1KdQLvYEnpLC0ykHn1hPoTn9vM2VQuVTpV6CnQh4cX9Egg==">
具体的
http://www.linuxidc.com/Linux/2016-11/137225.htm
COOKIE验证机制
上面讲到的XSS攻击,窃取cookie,之后就会通过cookie欺骗来实现非法登录。yii中也有一个cookie验证机制,可以防止cookie被修改。启用之后可以对cookie的值进行HMAC检查。启用之后要用内置的cookies集合来访问cookie。
return array(
'components'=>array(
'request'=>array(
'enableCookieValidation'=>true,
),
),
);
// 检索一个名为$name的cookie值
$cookie = Yii::app()->request->cookies[$name];
$value = $cookie->value;
...
// 设置一个cookie
$cookie = new CHttpCookie($name, $value);
Yii::app()->request->cookies[$name] = $cookie;
密码加密
大部分开发者知道密码不能以明文形式存储,但是许多开发者仍认为使用 md5 或者 sha1 来哈希化密码是安全的。 一度,使用上述的哈希算法是足够安全的,但是, 现代硬件的发展使得短时间内暴力破解上述算法生成的哈希串成为可能。
为了即使在最糟糕的情况下(你的应用程序被破解了)也能给用户密码提供增强的安全性, 你需要使用一个能够对抗暴力破解攻击的哈希算法。目前最好的选择是 bcrypt。在 PHP 中, 你可以通过 crypt 函数 生成 bcrypt 哈希。 Yii 提供了两个帮助函数以让使用 crypt 来进行安全的哈希密码生成和验证更加容易。
这是yii文档的原话。
//加密
$this->password = Yii::$app->security->generatePasswordHash($this->password);
//解密
if (Yii::$app->getSecurity()->validatePassword($password, $hash)) {
// all good, logging user in
} else {
// wrong password
}
对magic_quotes_gpc的判断
magic_quotes_gpc函数在php中的作用是判断解析用户提示的数据,如包括有:post、get、cookie过来的数据增加转义字符“\”,以确保这些数据不会引起程序,特别是数据库语句因为特殊字符引起的污染而出现致命的错误.
if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
if(isset($_GET))
$_GET=$this->stripSlashes($_GET);
if(isset($_POST))
$_POST=$this->stripSlashes($_POST);
if(isset($_REQUEST))
$_REQUEST=$this->stripSlashes($_REQUEST);
if(isset($_COOKIE))
$_COOKIE=$this->stripSlashes($_COOKIE);
}
访问控制过滤器
yii实现了访问控制器,只需要调用就可以用来过滤权限,另外配合角色权限,可以发挥非常棒的功能。控制器中重载了filters方法来进行设置。
开发模式
在开发模式中才能看到调试信息,保护代码。