V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
Forviler
V2EX  ›  JavaScript

今天被测试发了一个 xss 漏洞,之前明明做过 xss 过滤的,很纳闷的看了一下

  •  
  •   Forviler · 362 天前 · 4494 次点击
    这是一个创建于 362 天前的主题,其中的信息可能已经有所发展或是发生改变。

    之前做过 xss 过滤 用的 js-xss

    之前测试也都是正常的

    今天看到他的测试内容: < img/src=1 onerror='top.onerror=alert; throw 2'>

    看到这个 “/” 好像明白了什么, 不过为什么这种也会被浏览器识别成 img 标签 很纳闷

    然后去看 js-xss 的 issues 发现了好像一样的 https://github.com/leizongmin/js-xss/issues/283

    这么久也没回复,而且 js-xss 好像是不是也不维护了

    虽然用其中的 onIgnoreTag 在其中做了标签名中是否有 “/” 然后去掉 “/” 后再调用 xss 函数 但是不知道还有没有类似的问题出现;

    想问一下有没有别的好用的 xss 过滤办法

    41 条回复    2023-12-12 03:17:03 +08:00
    jowan
        1
    jowan  
       361 天前
    现在的浏览器不是上古的 IE 很多编写的缺陷和 BUG 会被它们主动修复 比如你缺少关闭标签 或者属性值拼写错误 它们都是尽量去帮你修复 有时候在控制台会给你一些 warning 实在修复不了 会直接给你报错
    jowan
        2
    jowan  
       361 天前
    就比如说 chrome 你输入网址的时候 xxx.com 的点写成了句号 它都会帮你转换成英文的
    InDom
        3
    InDom  
       361 天前   ❤️ 1
    如果你不是富文本的话,其实直接用 innerText 而非 innerHTML 就可以避免。

    至于框架,也有框架也有类似的安全方法。从原理上就杜绝了这种问题的发生。

    如果你真的有富文本的需求,那么我一般是这么做的

    禁止 script 与 on[a-zA-Z] 的出现,或者把 script on 替换为 scr-ipt on-.

    宁错杀,不放过。
    Forviler
        4
    Forviler  
    OP
       361 天前
    @jowan 所以 ‘/’ 是在修复之列的, 我试了几个别的都不行,这种不同浏览器还有不同的修复方案了,希望没有别的了
    tabris17
        5
    tabris17  
       361 天前
    甚至不同浏览器对于不规范 HTML Tag 处理方式还不一样,扯得很。最好的办法就是保存时服务端做一次 html 解析,规范化后保存
    jowan
        6
    jowan  
       361 天前   ❤️ 3
    @jowan TMD 楼下的朋友不要点击上面我发的那个示例网址 我草我在办公室 27 寸的显示屏打开了 尴尬
    Forviler
        7
    Forviler  
    OP
       361 天前
    @InDom 确实是需要富文本,不然 innerText 完全不会有这种问题; 干掉 on[a-zA-Z] 和 script 确实一劳永逸;这项目是个老项目了,不想动太多; 下个项目要这样搞一下
    xenme
        8
    xenme  
       361 天前 via iPhone
    @jowan 😄,说明这域名可以
    Forviler
        9
    Forviler  
    OP
       361 天前
    @tabris17 后端大佬使唤不动
    Forviler
        10
    Forviler  
    OP
       361 天前
    @jowan ....好奇心害死猫,还好我手快,随便拼个网址竟然是这。。。。
    yumusb
        11
    yumusb  
       361 天前
    XSS 粗暴一点的话。直接过滤掉 引号与尖号。
    lneoi
        12
    lneoi  
       361 天前
    Forviler
        13
    Forviler  
    OP
       361 天前
    @yumusb 你这有点过分,过滤完只剩标签了
    zsh2517
        14
    zsh2517  
       361 天前   ❤️ 2
    @jowan 我印象好像确实有规范要求这么干的,把中文句号换成点继续访问,不是浏览器自作主张的本土化/兼容。

    刚才问 GPT + 翻了一下 RFC ,RFC 3490 里面确实规定了好几种分隔符

    > 当使用点作为标签分隔符时,必须将以下字符识别为点:U+002E (句号)、U+3002 (表意句号)、U+FF0E (全幅句号)、U+FF61 (半幅表意句号)。

    英文文档: https://datatracker.ietf.org/doc/html/rfc3490#section-3.1
    中文翻译: https://rfc2cn.com/rfc3490.html 3.1 部分
    zjp
        15
    zjp  
       361 天前 via Android   ❤️ 1
    jowan
        16
    jowan  
       361 天前 via iPhone
    @zsh2517 但是很早之前的版本会跳到浏览器设置的搜索引擎进行内容搜索 不知道是哪个版本更新的
    a632079
        17
    a632079  
       361 天前
    mark. 我现在项目用的都是 xss 0 0 ,图方便。看来得换了。感谢楼主预警。
    BaiLinfeng
        18
    BaiLinfeng  
       361 天前
    表示从来都没使用过啊
    Puteulanus
        19
    Puteulanus  
       361 天前
    本来记得有个新出的 HTML Sanitizer API ,看了下浏览器兼容,可以当它没有了。。
    dawn009
        20
    dawn009  
       361 天前
    浏览器对不合规范的写法做了太多妥协,不要信任。
    可以用 javascript 写一个简易的 HTML parser ,自己控制解析哪些 tag 、怎样解析。
    LeeReamond
        21
    LeeReamond  
       361 天前
    非前端,好奇把 script on 替换为 scr-ipt on-这个方法能不能 100%防御所有 xss 。另外同时也好奇 OP 一楼写的那个漏洞是怎么解释执行的,/相当于没加?
    INW017bzMfgkkYGn
        22
    INW017bzMfgkkYGn  
       361 天前
    @jowan #6 你这是用的全局代理呀,这域名被墙了的。
    siweipancc
        23
    siweipancc  
       361 天前 via iPhone
    @jowan 哇塞,辣眼睛
    Forviler
        24
    Forviler  
    OP
       361 天前
    @a632079 如果不是测试,这东西我是发现不了
    Forviler
        25
    Forviler  
    OP
       361 天前
    @dawn009 还有点过于信任库了
    Forviler
        26
    Forviler  
    OP
       361 天前
    @LeeReamond 加了 / 的话 js-xss 不会把这个 tag 识别为 img 识别出来的 tag 名是 img/src , 但是浏览器会自动把 / 替换成空格,从而被当作 img 执行
    Forviler
        27
    Forviler  
    OP
       361 天前
    @lneoi 全是英文,我英文太差,回头翻译一下研究研究
    Granado
        28
    Granado  
       361 天前
    @Forviler #9 这种前端领域的问题,是不是可以做一层前端的网关统一处理后再给后端服务?这样自己团队内就可以闭环这个问题。
    Sum0l
        29
    Sum0l  
       360 天前
    @jowan #6 卧槽 xxx 好奇害死猫啊!!!
    Forviler
        30
    Forviler  
    OP
       360 天前
    @Granado 前端网关处理是指什么,ajax 请求拦截器里 做参数处理? 没想过这样做,感觉不如在 使用 innerHTML 的时候做处理要简单
    a632079
        31
    a632079  
       360 天前
    @Forviler #27 试了下他的 Demo ,似乎也防御不了。
    onice
        32
    onice  
       360 天前
    防御 xss 最正确的方法是实体编码,而不是黑白名单过滤。
    请参阅: https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
    Forviler
        33
    Forviler  
    OP
       360 天前
    @a632079 #31 你是用我那段代码测的么, 我那段尖括号是中文的,换成英文我测是可以过滤掉我说的这种情况的
    Forviler
        34
    Forviler  
    OP
       360 天前
    @onice 没看明白,转为实体编码 我只知道一些 < 转为 &lt; 之类的 不知道如何实现预防的,英文的翻过来没看太懂,

    发现了新的问题

    document.getElementById('rf').innerHTML= `&lt;img/src=1 &gt;` ; edge 下会显示为文本
    document.getElementById('rd').innerHTML = `<img/src=1 >`; edge 下显示为 标签

    不过 v-html 都会显示为标签

    我再研究研究实体编码
    onice
        35
    onice  
       360 天前
    @Forviler 是这样子。XSS 的本质,是浏览器解析了攻击者插入到页面中的 JS 代码,,而这些代码恰好是恶意的,例如窃取用户 cookie 。

    通过实体编码,我们就可以让攻击者插入的 js 代码原样显示在浏览器中,浏览器会显示尖括号,但并不会解析这些 js 代码。当然,浏览器中显示的是尖括号,但在代码层面,已经被处理为&lt;之类的编码了。

    对于大部分前端框架,例如 Vue 和 React ,默认就对 xss 进行防护了。当然, 除非你使用 v-html ,而通过 v-html 渲染的值,用户可以控制。

    对于 Java 后端来说,,防御 XSS 的方法也很简单,加一个过滤器即可。把从前端传过来的所有数据,进行判断,如果发现尖括号等敏感的字符,就进行编码,例如转为:&lt;

    转换后的数据就是安全的了,转换后方可入库。

    XSS 漏洞主要是危害用户的安全,XSS 往往导致用户的登录凭证被窃取,并不危害网站服务器。

    大多数时候,XSS 都被划分为低危漏洞。

    我上面说得可能也不是很详细,要不你参考下白帽子讲 web 安全,第三章 XSS 的部分。

    XSS 漏洞很容易理解,是属于 web 漏洞中比较简单的。

    书籍链接为:

    链接: https://pan.baidu.com/s/1cmMkJH2_9I16A9DODUt5tg?pwd=xwld
    提取码:xwld
    onice
        36
    onice  
       360 天前
    @Forviler
    @onice

    再补充下另一本书:web 安全深度剖析,,这本书篇幅短一些。条例比白帽子讲 web 安全清晰一些。建议优先看这本。

    只看 XSS 章节即可。

    链接: https://pan.baidu.com/s/16s19_V5p3V-bMjsLtZLZMg?pwd=mhxz
    提取码:mhxz
    onice
        37
    onice  
       360 天前
    @Forviler
    针对你当前的场景:

    document.getElementById('rf').innerHTML= `&lt;img/src=1 &gt;` ; edge 下会显示为文本
    document.getElementById('rd').innerHTML = `<img/src=1 >`; edge 下显示为 标签

    假如攻击者的代码为:<img/src=1 >,,你在代码中转为&lt;img/src=1 &gt;后,这就是消毒的操作。浏览器页面中会显示<img/src=1 >,但其实浏览器把显示的<img/src=1 >当成&lt;img/src=1 &gt;处理。这么一来,浏览器就不会真的把这串代码当成 img 标签进行渲染了。这样既能够不破坏用户输入的数据,又能够保障代码的安全(不被解析成 js 代码)。

    document.getElementById('rd').innerHTML = `<img/src=1 >`; edge 下显示为 标签
    这个就是危险的。假如攻击者的攻击代码为:<img/src=1 onerror="alert(xss)">,,由于没有进行编码,这个代码会被当成 js 处理,,浏览器会加载图片,但由于 url 不存在,图片加载失败,触发 onerror 事件,执行 alert 弹窗代码。当然这里仅仅是测试,alert 并不具备危害。但是如果 alert 是窃取 cookie 的代码,这可就危险了。
    Forviler
        38
    Forviler  
    OP
       359 天前
    @onice #37 听起来好像是实体编码是确保用户输入的不会被当作代码来进行解析 这个意思;

    那么我使用富文本的时候是必须要将数据当作代码来进行解析的,所以是不能进行实体编码的操作的么,因为浏览器会把它当作文本来显示
    a632079
        39
    a632079  
       359 天前
    @Forviler #33 😀好
    onice
        40
    onice  
       359 天前
    @Forviler 攻击者也是我们的用户之一,,只不过是不怀好意的用户。所以,我们可以把攻击者看成是正常用户。那么,用户输入的数据,我们肯定不能破坏。例如用户输入 abc ,我们不能为了安全把数据改成 bcd 。所以,实体编码是个好办法。用户输入的数据,关键点在于攻击者输入的数据包含恶意代码,所以用实体编码我们既能让用户输入的数据原样显示在浏览器中,又能让即使是包含了恶意代码的数据不被浏览器解析。

    那么我使用富文本的时候是必须要将数据当作代码来进行解析的,所以是不能进行实体编码的操作的么,因为浏览器会把它当作文本来显示。

    至于富文本,你说得对,的确是这样子。富文本的业务场景下,我们必须要让浏览器解析用户输入的数据。所以实体编码后,富文本的输入数据不被解析,代码就会原封不动的显示在浏览器中。用户的格式设置就会失效,例如文本背景,字体加粗,图片等。

    富文本的场景下宜采用白名单的方式。只允许用户输入特定的 HTML 标签,对用户的输入的数据要严格限制。
    NewYear
        41
    NewYear  
       356 天前
    接着楼主的<img/src=>试了下其他的符号,还有好几个会修正的符号……

    没有用的冷知识又增加了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5552 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 08:34 · PVG 16:34 · LAX 00:34 · JFK 03:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.