目錄
回复内容:
首頁 後端開發 php教程 入侵 - PHP的防御XSS注入的终极解决方案【信息安全】【Hack】

入侵 - PHP的防御XSS注入的终极解决方案【信息安全】【Hack】

Jun 06, 2016 pm 08:23 PM
hack php 資訊安全 入侵 注入

Update20151202:
感谢大家的关注和回答,目前我从各种方式了解到的防御方法,整理如下:

  1. PHP直接输出html的,可以采用以下的方法进行过滤

    <code>1.htmlspecialchars函数
    2.htmlentities函数
    3.HTMLPurifier.auto.php插件
    4.RemoveXss函数(百度可以查到)</code>
    登入後複製
    登入後複製
  2. PHP输出到JS代码中,或者开发Json API的,则需要前端在JS中进行过滤

    <code>1.尽量使用innerText(IE)和textContent(Firefox),也就是jQuery的text()来输出文本内容
    2.必须要用innerHTML等等函数,则需要做类似php的htmlspecialchars的过滤(参照@eechen的答案)</code>
    登入後複製
    登入後複製
  3. 其它的通用的补充性防御手段

    <code>1.在输出html时,加上Content Security Policy的Http Header
    (作用:可以防止页面被XSS攻击时,嵌入第三方的脚本文件等)
    (缺陷:IE或低版本的浏览器可能不支持)
    2.在设置Cookie时,加上HttpOnly参数
    (作用:可以防止页面被XSS攻击时,Cookie信息被盗取,可兼容至IE6)
    (缺陷:网站本身的JS代码也无法操作Cookie,而且作用有限,只能保证Cookie的安全)
    3.在开发API时,检验请求的Referer参数
    (作用:可以在一定程度上防止CSRF攻击)
    (缺陷:IE或低版本的浏览器中,Referer参数可以被伪造)
    </code>
    登入後複製
    登入後複製

大概就是这些了,大家还有什么别的思路,欢迎补充!

——————————————————————————————————————————————————

原问题如下:

1.PHP如何完美(或者尽可能完美地)防御XSS攻击(比htmlspecialchars更完善的)?
2.我在想是不是防御XSS最好在前端做(毕竟JS在前端解析字符串都有坑啊)?
3.有木有什么解决方案或者思路啊,什么都行?

最近都在研究XSS防御的问题。

毕竟,比如用户注册的API,可能被Hacker利用,强行提交了"<script>alert('注入成功!')</script>"这样的用户名。

然后WEB前端怎么都要有显示用户名的地方吧。。。
于是。。。Boom。。。

直入重点:
我看到很多应对XSS的防御方案都是PHP的htmlentities函数或者htmlspecialchars。
随意百度了下,貌似ThinkPHP3.x默认就是用的htmlspecialchars。
比如:$str = htmlspecialchars($str, ENT_QUOTES);//替换掉&'"这5个字符
但是,只替换掉那几个字符真的够吗?

然后我发现了这个文章:
http://tieba.baidu.com/p/3003719171
使用\u003c\u003e在JS字符串中会被解释成的特性进行XSS攻击。。。
卧槽。。。

然后我想到了JS里的eval等等函数简直是无底洞。。。
然后我发现了这个文章:
http://www.2cto.com/Article/201310/251830.html
使用各种编码,各种手段执行JS,简直丧心病狂。
比如:入侵 - PHP的防御XSS注入的终极解决方案【信息安全】【Hack】

啊!CAO。
我开始怀疑整个世界了。。。
所以,
我的问题是:

1.PHP如何完美(或者尽可能完美地)防御XSS攻击(比htmlspecialchars更完善的)?
2.我在想是不是防御XSS最好在前端做(毕竟JS在前端解析字符串都有坑啊)?
3.有木有什么解决方案或者思路啊,什么都行?

Update20151201:
能不要再复制粘贴答案,or迷信htmlspecialchars是无敌的了好嘛?
\u003cimg src=1 onerror=alert(/xss/)\u003e里的任何一个字符都是不会被htmlspecialchars处理的。
自己看图,对,就是你!

