XSS学习总结
前言
本文是作者由CSDN博客迁移而来,原文地址:https://blog.csdn.net/2302_81178149/article/details/142746504?spm=1001.2014.3001.5501
我们下面进行下一个漏洞——XSS的学习,XSS是常见漏洞之一,是Web安全必学漏洞。
为探讨清楚XSS的诸多细节,我们特以经典的xss-labs进行从入门到进阶的专项训练。而本文是经由xss-labs训练总结而来,所以配合作者的xss-labs通关全详解食用更佳(怎么可以光学习不训练呢)。
xss-labs通关:xss-labs通关全详解_xsslabs-CSDN博客
基础知识汇总
W3C标准
W3C标准:网页主要由三部分构成
结构:HTML**(简单掌握HTML,学会写常用标签、大体能看懂网站HTML源码即可)**
表现:CSS**(简单了解,知道作用就行)**
行为:JavaScript**(需要较深入了解,但具体的语法在练习中学习即可)**
HTML:定义了页面的结构和内容,包括文本、图像、链接
CSS:页面的样式和布局
JS:用于添加交互性和动态功能作用
原理
XSS全称跨站脚本攻击(Cross Site Scripting),为避免与层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故缩写为XSS。
这是一种将任意 Javascript 代码插入到其他Web用户页面中执行以达到攻击目的的漏洞。攻击者利用浏览器的动态展示数据功能,在HTML页面里嵌入恶意代码。当用户浏览该页时,这些潜入在HTML中的恶意代码会被执行,用户浏览器被攻击者控制,从而达到攻击者的特殊目的,如 cookie窃取等。
凡是数据输入或者交互的地方,都有可能发生xss。
XSS属于代码注入的一种,它允许攻击者将代码注入到网页,其他用户在浏览网页时就会受到影响。
分类
反射型:
又称非持久型XSS,这种攻击属于一次性攻击,只是简单的把用户输入的数据“反射”给浏览器。恶意代码一般存放于链接当中,攻击者将包含XSS代码的恶意链接发送给目标用户,当目标用户访问该链接时,服务器接受该目标用户的请求并进行处理,然后服务器把带有XSS代码的数据发送给目标用户的浏览器,浏览器解析这段带有XSS代码的恶意脚本后,就会触发XSS,也就是说攻击者往往需要诱使用户点击恶意链接才能攻击成功。
常见的注入点:网站的搜索栏、用户登录入口、输入表单等地方。常用来窃取客户端Cookie或钓鱼欺骗。
产生的原因一般是网站只是简单的将用户输入的数据直接或未经过完善的安全过滤就在浏览器中输入,导致输出的数据中存在可被浏览器执行的代码数据。
存储型:
又称持久型XSS,比反射型XSS更具有威胁性,攻击脚本会永久的存储在目标服务器的数据库或文件中,具有一定的隐蔽性。这种攻击方式多见于论坛、博客和留言板,攻击者在发帖的过程中,将恶意脚本与正常信息一起注入到留言中,随着留言被服务器存储下来,恶意脚本也被存储到存储器中。当其他用户浏览这个被注入恶意脚本的留言时,恶意脚本就会在用户的浏览器被执行。存储型XSS能将恶意代码永久的嵌入页面中,所有访问这个页面的用具都将成为受害者。
常见注入点:论坛、博客、留言板、网站的留言、评论、日志等交互处。
造成漏洞原因一般是由于Web应用程序对用户输入数据的不严格,导致Web应用程序将黑客输入的恶意跨站攻击数据信息保存在服务端的数据库或其他文件形式中。
DOM型:
DoM是文档对象模型( Document Object Model)的缩写。它是HTML文档的对象表示,同时也是外部内容(例如 JavaScript)与HTML元素之间的接口。解析树的根节点是“Document”对象。DOM( Document object model),使用DOM能够使程序和脚本能够动态访问和更新文档的内容、结构和样式。
DOM型的XSS是通过修改页面DOM节点数据信息而形成的XSS跨站脚本攻击。不同于反射型XSS和存储型XSS,基于DOM的XSS跨站脚本攻击往往需要针对具体的 Javascript DOM代码进行分析,并根据实际情况进行XSS跨站脚本攻击的利用。
并且DOM型XSS是基于JS上的,并不需要与服务器进行交互,它只发生在客户端处理数据的阶段。当用户请求一个包含XSS恶意代码的URL,服务器的响应不会以任何形式包含攻击者的脚本,当用户的浏览器处理这个响应时,DOM对象就会处理XSS代码。
事实上,DOM型也是一次性攻击,只不过由于DOM是在客户端修改节点的,所以基于DOM型的XSS漏洞不需要与服务器端交互,它只发生在客户端处理数据的阶段。DOM型其实也属于非持久型XSS,只不过因DOM型有不与服务器端交互的特性,使得它与常规反射性XSS有明显区别(在防护上有天壤之别,不与服务器端交互使得它基本不能在服务器端做防护),故独立出来
常见注入点:通过前端的dom节点形成的XSS漏洞,一般不与后台服务器产生数据交互,主要通过与前端页面进行闭合来产生xss。通过js脚本对文档对象进行编辑,从而修改页面的元素。也就是说,客户端的脚本程序可以DOM动态修改页面的内容,从客户端获取DOM中的数据并在本地执行。
造成漏洞的原因:这是一种基于DOM的跨站,这是客户端脚本本身解析不正确导致的安全问题。
总述:
反射型与持久性XSS在payload上区别不大,主要区别在于生效位置不同而导致的持久性不同。反射型是一次性攻击,往往存在于链接之中,需要点击才能生效;持久性可能注入在网站的评论区,随网站加载即可生效,可以长期有效。至于DOM型可以看作一种特殊的反射型XSS,但其有不与服务器端交互的特性,使得它与常规反射性XSS有明显区别(在防护上有天壤之别,不与服务器端交互使得它基本不能在服务器端做防护),故独立出来。
Payload(常用标签)
XSS常见的触发标签:
XSS常见的触发标签_xss< img src οnerrοr=alt=’’+document.domain>”怎么触发-CSDN博客
上文已经列举得很详细了,这里对几个常用标签进行详解,以方便读者理解。
注:所有具体的攻击代码都用alert()代替。
一、<script>alert()</script>
最基础的payload
二、οnfοcus=javascript:alert()
onfocus事件在元素获得焦点时触发,最常与 <input>
、<select>
和 <a>
标签一起使用,以html标签<input>
为例,<input>
标签是有输入框的,简单来说,onfocus事件就是当输入框被点击的时候,就会触发,然后我们再配合javascript伪协议来执行javascript代码。
onfucus事件可以用来绕过<>号的过滤以达到执行js的目的,有时会οnfοcus=javascript:alert() type=”text”这样连着使用,以除去type=”hidden”,把输入框(或者其他边框)显示出来,从而可以使鼠标聚焦到输入框。
οnclick=alert()与onfocus类似
三、<a href=javascript:alert()>xxx</a>
可以插入标签(如<a>
标签的href属性)达到js执行的效果,前提是闭合号<””>没失效。
还能利用href的隐藏属性自动Unicode解码,从而可以插入一段Unicode编码后的js伪协议,如
1 |
|
其中,javascript:alert()在Unicode编码后为:
1 |
|
不过需要注意的是,有时会对herf中传入的值进行检查,看看是否有http://,这时候需要变成
1 |
|
四、<img src='xxx' οnerrοr=alert()>
src(source)是一个指向,可以大概理解跟href一样把,只是执行的内容不太一样。
onerror属性是指当图片加载不出来的时候触发js函数,以上面的代码为例,这里因为src指向的是值xxx,而不是图片的地址和base64编码啥的,就会导致触发alert函数
当然img标签还有其他姿势
当鼠标移出图片的时候执行的属性onmouseout ,如
1 |
|
当鼠标移动到图片的时候执行的属性onmouseover,如
1 |
|
五、<iframe src="data:text/html;base64,<script>alert()</script>">
data一般在<iframe>
标签中用来配合date:text/html(类似于解析),有时会用
1 |
|
<script>alert()</script>
进行base64编码后是PHNjcmlwdD5hbGVydCgpPC9zY3JpcHQ+
,这样就可以绕过<script>
的过滤
六、图片xss
如果有exif xss漏洞,那我们就需要制作可以xss的图片。
exif是可交换图像文件格式(英语:Exchangeable image file format,官方简称Exif),是专门为数码相机的照片设定的,可以记录数码照片的属性信息和拍摄数据(就是图像的相关信息)。
我们可以在网上随便下载一个带有exif的图片,然后按下面步骤制作图片xss:
我们右键图片选择属性,点击详细信息就可以看到exif的相关属性。
然后大家在各个信息上编写XSS代码即可(能写的可以都写上)。
当然可能大家想做的图片可能没有exif,相关信息根本就写不了。这里作者制作了一个脚本,可以给没有exif的图片加上exif。
(需要下载两个Python包:
- Pillow:这是一个用于图像处理的库,支持打开、操作和保存多种格式的图像。
- piexif:用于处理EXIF数据的库,能方便地读取、修改和保存EXIF信息。
1 |
|
)。
1 |
|
混淆和绕过
一、前端
如果后端没有进行对前端数据的判断和处理,对前端的限制可以尝试进行抓包重发或者修改前端的HTML。比如输入框限制只能输入20个字符,这就是限制,但是前端的限制对能力强的攻击者来讲都是无用的。抓包改请求包,或者直接在前端代码中修改等。
二、后端
1. 大小写绕过
例如,
1 |
|
2.双写绕过
1 |
|
或者
1 |
|
3.闭合
可以闭合所在标签,然后重新开始一个标签闭合
1 |
|
4.字符代替
在html中是可以将%0a和%0d作为空格使用的(回车代替空格)
5.换标签
根据标签的性质使用一些其他标签,或是不需要<>或是不在过滤范围内
1 |
|
6.伪协议
javascript伪协议,即javascript:代码
1 |
|
7.编码绕过
后台有可能会对代码中的关键字进行过滤,但我们可以尝试将关键字进行编码后在插入,浏览器 对改编码进行识别时,会翻译成正常的代码。(注意:编码在输出时是否会被正常识别和翻译才是关键,不是所有的编码都是可以的)
浏览器解析顺序是这样的,URL 解析器->HTML 解析器->CSS 解析->JS解析器
URL的解码:是在后台服务检测之前的,可以理解为后台收到URL后会自动进行解码,然后才是执行开发人员编写的对URL中的值的检测函数,首先URL编码作用不在于绕过后台检测,但是当我们是 GET方式提交数据时,而我们提交的数据中进行了实体编码,也就意味着存在&,#这样的特殊字符,这时就需 要对这些特殊字符进行URL编码,这样才会保证正常解析,如果不进行URL编码的话,就会把+认为是空格了,而&也会是被认为用来连接URL中参数的连接符,故需要进行URL编码。如果是以POST方式传递值,就不需要进 行URL编码了。
html实体编码(HTML解析器):&#十进制,而&#x十六进制;JS编码(JS解析器):也就是unicode编码,\u00十六进制。
利用实体编码 :
1 |
|
利用unicode编码:
&#、&#x、\u 都可以用来表示一串 unicode 编码,unicode编码底层还是用二进制来存储的,显示 一般用16进制来表示。\u开头和&#x开头是一样的都是16进制,只是unicode字符的不同写法,&#则是unicode字符的10进制的写法。编码后
1 |
|
实体编码要在不破坏DOM树的构成的情况下,对于有语法结构的标签名、属性名、标签名就不能进行实体编码,而对属性的值、标签之间的文本节点能够进行实体编码。
JS编码只能对位于JS解析环境内字符进行编码,且不能是括号、双引号、单引号等构成特殊意义的特殊字符,比如alert(1)中的括号就不能进行实体编码,而且在JS编码环境中不会进行实体编码解析,但有一个例外,就是在在javascript伪协议中,比如javascript:alert(‘test’);就可以实体编码。这一部分可以看成是标签a的属性href的值,从而进行实体编码会被正常解析,又可以对alert或alert中的字符进行JS编码,但对alert中的字符编码没什么实际作用。如果是输出到了js代码中,再由js代码输出到html中,那么js会先将unicode编码进行解析,然后再输出到 html中,这就有了html标签效果。
8.htmlspecialchars()函数
PHP里面的这个htmlspecialchars()函数把一些预定义的字符转换为 HTML 实体(文本)。比如,将可以编码的括号改成文本类型的括号。
过滤原理:htmlspecialchars() 函数把预定义的字符转换为 HTML 实体,从而使XSS攻击失效。但是这个函数默认配置不会将单引号和双引号过滤,只有设置了quotestyle规定编码单引号和双引号才能会过滤掉单引号。
预定义的字符有:
& (和号)成为 &
“ (双引号)成为 “
’ (单引号)成为’
< (小于)成为 <
9.httponly
HttpOnly是包含在http响应头Set-Cookie里面的一个附加的标识,所以它是后端服务器对cookie设置的一个附加的属性,在生成cookie时使用HttpOnly标志有助于减轻客户端脚本访问受保护cookie的风险。如果浏览器支持的话,大多数XSS攻击都是针对会话cookie的盗窃。后端服务器可以通过在其创建 的cookie上设置HttpOnly标志来帮助缓解此问题,这表明该cookie在客户端上不可访问。如果支持 HttpOnly的浏览器检测到包含HttpOnly标志的cookie,并且客户端脚本代码尝试读取该cookie,则浏览器将返回一个空字符串作为结果。这会通过阻止恶意代码(通常是XSS)将数据发送到攻击者的网站来使攻击失败.
如果HTTP响应标头中包含HttpOnly标志(可选),客户端脚本将无法访问cookie(如果浏览器支持该标志的话)。因此即使客户端存在跨站点脚本(XSS)漏洞,浏览器也不会将Cookie透露给第三方。 但是如果浏览器不支持HttpOnly,并且后端服务器设置了HttpOnly cookie,浏览器也会忽略HttpOnly 标志,从而创建传统的,脚本可访问的cookie。那么该cookie(通常是会话cookie)容易受到XSS攻 击。这里大家要注意一个问题,httponly不是防止xss攻击的,而是防止xss攻击代码中的js代码在浏览器上获取cookie信息。
利用方式
一、找到xss漏洞
1、凡是数据输入或者交互的地方,都有可能发生xss。所以我们需要测试的地方有:
输入框(包括搜索框、评论框等),
传递的get、post参数(可能有隐藏参数,建议抓包测试),
Referer、User-Agent、Cookie等http头传参。
我们必须认真全面的对上面各处进行仔细的测试,借以找到开发及维护人员的疏忽所在。
2、测试关键字及其过滤情况
可以套用下面payload的测试
1 |
|
其中,“’是为了测试是否有闭合的机会,而sRc DaTa OnFocus OnmOuseOver OnMouseDoWn P <sCriPt> <a hReF=javascript:alert()>
是各个payload所需的关键字,j则是unicode编码。
二、利用xss漏洞
1、在线XSS平台
需要一个在线XSS平台来收集cookie——>
对于反射型xss可构造链接,当用户点击时,用户cookie被发送到xss平台——>
窃取用户cooike之后加以利用
具体请参考:
XSS免费接收平台以及模拟钓鱼一键生成测试_xss平台-CSDN博客(入门)
XSS-窃取Cookie及拓展_xss获取cookie并利用-CSDN博客(进阶)
2、自建网站
如果我们自己搭建了一个网站,也可以用自己的网站去接收。
假设我们自己搭建了一个网站(http://ip/setup.php)并在里面写好了php,代码如下
(代码意思是以get类型接受一个cookie变量,并将其写入cookie.txt中)
然后用户即将访问一个名叫access的网站(即http://access.com
),
当他访问其中某个界面要传递name参数时,若存在xss漏洞,我们可以构建payload:
1 |
|
注意document.location起到跳转的作用,跳到我们搭建的网站,并且用户把自己在access网站的cookie也传递过来了,这样就达成了我们获取cookie的目的(在习题中,我们用alet()代替实际的攻击代码,所以上文所有含有alert()的所有代码在实际攻击过程中都需修改,但混淆与绕过等技术不变)
3、劫持
当然,如果真有xss漏洞,我们还可以做一个劫持,只要在下方填上我们的网站,就可以把所有a标签的链接改成我们的网站,这样用户无论点哪个链接都会跳到我们的网站,当浏览网站时点击某些链接会突然跳转到广告页面就是这个技术(不只是a标签,图片也可以,我们这里拿a标签举个例子)。
1 |
|
利用方式会有很多,比如说,我们的网站甚至可以伪装成重新登录的页面,然后布置好跳转(这里我们模拟一下具体场景:用户鼠标一点,突然跳转,需要重新登录,然后懵懵地输入完,又返回之前的页面了),这样我们就可以获得账户密码。
上面只是举一个例子,就是说大家不要被习题困住,要有探索各种利用方法的意识(只有会攻才能会防)。
4、xss集成平台
此外我们也可以用功能更全面的xss集成平台进行利用,达到我们上面想要的效果,比如beef。
详见下文: