php htmlspecialchars xss,PHP htmlspecialchars不能防御前端innerHTML产生的XSS注入

不要在JS里直接用innerHTML输出未经JS过滤的用户内容,

即使这些内容已经经过服务器端PHP的htmlspecialchars或者HTMLPurifier过滤.

比如下面的代码,页面将alert弹出字符串/xss/,因为JS会把变量中的Unicode字符\u003c和\u003e转换成输出.

//1

$xss = '\u003cimg src=1 οnerrοr=alert(/xss/)\u003e';

//XSS

$xss = '\u003ca href=javascript:alert(String.fromCharCode(88,83,83))\u003eXSS\u003c/a\u003e';

header('Content-Type: text/html;charset=utf-8');

?>

// PHP的htmlspecialchars不能过滤\u003c和\u003e,经过JS赋值后,Unicode字符\u003c和\u003e被转换成.

var xss = '<?php echo htmlspecialchars($xss, ENT_QUOTES, 'UTF-8'); ?>';

console.log(xss);

//$("#xss").html(xss); //能够执行alert(/xss/) document.getElementById("xss").innerHTML = xss;

//$("#xss").html(xss.replace(//g, ">")); //不能执行alert(/xss/)

//$("#xss").text(xss); //不能执行alert(/xss/) document.getElementById("xss").innerText = xss;

$(#xss).append(xss)跟$("#xss").html(xss)输出的都是HTML.

解决方法:

http://segmentfault.com/q/1010000004067521

毕竟很多时候要把AJAX加载的数据用innerHTML添加到页面.

值得注意的是,innerHTML本质也是输出HTML,

所以我们可以在输出前用JS像PHP的htmlspecialchars那样

把特殊字符(&,",',)替换为HTML实体(&"'<>).

或者干脆直接用innerText(IE)和textContent(Firefox),也就是jQuery的text()来输出文本内容.

Firefox不支持IE的innerText,但支持textContent.

StackOverflow上找到的两个实现:

function htmlspecialchars(str) {

return str

.replace(/&/g, "&")

.replace(/

.replace(/>/g, ">")

.replace(/"/g, """)

.replace(/'/g, "'");

}

function htmlspecialchars(str) {

var map = {

'&': '&',

'

'>': '>',

'"': '"',

"'": '''

};

return str.replace(/[&<>"']/g, function(k) { return map[k]; });

}

其中g表示全局(global)替换的意思,也就是把字符串中的所有匹配的内容都进行替换.

不过JS模仿PHP的htmlspecialchars是一刀切的方法,数据将丧失HTML特性.

请教下,对于前端AJAX(PJAX)过来后的HTML数据大家是怎么过滤XSS输出的呢?

经过PJAX测试后发现,AJAX返回的数据用jQuery的html()函数插入并不会因为Unicode字符\u003c和\u003e而发生XSS.

index.php:

Index

data.php

$(document).ready(function() {

$('#main').on('click','a',function(e) {

if(window.history.pushState) {

e.preventDefault(); //不跟随原链接跳转

url = $(this).attr('href');

$.ajax({

async: true,

type: 'GET',

url: 'data.php',

data: 'pjax=1',

success: function(data) {

window.history.pushState(null, null, url); //改变URL和添加返回历史

document.title = data.title; //设置标题

$('#main').html(data.main); //这里并不会因为Unicode字符\u003c和\u003e而发生XSS

//$('#main').html('\u003cimg src=1 οnerrοr=alert(/xss/)\u003e'); //直接赋值字符串则会发生XSS

}

});

} else {

return; //低版本IE8等不支持HTML5 pushState,直接返回进行链接跳转

}

});

});

data.php:

if(isset($_GET['pjax'])) {

//PJAX请求返回JSON

$arr['title'] = 'Data';

$arr['main'] = '\u003cimg src=1 οnerrοr=alert(/xss/)\u003e';

header('Content-Type: application/json; charset=utf-8');

echo json_encode($arr);

} else {

//常规请求返回HTML

?>

Data
\u003cimg src=1 οnerrοr=alert(/xss/)\u003e
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值