入侵 - PHP的防御XSS注入的终极解决方案【信息安全】【Hack】

回复内容:

Update20151202:
感谢大家的关注和回答,目前我从各种方式了解到的防御方法,整理如下:

  1. PHP直接输出html的,可以采用以下的方法进行过滤

    <code>1.htmlspecialchars函数
    2.htmlentities函数
    3.HTMLPurifier.auto.php插件
    4.RemoveXss函数(百度可以查到)</code>
    登入後複製
    登入後複製
  2. PHP输出到JS代码中,或者开发Json API的,则需要前端在JS中进行过滤

    <code>1.尽量使用innerText(IE)和textContent(Firefox),也就是jQuery的text()来输出文本内容
    2.必须要用innerHTML等等函数,则需要做类似php的htmlspecialchars的过滤(参照@eechen的答案)</code>
    登入後複製
    登入後複製
  3. 其它的通用的补充性防御手段

    <code>1.在输出html时,加上Content Security Policy的Http Header
    (作用:可以防止页面被XSS攻击时,嵌入第三方的脚本文件等)
    (缺陷:IE或低版本的浏览器可能不支持)
    2.在设置Cookie时,加上HttpOnly参数
    (作用:可以防止页面被XSS攻击时,Cookie信息被盗取,可兼容至IE6)
    (缺陷:网站本身的JS代码也无法操作Cookie,而且作用有限,只能保证Cookie的安全)
    3.在开发API时,检验请求的Referer参数
    (作用:可以在一定程度上防止CSRF攻击)
    (缺陷:IE或低版本的浏览器中,Referer参数可以被伪造)
    </code>
    登入後複製
    登入後複製

大概就是这些了,大家还有什么别的思路,欢迎补充!

——————————————————————————————————————————————————

原问题如下:

1.PHP如何完美(或者尽可能完美地)防御XSS攻击(比htmlspecialchars更完善的)?
2.我在想是不是防御XSS最好在前端做(毕竟JS在前端解析字符串都有坑啊)?
3.有木有什么解决方案或者思路啊,什么都行?

最近都在研究XSS防御的问题。

毕竟,比如用户注册的API,可能被Hacker利用,强行提交了"<script>alert('注入成功!')</script>"这样的用户名。

然后WEB前端怎么都要有显示用户名的地方吧。。。
于是。。。Boom。。。

直入重点:
我看到很多应对XSS的防御方案都是PHP的htmlentities函数或者htmlspecialchars。
随意百度了下,貌似ThinkPHP3.x默认就是用的htmlspecialchars。
比如:$str = htmlspecialchars($str, ENT_QUOTES);//替换掉&'"这5个字符
但是,只替换掉那几个字符真的够吗?

然后我发现了这个文章:
http://tieba.baidu.com/p/3003719171
使用\u003c\u003e在JS字符串中会被解释成的特性进行XSS攻击。。。
卧槽。。。

然后我想到了JS里的eval等等函数简直是无底洞。。。
然后我发现了这个文章:
http://www.2cto.com/Article/201310/251830.html
使用各种编码,各种手段执行JS,简直丧心病狂。
比如:入侵 - PHP的防御XSS注入的终极解决方案【信息安全】【Hack】

啊!CAO。
我开始怀疑整个世界了。。。
所以,
我的问题是:

1.PHP如何完美(或者尽可能完美地)防御XSS攻击(比htmlspecialchars更完善的)?
2.我在想是不是防御XSS最好在前端做(毕竟JS在前端解析字符串都有坑啊)?
3.有木有什么解决方案或者思路啊,什么都行?

Update20151201:
能不要再复制粘贴答案,or迷信htmlspecialchars是无敌的了好嘛?
\u003cimg src=1 onerror=alert(/xss/)\u003e里的任何一个字符都是不会被htmlspecialchars处理的。
自己看图,对,就是你!

入侵 - PHP的防御XSS注入的终极解决方案【信息安全】【Hack】

这个问题我们还是先来请教一下砖家……

现在马上为我们连线场外的砖家……

嘟嘟嘟……

