Re: [請益] textarea中的html標籤(emoji)

作者: GALINE (天真可愛CQD)   2016-07-21 11:17:55
直接寫一篇可能比較清楚
「存資料的時候應該存未處理過的原始資料,吐 html 的時候才做 escape」
原因有幾個
- 你先 escape 了以後,你就沒有原始資料,只剩下加料過的資料
- 東西不見得塞在 HTML 裡面,不同的地方要做不同的 escape
- 萬一未來發現了新的攻擊方法,你有機會改 code 應對,而不是進 DB 改資料
===============================================================
第一點跟第三點我就不特別討論了,這邊專注在第二點上
範例像這樣
<h1><?= $title?></h1>
<script>alert("標題是<?= $title?>")</script>
如果你存檔的時候就做 $title = htmlspecialchars($title)
那麼你就會不知道該怎麼對 javascript 做處理,於是
- <最新>高雄宇宙港遭恐怖份子攻擊
- h1 會顯示,但 script 會噴出怪訊息
- 群星齊唱"愛還記得嗎"
- h1 會顯示,但 script 會爛掉
而且完全可以寫出不會被 htmlspecialchars 影響的 xss...
正解會是這樣
<h1><?= htmlspecialchars($title)?></h1>
<script>alert("標題是" + <?= json_encode($title)?>)</script>
這些問題就算你用 template engine 也還是得注意,頂多是做起來比較輕鬆
例如 twig,預設是當成 html 來 escape,所以
<h1>{{ title }}</h1>
<script>alert("標題是{{ title }}")</script>
還是會死在 javascript,正確的做法是
<h1>{{ title }}</h1>
<script>alert("標題是{{ title|e('js') }}")</script>
BTW,這邊有個隱藏大魔王叫做 URL
雖然塞在 html 裡面,但是用 htmlspecialchars() 清理是不夠的
因為有 data: 跟 javascript: 這種東西可以用,讓 escape 變得很麻煩
這邊建議用第三方 lib 來處理(例如 htmlpurifier),或根本不讓使用者自填 url...
===============================================================
總之,你在不同的地方,需要用不同的方式 escape 資料
「事先 escape 然後到處通用」這條路...很可惜的是不通的
而為了讓每個地方都能正確的 escape,你必須保留原始的輸入資料
作者: MOONRAKER (㊣牛鶴鰻毛人)   2016-07-21 12:03:00
Yea, use the source
作者: Kenqr (function(){})()   2016-07-21 13:17:00
作者: kajm (kajm)   2016-07-21 13:35:00
感謝G大分享,這篇真的很實用,尤其對我這種新手 QQ另外想補問,用了escape是否就無法使用n2lbr? 可是這樣取json格式時,會被換行符號斷行.. 用了n2lbr會變成取<br> 囧!
作者: MOONRAKER (㊣牛鶴鰻毛人)   2016-07-21 16:25:00
可以先htmlspecialchars()再nl2br()阿還是你escape的情況不一樣
作者: kajm (kajm)   2016-07-21 16:55:00
我是希望能像Dcard取留言的json格式一樣,像是這樣:https://goo.gl/qgExPE 裡面把換行換成\n,其他都能正常顯示可是我用n2lbr的話,會在json變成<br>,然後在urldecode()後就會變成斷行了
作者: xdraculax (首席怪叔叔)   2016-07-22 11:05:00
斷行經過json_encode就會變\n不需要先nl2br啊
作者: kajm (kajm)   2016-07-25 02:09:00
感謝各位前輩指點,後來發現header沒設定到json格式,才衍伸很多問題出來 XD

Links booklink

Contact Us: admin [ a t ] ucptt.com