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