砖家您好,请问这位同学的问题您怎么看?

砖家:我趴在窗户上看……

……@#%&*!~~(@$%……

好了,原来砖家是说最近雾霾严重,所以他只能趴在窗户上看这个问题……

现在请听专家解读:

魔亦有道。

有专门的研究这些东西的,任何事只有专业领域的人做才会更有效率。

使用HTMLPurifier才是终极理想。

  1. http://www.xcoder.cn/index.php/archives/971

  2. http://willko.iteye.com/blog/475493

  3. http://www.piaoyi.org/php/HTML-Purifier-PHP-xss.html

  4. http://www.edu.cn/ji_shu_ju_le_bu_1640/20080717/t20080717_310285.shtml

  5. http://www.111cn.net/phper/phpanqn/78018.htm

  6. http://security.ctocio.com.cn/securitycomment/54/8222554.shtml

其实我还想说,我不希望防XSS这种事情交给前端,模板语言来做,对于前端,给她用什么就用什么,用的不爽自己适当的做变量调节就可以了。给她们用,让她们用的爽,用的简单,这是我们好男人的责任和义务,大家说对不对啊,嘻嘻。

首先,我想说,不要用你的无知来挑战大家

这是道高一尺魔高一丈的东西

html中的编码:

<code></code>
登入後複製
登入後複製

javascript中的编码:

<code></code>
登入後複製
登入後複製

当然 htmlspecialchars 肯定是不行的,只能进行简单的处理,要不然还讨论什么xss了

<code>The translations performed are:

