PHP htmlspecialchars不能防禦前端innerHTML產生的XSS注入
來源:互聯網
上載者:User
不要在JS裡直接用innerHTML輸出未經JS過濾的使用者內容,
即使這些內容已經經過伺服器端PHP的htmlspecialchars或者HTMLPurifier過濾.
比如下面的代碼,頁面將alert彈出字串/xss/,因為JS會把變數中的Unicode字元\u003c和\u003e轉換成<和>輸出.
//
$xss = '\u003cimg src=1 onerror=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');
?>
$(#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輸出的呢?