入侵 - PHP的防禦XSS注入的終極解決方案【資訊安全】【Hack】

來源:互聯網
上載者:User

Update20151202:
感謝大家的關注和回答,目前我從各種方式瞭解到的防禦方法,整理如下:

  1. PHP直接輸出html的,可以採用以下的方法進行過濾

    1.htmlspecialchars函數2.htmlentities函數3.HTMLPurifier.auto.php外掛程式4.RemoveXss函數(百度可以查到)
  2. PHP輸出到JS代碼中,或者開發Json API的,則需要前端在JS中進行過濾

    1.盡量使用innerText(IE)和textContent(Firefox),也就是jQuery的text()來輸出常值內容2.必須要用innerHTML等等函數,則需要做類似php的htmlspecialchars的過濾(參照@eechen的答案)
  3. 其它的通用的補充性防禦手段

    1.在輸出html時,加上Content Security Policy的Http Header(作用:可以防止頁面被XSS攻擊時,嵌入第三方的指令檔等)(缺陷:IE或低版本的瀏覽器可能不支援)2.在設定Cookie時,加上HttpOnly參數(作用:可以防止頁面被XSS攻擊時,Cookie資訊被盜取,可相容至IE6)(缺陷:網站本身的JS代碼也無法操作Cookie,而且作用有限,只能保證Cookie的安全)3.在開發API時,檢驗請求的Referer參數(作用:可以在一定程度上防止CSRF攻擊)(缺陷:IE或低版本的瀏覽器中,Referer參數可以被偽造)

大概就是這些了,大家還有什麼別的思路,歡迎補充!

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

原問題如下:

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

最近都在研究XSS防禦的問題。

畢竟,比如使用者註冊的API,可能被Hacker利用,強行提交了""這樣的使用者名稱。

然後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,簡直喪心病狂。
比如:

啊!CAO。
我開始懷疑整個世界了。。。
所以,
我的問題是:

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

Update20151201:
能不要再複製粘貼答案,or迷信htmlspecialchars是無敵的了好嘛?
\u003cimg src=1 onerror=alert(/xss/)\u003e裡的任何一個字元都是不會被htmlspecialchars處理的。
自己看圖,對,就是你!

回複內容:

Update20151202:
感謝大家的關注和回答,目前我從各種方式瞭解到的防禦方法,整理如下:

  1. PHP直接輸出html的,可以採用以下的方法進行過濾

    1.htmlspecialchars函數2.htmlentities函數3.HTMLPurifier.auto.php外掛程式4.RemoveXss函數(百度可以查到)
  2. PHP輸出到JS代碼中,或者開發Json API的,則需要前端在JS中進行過濾

    1.盡量使用innerText(IE)和textContent(Firefox),也就是jQuery的text()來輸出常值內容2.必須要用innerHTML等等函數,則需要做類似php的htmlspecialchars的過濾(參照@eechen的答案)
  3. 其它的通用的補充性防禦手段

    1.在輸出html時,加上Content Security Policy的Http Header(作用:可以防止頁面被XSS攻擊時,嵌入第三方的指令檔等)(缺陷:IE或低版本的瀏覽器可能不支援)2.在設定Cookie時,加上HttpOnly參數(作用:可以防止頁面被XSS攻擊時,Cookie資訊被盜取,可相容至IE6)(缺陷:網站本身的JS代碼也無法操作Cookie,而且作用有限,只能保證Cookie的安全)3.在開發API時,檢驗請求的Referer參數(作用:可以在一定程度上防止CSRF攻擊)(缺陷:IE或低版本的瀏覽器中,Referer參數可以被偽造)

大概就是這些了,大家還有什麼別的思路,歡迎補充!

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

原問題如下:

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

最近都在研究XSS防禦的問題。

畢竟,比如使用者註冊的API,可能被Hacker利用,強行提交了""這樣的使用者名稱。

然後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,簡直喪心病狂。
比如:

啊!CAO。
我開始懷疑整個世界了。。。
所以,
我的問題是:

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

Update20151201:
能不要再複製粘貼答案,or迷信htmlspecialchars是無敵的了好嘛?
\u003cimg src=1 onerror=alert(/xss/)\u003e裡的任何一個字元都是不會被htmlspecialchars處理的。
自己看圖,對,就是你!

這個問題我們還是先來請教一下磚家……

現在馬上為我們連線場外的磚家……

嘟嘟嘟……

磚家您好,請問這位同學的問題您怎麼看?

磚家:我趴在窗戶上看……

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

好了,原來磚家是說最近霧霾嚴重,所以他只能趴在窗戶上看這個問題……

現在請聽專家解讀:

魔亦有道。

有專門的研究這些東西的,任何事只有專業領域的人做才會更有效率。

使用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中的編碼:

< 進行編碼html十進位: <  html十六進位:<url: %3C  base64: PA==

javascript中的編碼:

<  進行編碼八進位:\74  十六進位:\x3c unicode:\u003c

當然 htmlspecialchars 肯定是不行的,只能進行簡單的處理,要不然還討論什麼xss了

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.'<' (less than) becomes '<''>' (greater than) becomes '>'

上面代碼還可以這樣寫

testtesttestclick test

但關鍵是,你確定你的那些代碼可以提交嗎?你要確定了再拿出來說

比如最簡單的href加入以下代碼基本上歇菜了

你到底有沒有測試過,就說你提到的那些情境能夠繞過htmlspecialchars呀,實踐出真知.

補充:
你說的對,畢竟很多時候要把AJAX載入的資料用innerHTML添加到頁面.
值得注意的是,innerHTML本質也是輸出HTML,
所以我們可以在輸出前用JS像PHP的htmlspecialchars那樣
把特殊字元(&,",',<,>)替換為HTML實體(&"'<>).
或者乾脆直接用innerText(IE)和textContent(Firefox),也就是jQuery的text()來輸出常值內容.
StackOverflow上找的兩個實現:

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

方法一,利用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) 。

方法二,給一個函數

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('/(&#x*[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:  $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('#]*+>#i','',$data); // http://www.111cn.net/ do{// Remove really unwanted tags  $old_data=$data;  $data=preg_replace('#]*+>#i','',$data); }while($old_data!==$data); // we are done... return $data;}

想要“完美”防禦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 直接一了百了呢?

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.