'&' (ampersand) becomes '&'
'"' (double quote) becomes '"' when ENT_NOQUOTES is not set.
"'" (single quote) becomes ''' (or ') only when ENT_QUOTES is set.
'</code>
登入後複製

上面代码还可以这样写

<code><div id="a">test</div>
<div id="b">test</div>
<div id="c">test</div>
<a href="javasc&NewLine;ript&colon;alert(/xss/)">click</a> 
<a href="data:text/html;base64,%20PGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpPg==">test</a>
<script>
var a="\u003cimg src=1 onerror=alert(/xss/)\u003e";
var b="\74\151\155\147\40\163\162\143\75\170\40\157\156\145\162\162\157\162\75\141\154\145\162\164\50\61\51\76";
var c="\u003c\u0069\u006d\u0067\u0020\u0073\u0072\u0063\u003d\u0031\u0020\u006f\u006e\u0065\u0072\u0072\u006f\u0072\u003d\u0061\u006c\u0065\u0072\u0074\u0028\u002f\u0078\u0073\u0073\u002f\u0029\u003e";
document.getElementById("a").innerHTML=a;
document.getElementById("b").innerHTML=a;
document.getElementById("c").innerHTML=a;
</script></code>
登入後複製

但关键是,你确定你的那些代码可以提交吗?你要确定了再拿出来说

比如最简单的href加入以下代码基本上歇菜了

<code><base href="http://bbs.wdzj.com/"></code>
登入後複製

你到底有没有测试过,就说你提到的那些场景能够绕过htmlspecialchars呀,实践出真知.

<code><?php $nowdoc = <<<'nowdoc'
xss
nowdoc;
header('Content-Type: text/html;charset=utf-8');
echo htmlspecialchars($nowdoc, ENT_QUOTES, 'UTF-8');
</code></code>
登入後複製

补充:
你说的对,毕竟很多时候要把AJAX加载的数据用innerHTML添加到页面.
值得注意的是,innerHTML本质也是输出HTML,
所以我们可以在输出前用JS像PHP的htmlspecialchars那样
把特殊字符(&,",',)替换为HTML实体(&"'<>).
或者干脆直接用innerText(IE)和textContent(Firefox),也就是jQuery的text()来输出文本内容.
StackOverflow上找的两个实现:

<code>function escapeHtml(text) {
    return text
        .replace(/&/g, "&")
        .replace(/, "<")
        .replace(/>/g, ">")
        .replace(/"/g, """)
        .replace(/'/g, "'");
}
function escapeHtml(text) {
    var map = {
        '&': '&',
        '"']/g, function(m) { return map[m]; });
}</code>
登入後複製

方法一,利用php htmlentities函数

php防止XSS跨站脚本攻击的方法:是针对非法的HTML代码包括单双引号等,使用htmlspecialchars()函数 。

在使用htmlspecialchars()函数的时候注意第二个参数, 直接用htmlspecialchars($string) 的话,第二个参数默认是ENT_COMPAT,函数默认只是转化双引号(“), 不对单引号(‘)做转义。

所以,htmlspecialchars函数更多的时候要加上第二个参数, 应该这样用: htmlspecialchars($string,ENT_QUOTES).当然,如果需要不转化如何的引号,用htmlspecialchars($string,ENT_NOQUOTES)。

另外, 尽量少用htmlentities, 在全部英文的时候htmlentities和htmlspecialchars没有区别,都可以达到目的.但是,中文情况下, htmlentities却会转化所有的html代码,连同里面的它无法识别的中文字符也给转化了。

htmlentities和htmlspecialchars这两个函数对 '之类的字符串支持不好,都不能转化, 所以用htmlentities和htmlspecialchars转化的字符串只能防止XSS攻击,不能防止SQL注入攻击.

所有有打印的语句如echo,print等 在打印前都要使用htmlentities() 进行过滤,这样可以防止Xss,注意中文要写出htmlentities($name,ENT_NOQUOTES,GB2312) 。

方法二,给一个函数

<code>function xss_clean($data){
 // Fix &entity\n;
 $data=str_replace(array('&','<','>'),array('&amp;','&lt;','&gt;'),$data);
 $data=preg_replace('/(*\w+)[\x00-\x20]+;/u','$1;',$data);
 $data=preg_replace('/(*[0-9A-F]+);*/iu','$1;',$data);
 $data=html_entity_decode($data,ENT_COMPAT,'UTF-8');
 // Remove any attribute starting with "on" or xmlns
 $data=preg_replace('#(]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu','$1>',$data);
 // Remove javascript: and vbscript: protocols
 $data=preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu','$1=$2nojavascript...',$data);
 $data=preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu','$1=$2novbscript...',$data);
 $data=preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u','$1=$2nomozbinding...',$data);
 // Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
 $data=preg_replace('#(]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i','$1>',$data);
 $data=preg_replace('#(]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i','$1>',$data);
 $data=preg_replace('#(]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu','$1>',$data);
 // Remove namespaced elements (we do not need them)
 $data=preg_replace('#*\w+:\w[^>]*+>#i','',$data);
 // http://www.111cn.net/
 do{// Remove really unwanted tags
  $old_data=$data;
  $data=preg_replace('#*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i','',$data);
 }while($old_data!==$data);
 // we are done...
 return $data;
}</code>
登入後複製

想要“完美”防御XSS,就要每个开发都完全了解XSS的知识,在合适的场景用合适的方案来编码

推荐参考:
https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

任何用一个函数/一个库来解决这个问题的努力都是白日做梦。

重新再贴一边:
https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

永远不可能完美防御,但至少可以挡住99%(剩下的1%才是最凶猛的~~~),目前的统一做法是,做好输入检查,良好的编程意识,安全转义,借助第三方安全库。不要信任输入。也不要信任输出。

为什么不用 CSP 直接一了百了呢?

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

在PHP API中說明JSON Web令牌(JWT)及其用例。 在PHP API中說明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

您如何在PHP中解析和處理HTML/XML? 您如何在PHP中解析和處理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

解釋PHP中的晚期靜態綁定(靜態::)。 解釋PHP中的晚期靜態綁定(靜態::)。 Apr 03, 2025 am 12:04 AM

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

php程序在字符串中計數元音 php程序在字符串中計數元音 Feb 07, 2025 pm 12:12 PM

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? 什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? Apr 03, 2025 am 12:03 AM

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。

PHP和Python:比較兩種流行的編程語言 PHP和Python:比較兩種流行的編程語言 Apr 14, 2025 am 12:13 AM

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

See all articles