1.反射型
非持久化,需要用户自己点击才可以触发
通常出现在搜索框
<?php
$id=$_GET['id'];
echo $id;
?>
http://127.0.0.1/test/sc.php?id=<script>alert(1)</script>
2.存储型
持久化,危害比较大
通常出现在个人信息和留言板处
//提交漏洞页面
<form action="" method="post">
<input type="text" name="xss"/> <input type="submit" value="test"/> </form> <?php $xss=$_POST['xss']; mysql_connect("localhost","root","root"); mysql_select_db("test"); if($xss!==null){ $sql="insert into xss(id,s) values('1','$xss')"; $result=mysql_query($sql); echo $result; } ?>
//显示数据库查询页面
<?php
mysql_connect("localhost","root","root"); mysql_select_db("test"); $sql="select s from xss where id=1"; $result=mysql_query($sql); while($row=mysql_fetch_array($result)){ echo $row['s']; } ?>
3.DOM型
类似于反射型,但是直接在前端输出,而不经过后端
<?php
error_reporting(0);
$test = $_GET["test"];
?> <html> <input id="text" type="text" value="<?php echo $test;?>" /> <script type="text/javascript"> var text = document.getElementById("text"); document.write(text.value); </script> </html>
关于DOM型
<html>
<body>
<input id="id" type='text'> <script> //var a='<script>alert(1)<\/script>'; var a="<img src=1 onerror=alert(1)>"; document.getElementById("id").innerHTML=a; </script> </body> </html>
上面的代码,如果是<script>alert(1)</script>不会触发弹窗
如果是<img src=1 onerror=alert(1)>则会触发弹窗
原理应该是(?)
浏览器对<script>标签DOM操作时,会页面渲染,不会再JS解析
4.触发
如果我们可控的数据在标签的属性当中
<1>资源属性
使用 javascript伪协议
基本上可以请求资源的HTML标签内都可以使用src\href等
但是有的标签已经不能触发XSS,有的则可以
<html>
<script> var lang = document.location.href.substring(document.location.href.indexOf("id=")); lang=lang.substr(3,); document.write('<a href="'+lang+'">test</a>'); document.write('<iframe src="'+lang+'">'); document.write('<img src="'+lang+'">');//不能触发 </script> </html>
JS伪协议不区分大小写,并且会自动实体解码和进制解码
javascript:alert(1)
JavascRipt:alert(1)
等等都可以触发
<2>事件属性
<html>
<script> var lang = document.location.href.substring(document.location.href.indexOf("id=")); lang=lang.substr(3,); document.write('<a href=1 onclick="'+lang+'">test</a>'); document.write('</br>'); document.write('<a href=1 onmouseover="'+lang+'">test1</a>'); </script> </html>
事件不区分大小写,引号可以不使用也可是是单引号或双引号
<html>
<script> var lang = document.location.href.substring(document.location.href.indexOf("id=")); lang=lang.substr(3,); document.write('<a href=1 onmouseover="'+lang+'">test</a>'); document.write('</br>'); document.write("<a href=1 onmouseover='"+lang+"'>test1</a>"); document.write('</br>'); document.write('<a href=1 onmouseover='+lang+'>test</a>') </script> </html>
上面的三种都是一样的
<3>普通属性
想办法构造新的属性或者闭合标签
5.HTMLENCODE
有些标签具备HTMLENCODE功能
<html>
<textarea><img src=1 onerror=alert(1)></textarea> <title><img src=1 onerror=alert(1)></title> <iframe><img src=1 onerror=alert(1)></iframe> <noscript><img src=1 onerror=alert(1)></noscript> <noframes><img src=1 onerror=alert(1)></noframes> </html>
剩下的,比如div标签
<html>
<div><img src=1 onerror=alert(1)></div> </html>
6.进制转换
<1>HTML
HTML支持十进制和十六进制
图片可以正常显示
<2>CSS
CSS支持十进制和十六进制
<3>JS
JS支持八进制和十六进制
<html>
<script>alert(1)</script> <script>eval("\141\154\145\162\164\50\62\51")</script> <script>eval("\u0061\u006c\u0065\u0072\u0074\u0028\u0033\u0029")</script> </html>
进制方式对大小写不敏感,后缀’;’也不是必须的,所以可以用常规字符、十进制编码和十六进制编码混合
如果给汉字编码,则只能使用十六进制的unicode
7.源码审计
<1>反射型和存储型
查找在页面输出的变量,检验是否收到用户控制,跟踪传递过程,分析是否被过滤。
主要关注 $_SERVER,$_GET,$_POST,$_REQUEST查找输出的变量,检验是否可控,查看是否被过滤print,print_r,echo,printf,sprintf,die,var_dump,var_export
主要出现在搜索框、文章发表、评论回复、留言、友情链接、资料设置等处
<2>DOM型
1. 查看用户的某些输入源
document.referer
window.name
location
2. 输出
innerHTML
document.write
8.防御
<1>反射型和存储型
对用户的输入进行过滤
黑白名单输入进行编码
htmlspecialchars()
<2>DOM型
避免客户端对文档进行重写、重定向或其他敏感操作
避免使用客户端数据,这些操作尽量放在服务端使用动态页面来实现