作者GALINE (天真可爱CQD)
看板PHP
标题Re: [请益] textarea中的html标签(emoji)
时间Thu Jul 21 11:17:55 2016
直接写一篇可能比较清楚
「存资料的时候应该存未处理过的原始资料,吐 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,你必须保留原始的输入资料
--
这闪电拳能射出雷射光,威力每平方公分一万亿瓦特
威力无比,拳到之处,攻无不克
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 60.248.122.206
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/PHP/M.1469071079.A.9CD.html
1F:推 MOONRAKER: Yea, use the source 07/21 12:03
※ 编辑: GALINE (60.248.122.206), 07/21/2016 13:00:59
2F:推 Kenqr: 推 07/21 13:17
3F:推 kajm: 感谢G大分享,这篇真的很实用,尤其对我这种新手 QQ 07/21 13:35
4F:→ kajm: 另外想补问,用了escape是否就无法使用n2lbr? 可是这样取jso 07/21 13:36
5F:→ kajm: n格式时,会被换行符号断行.. 用了n2lbr会变成取<br> 囧! 07/21 13:37
6F:→ MOONRAKER: 可以先htmlspecialchars()再nl2br()阿 07/21 16:25
7F:→ MOONRAKER: 还是你escape的情况不一样 07/21 16:25
8F:推 kajm: 我是希望能像Dcard取留言的json格式一样,像是这样: 07/21 16:55
10F:→ kajm: 可是我用n2lbr的话,会在json变成<br>,然後在urldecode()後 07/21 16:56
11F:→ kajm: 就会变成断行了 07/21 16:57
12F:推 xdraculax: 断行经过json_encode就会变\n不需要先nl2br啊 07/22 11:05
13F:推 kajm: 感谢各位前辈指点,後来发现header没设定到json格式,才衍伸 07/25 02:09
14F:→ kajm: 很多问题出来 XD 07/25 02:09