如何使ajax评论系统安全

时间:2014-05-27 19:51:30

标签: php ajax regex security

我正在使用这样的评论系统:(我已经简化了这个问题的代码)

 <?php
        $status_ui = '<textarea id="box"></textarea>';
        $status_ui .= '<button id="status_button" onclick="postComment(\'box\')">Post</button>';
    ?>
    <html>
    <head>
        <script type="text/javascript">
        function postComment(box){
            var data = document.getElementById(box).value;
            data = data.replace(/[^a-zA-Z0-9,.?! ;:'"]+/, '');  
            var hr = new XMLHttpRequest();
            hr.open("POST", "comment_system.php", true);
            hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            hr.onreadystatechange = function() {
                if(hr.readyState == 4 && hr.status == 200) {
                    var html_output = "";
                        current_html = document.getElementById("comment_list").innerHTML;                   
                        html_output +=  '<div class="comment">';
                        html_output +=      data;
                        html_output +=  '</div>';
                        document.getElementById("comment_list").innerHTML = html_output + current_html;
                    }
                    results_box.innerHTML = html_output;
                }
            }
            hr.send("comment="+data);
        </script>
    </head>
    <body>
        <div id="container">
            <?php echo $status_ui; ?>        
            <div id="comment_list"></div>
        </div>
    </body>
    </html>

用户只能输入a-zA-Z0-9,。?! ;:&#39;&#34;一切都很酷。

在comment_system.php中,我正在执行各种检查,正则表达式,以便将数据安全地存储到数据库中。问题是:如何安全地将用户注释输出到comment_list div作为XSS证明?

我正在使用string.replace,我知道坏用户可以绕过它。

1 个答案:

答案 0 :(得分:2)

                    html_output +=  '<div class="comment">';
                    html_output +=      data;
                    html_output +=  '</div>';

这是HTML注入,导致客户端跨站点脚本(DOM-XSS)漏洞。

要停止评论div中包含的有效HTML内容,请执行以下操作:

  • 转义数据中的HTML特殊字符(例如<&lt;
  • (更好)使用DOM方法在div元素中设置文本而不是尝试创建标记
  

document.getElementById(&#34; comment_list&#34;)。innerHTML = html_output + current_html;

这是一个坏主意。每次调用它时,您都会将注释列表的全部内容序列化为新的HTML标记字符串,添加到字符串,销毁注释列表中的所有元素,以及从标记中解析新元素。这很慢并且容易出现重新编码错误,这也可能导致DOM-XSS(IE在反引号字符方面遇到问题 - 阅读innerHTML并不一定能为您提供一个可以安全重新分配给{的字符串{1}})。

再次,通过使用DOM方法创建内容来避免这种情况:

innerHTML

(类似于结果框。)现在用户输入中可能出现的有趣字符并不重要,您将始终正确显示。因此,您可以允许用户键入一个较少的符号,而不会破坏他们的评论。

  

在comment_system.php中,我正在执行各种检查,正则表达式,以便将数据安全地存储到数据库中。

输入过滤有它的位置,但它不是SQL注入的答案。您应该使用查询参数化(使用mysqli或PDO)将数据导入数据库,而不是创建包含数据的查询。然后,再次,任何输入都是安全的,您可以允许用户键入撇号而不会破坏他们的评论。