XSS基础学习

XSS基础学习

By:Mirror王宇阳

什么是XSS

XSS攻击是指在网页中嵌入一段恶意的客户端Js脚本代码片段,JS脚本恶意代码可以获取用户的Cookie、URL跳转、内容篡改、会话劫持……等。

xss攻击手段本身对服务端没有直接的危害,xss主要是借助网站传播;一般通过留言板、邮件、等其他途径向受害者发送一段恶意的URL,受害者通过访问该恶意URL可能会导致恶意的xss脚步会在受害者的客户端浏览器中执行,实现自己的目的

XSS的攻击类别分为:反射型、存储型、DOM型等三大类攻击类别。

反射型XSS

反射型XSS会把用户输入的数据直接返回给页面,是一种非持久型攻击;这类型的xss是最为常见的,主要的利用方法就是恶意脚本添加到参数(URL)发送给用户诱骗用户点击后反射数据给页面。

  • 页面源码

    <!DOCTYPE html>
    <html>
      <head>
          <meta charset="utf-8">
          <title>XSS | 反射型</title>
      </head>
      <body>
          <form action="xss.php" method="GET">
              <h2>xss反射型注入攻击测试</h2>
              <span>测试语句:</span>
              <input type="text" name="name">
              <input type="submit" value="提交">
          </form>
      </body>
    </html>
  • 后台源码
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>Text page | Return</title>
    </head>
    <body>
      <h2>反射型测试页面</h2>
      <?php
          echo $_GET["name"];
      ?>
    </body>
    </html>
  • 源码分析

    我们输入的内容会被执行并嵌入在HTML页面中;$_GET[‘name‘]会触发js恶意代码并嵌入HTML页面中。

  • 测试
    • 正常页面

    • XSS测试

    • 结果发现:我们在输入text框中写入了一个Js代码,代码直接被执行并嵌入在HTML页面中;众所周知,Js代码和HTML代码直接暴露在客户端,一旦写入的Js代码可以被执行并嵌入在HTML页面中即视为存在XSS攻击。
  • 恶意利用

    我们通过向受害者发送如下的恶意URL就可以实现在用户客户端执行该恶意js脚本;

    http://127.0.0.1/xss/xss.php?name=<script>alert('XSS测试结果');</script>

    攻击者还会将URL进行各式各样的加密转换的处理,最大程度的减少URL恶意脚本的暴露;

存储型XSS

存储型XSS是一种持久的xss攻击类别,攻击者将恶意脚本植入到服务端数据库或长期的嵌入在HTML页面中;当用户符合触发条件后就会触发Js的xss恶意脚本。

存储型的xss通常会存储在客户端或数据库中,当用户访问页面即触发xss。

存储型的xss不需要构造URL诱骗用户去点击,大大的减少暴露和增加隐秘性。

  • 创建数据库和表

    create table text(
      uid int(10) not null auto_increment primary key,
        title varchar(20) null,
        content text(100) null
    )engine=innodb default charset=utf8;

  • HTML页面源码
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>xss | 存储型</title>
    </head>
    <body>
    
      <form action="xss_storage.php" method="POST">
      <span>
          <h2>xss|存储型测试</h2>
          <h3>留言板测试</h3>
      </span>
      主题:<input type="text" name="title"></br>
      留言:<textarea name="content">
              </textarea><!-- 文本域留言 -->
              <input type="submit" name="提交">
    
      </form>
    </body>
    </html>

  • PHP后台源码
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>xss | 存储型</title>
    </head>
    <body>
    
      <!-- create databases xss_text 创建数据库-->
      <?php
          $conn = mysqli_connect("127.0.0.1","root","root","xss_text") or die("数据库连接错误".mysqli_error());
          // set names utf-8 -- 写入数据库采用的编码(utf-8)
          mysqli_query($conn, 'set names utf-8');
    
          if (isset($_POST["title"])) {
              $title = $_POST["title"];
              $content = $_POST["content"];
              //向数据库添加 title content 两字段的内容
              $sql = "INSERT INTO `xss_text`.`text` (`uid`, `title`, `content`) VALUES (NULL, '$title', '$content')";
              echo $sql;
              $result_1 = mysqli_query($conn,$sql);
              // 页面回显/查询数据
              $result_2 = mysqli_query($conn , "select * from text");
    
              echo "<table boreder='1'><tr><td>标题</td><td>内容</td></tr>";
    
              while($row = mysqli_fetch_array($result_2, MYSQLI_BOTH)) {
                  echo "<tr><td>" . $row['title']. "</td><td>" .$row['content']. "</td>";
              }
              echo "</table>";
              echo $row['title'];
          }
    
      ?>
    </body>
    </html>
  • 分析

    当用户在content写入一个可执行恶意js脚本的标签即可过程xss例如:<input type="button" value="xss" onclick="alert(xss)"/>,提交查询后内容就会写入在数据库中,在数据库的查询结果回显至页面后就可以触发了,这里举两个例子,一个是手动触发,一个是自动加载触发。

  • 测试

    这是写入一个input标签,鼠标点击事件可执行一个js脚本即一个弹窗。

    这里是写入了一个img标签但是标签src无索引会错误error,由此触发onerror属性执行js;也可以使用其他类似于onload属性……

    测试过程中发现单引号无法存入数据库,原因本小白也是半懂不懂;在sql执行的写入的时候单引号会被转义,对此可以尝试双单引号来实现最后也会以单引号的语句保存在表中。

DOM型xss

基于DOM的XSS攻击手段,效果上和反射型XSS类似;通过修改页面的DOM节点形成XSS

DOM规定:

  • 一个文档就是一个文档节点
  • 每个HTML标签就是一个元素节点
  • 包含在HTML元素中的文本是文本节点
  • 每一个HTML属性是一个属性节点
  • 节点与节点之间都有等级关系
  • 测试源码
    <!DOCTYPE html>
    <head>
        <meta charset='utf-8'>
        <title>xss | DOM</title>
    </head>
    <body>
        <h1>
            XSS - DOM攻击测试页面
        </h1>
        <script type="text/javascript">
          function xss() {
              var str = document.getElementById("xss").value;
              document.getElementById("demo").innerHTML = "<a href = '"+str+"'>超链接</a>";
          }
    
        </script>
        <div id = "demo">
            测试区域
        </div>
    
        <div>
        xss测试:
          <input type="text" id="xss" />
          <input type="button" id="a" value="提交" onclick="xss()" />
        </div>
    </body>
  • 分析

    当我们想id=xss提交数据后,提交的内容则会作为a标签的href属性被写入在HTML页面中;而攻击者则采用闭合拼接的方式来构成恶意的xss

  • 测试

    • 构造恶意的闭合xss

      <a href = "" onclick=alert("Hello,World!") >超链接</a>
      
      xss 提交:
      " onclick=alert("Hello,World!")

      这样的xss构造语句会向测试区域发送恶意的构造标签实现攻击目的

XSS常见测试语句

<script> alert(1) </script>

<img src=x onerror = alert(1) />

<svg onload=alert(1)>

<a href=javascript:alert(1)>

XSS绕过思路

  • Js编码

JS提供了四种字符编码的策略

  • 三个八进制数字,空位补0,\***
  • 两个十六进制数,空位补0,\x**
  • 四个十六进制数,空位补0,\u****
  • 控制字符,例如 \r , \h , \t
  • HTML实体编码

命名实体:命名以 “&” 开头,分号结尾;参考:实体编码字符

字符编码:十进制、十六进制ASCII编码或Unicode字符编码

  • URL编码

在线工具:http://tool.chinaz.com/tools/urlencode.aspx

线下工具:URL编码解码工具(Burp-Decoder)

XSS检测

使用手动检测可以最大精确化,但是对于大型的web应用是困难的是;最首要的重要就是哪里有输入、输入的结果输出的地方。

手工检测XSS要使用特殊意义的字符,这样可以快速的测试是否存在XSS;

  • 可得知输出位置

    输入一些敏感字符,例如: > < " ‘ ( )等,遵照自提交后查看HTML源代码,查看自己输入的字符是否被转义;

  • 无法得知输出位置

    大多的web应用时非开源的,测试XSS的时候无法得知具体的输出位置显示;例如:我们的评论提交后会交由后台进行内容敏感检查,我们就无法得知具体的输出位置了;

    <input type="text" id="name" value="Coke" />

    上述是一个表单,我们可以使用/> xxx测试该标签的具体输出位置

xss利用方式

Cookie窃取

Cookie时能够让网站服务器吧少量的文本数据存储到客户端的硬盘或内存中,用于维持HTTP无状态协议导致的可持续网站会话;

  • 如何产生:

    当我们访问某网站,网站服务端由于HTTP时无状态协议,而客户端和服务器无法直接判断是否来自同一个客户源,为此当用户访问第一次网站后并登录等操作,服务端会返回Cookie给客户端的硬盘或内存中存留

  • 如何使用:

    当用户第二次访问服务端的时候,服务端就会检查客户端中是否有Cookie文件,如果有Cookie则会利用该文件登录并访问网站

  • Cookie格式:

    每一个浏览器保存的Cookie的文件位置均不同,这里以Firefox浏览器为例,我们访问DVWA平台并登录,保存用户和密码形成Cookie

    Cookie主要由变量名key和值value组成:

    Set-Cookie: <name>=<value>[;<Max-Age>=<age>][;expires=<date>][;domain=<domain_name>][;path=<some_path>][;secure][;HttpOnly]

    Set-Cookie HTTP服务器的响应头,Web服务器通过此头讲Cookie发给客户端

    name=value Cookie必有部分,用户通过name取得Cookie的对应的Value值

    expires=<date> 规定了Cookie的有效终止日期;缺省该字段则cookie不会存储在硬盘中

    domain=<domain_name> 规定了哪些Internet域中的Web服务器可以读取客户端的Cookie文件,如果缺省则Web服务器的域名为Value;

    path=<some_path> 定义Web服务器上哪些路径下的页面可以获取服务器发送的Cookie文件;Value为/表示Web服务器中所有页面都可以获取Cookie文件;如果缺省,Path的Value则是Web服务器向客户端发送Cookie的URL;

    Secure Cookie中标明变量,只有当web服务器和客户端之间采用HTTPS加密认证协议才可以进行连接通信提交Cookie文件

    HttpOnly 禁止JavaScript读取

    Cookie中的内容经过加密处理,只有Web服务器的Cookie处理程序可以解析Cookie真正的意义

  • 利用xss获取cookie
    • 创建一个cookie

      setcookie() 函数向客户端发送一个 HTTP cookie。参考文章

      setcookie(name,value,expire,path,domain,secure)
        # 参数定义
          name    必需。规定 cookie 的名称。
          value   必需。规定 cookie 的值。
      
          expire  可选。规定 cookie 的有效期。  若是删除一个cookie则可以设置时间为过去时
          path    可选。规定 cookie 的服务器路径。
          domain  可选。规定 cookie 的域名。
          secure  可选。规定是否通过安全的 HTTPS 连接来传输 cookie。
      
      注释:可以通过 $HTTP_COOKIE_VARS["user"] 或 $_COOKIE["user"] 来访问名为 "user" 的 cookie 的值。
      
      注释:在发送 cookie 时,cookie 的值会自动进行 URL 编码。接收时会进行 URL 解码。如果你不需要这样,可以使用 setrawcookie() 代替。
    • 页面添加设置COOKIE
      <!DOCTYPE html>
      <html>
          <head>
              <meta charset="utf-8">
              <title>XSS | 反射型</title>
          </head>
          <body>
              <form action="xss.php" method="GET">
                  <h2>xss反射型注入攻击测试</h2>
                  <span>测试语句:</span>
                  <input type="text" name="name">
                  <input type="submit" value="提交">
              </form>
              <?php
                  $COOKIE="XSS获取COOKIE测试";
                  setcookie("xss_cookie",$COOKIE);
                  echo "COOKIE设置成功";
              ?>
          </body>
      </html>
    • xss获取Cookie
      <script>
          alert(document.cookie);//获取Cookie
      </script>

    • 恶意构造URL
      http://127.0.0.1/xss/xss.php?name=<script>alert(document.cookie);</script>

      若是用户访问了这个URL则会直接暴露自己的COOKIE,一旦暴露,攻击者可以伪造COOKIE访问。

    • COOKIE安全

      正是因为Cookie存在客户端且可以容易被伪造,所以最初的预防办法就是高度加密;用户获取Cookie信息后伪造Cookie登录即可操作该账号。对于高度加密的COOKIE攻击者至于要原样伪造一个即可,因为解密的大多是在服务端解密Cookie的;Cookie被窃取后就会导致Cookie伪造会话/Cookie欺骗严重的安全漏洞。

常规防御XSS

字符过滤

  • 输入过滤

    永远不要相信用户的输入;一般情况在客户端要设置字符验证过滤敏感的字符、限制长度、要求格式……等。当然客户端的内容用户都是可控的,单单依靠客户端是不可靠的,通过Burp等工具,可以轻易的修改数据包,绕过 客户端的过滤检查。

  • 输出转码

    千万不要把用户的输入内容完整的回显至HTML页面中!一般使用HTMLEncode进行编码处理。

    htmlspecialchars()函数可以将部分特殊字符转出HTML实体编码。

    <?php
      echo htmlentities($_GET["name"]);
      // echo $_GET["name"];
    ?>

    输出的转码可以预防xss脚本直接回显执行

  • 黑名单

    使用黑名单和白名单对输入的内容进行正则匹配,不符合的则不执行并取消。开发人员将敏感的关键词 、特殊字符进行黑名单设置,将一些符合条件的字符、关键词纳入白名单。

  • 前端过滤函数
    function xss_clean($data){
     // Fix &entity\n;
     $data=str_replace(array('&','<','>'),array('&amp;','&lt;','&gt;'),$data);
     $data=preg_replace('/(&#*\w+)[\x00-\x20]+;/u','$1;',$data);
     $data=preg_replace('/(&#x*[0-9A-F]+);*/iu','$1;',$data);
     $data=html_entity_decode($data,ENT_COMPAT,'UTF-8');
     // Remove any attribute starting with "on" or xmlns
     $data=preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu','$1>',$data);
     // Remove javascript: and vbscript: protocols
     $data=preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu','$1=$2nojavascript...',$data);
     $data=preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu','$1=$2novbscript...',$data);
     $data=preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u','$1=$2nomozbinding...',$data);
     // Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
     $data=preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i','$1>',$data);
     $data=preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i','$1>',$data);
     $data=preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu','$1>',$data);
     // Remove namespaced elements (we do not need them)
     $data=preg_replace('#</*\w+:\w[^>]*+>#i','',$data);
     do{// Remove really unwanted tags
     $old_data=$data;
     $data=preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i','',$data);
     }while($old_data!==$data);
     // we are done...
     return $data;
    }
    
  • 后端过滤
    <?php
    //php防注入和XSS攻击通用过滤.
    //by qq:831937
    $_GET     && SafeFilter($_GET);
    $_POST    && SafeFilter($_POST);
    $_COOKIE  && SafeFilter($_COOKIE);
    
    function SafeFilter (&$arr)
    {
    
       $ra=Array('/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/','/script/','/javascript/','/vbscript/','/expression/','/applet/','/meta/','/xml/','/blink/','/link/','/style/','/embed/','/object/','/frame/','/layer/','/title/','/bgsound/','/base/','/onload/','/onunload/','/onchange/','/onsubmit/','/onreset/','/onselect/','/onblur/','/onfocus/','/onabort/','/onkeydown/','/onkeypress/','/onkeyup/','/onclick/','/ondblclick/','/onmousedown/','/onmousemove/','/onmouseout/','/onmouseover/','/onmouseup/','/onunload/');
    
       if (is_array($arr))
       {
         foreach ($arr as $key => $value)
         {
            if (!is_array($value))
            {
              if (!get_magic_quotes_gpc())//不对magic_quotes_gpc转义过的字符使用addslashes(),避免双重转义。
              {
                 $value  = addslashes($value); //给单引号(')、双引号(")、反斜线(\)与NUL(NULL字符)加上反斜线转义
              }
              $value       = preg_replace($ra,'',$value);     //删除非打印字符,粗暴式过滤xss可疑字符串
              $arr[$key]     = htmlentities(strip_tags($value)); //去除 HTML 和 PHP 标记并转换为HTML实体
            }
            else
            {
              SafeFilter($arr[$key]);
            }
         }
       }
    }
    ?>
    

HttpOnly Cookie

防止xss窃取Cookie可以使用HttpOnlyCookie;

当一个Cookie在Set-cookie消息头中被标明为HttpOnly时,客户端的js是不可以直接访问该cookie的。

  • PHP设置HttpOnly

    • 修改php.ini文件,设置session.cookie_httponly =1
    • setcookie()函数和setrawcookie()函数的第七个参数用来做HttpOnly启动选项
      setcookie('','','','','','',TRUE);
      setrawcookie('','','','','','',TRUE);
      
    • php代码开启HttpOnly
      <?php
          ini_set("session.cookie_httponly",1);
          session_set_cookie_params(0,null,null,null,TRUE)
      ?>
      

客户端预防

用户在访问网站的时候为了防止恶意脚本在自己的客户端上呗执行,也可以在浏览器上安装一个插件,利用插件的功能来禁止页面的脚本执行。



XSS基础学习

原文地址:https://www.cnblogs.com/wangyuyang1016/p/12196045.html

时间: 2024-11-05 16:08:11

XSS基础学习的相关文章

结合代码对xss基础的学习

前言:有人曾经说过,XSS之所以那么流行,就是因为每个网站,包括Google.Microsoft等,都会存在XSS漏洞!之前对XSS这块"肥肉"只是了解,没有系统的学习一下.趁着暑假赋闲,来系统的剖析一下这块'肥肉'. 0x01 xss基础 Cross Site Script For web client 来源于js / ActiveX / Flash - js xss使用场景 直接嵌入html: <script>alert(/xss/);</script> 元

ASP.Net MVC开发基础学习笔记:二、HtmlHelper与扩展方法

一.一个功能强大的页面开发辅助类—HtmlHelper初步了解 1.1 有失必有得 在ASP.Net MVC中微软并没有提供类似服务器端控件那种开发方式,毕竟微软的MVC就是传统的请求处理响应的回归.所以抛弃之前的那种事件响应的模型,抛弃服务器端控件也理所当然. 但是,如果手写Html标签效率又比较低,可重用度比较低.这时,我们该怎样来提高效率呢?首先,经过上篇我们知道可以通过ViewData传递数据,于是我们可以写出以下的Html代码: <input name="UserName&quo

蓝鸥零基础学习HTML5—html+css基础

蓝鸥零基础学习HTML5-html+css基础 一.课程目标 1.了解前端开发职位:2.掌握常用标签以及语义及用法:3.掌握常用css的特性,掌握基础布局技巧:4.掌握整站规划概念. 二.适用人群 零基础积极学习html5者 三.课程简介 本课程主要讲解了 html+css的基础知识,包括html模板.标签.css基础样式.布局.表格表单.整站等等,是进行前端开发的基础.Html+css是前端开发的基础,大部分前端开发工程都需要从html+css布局开始,html+css的基础非常重要,是前端开

HTML&CSS基础学习笔记8-预格式文本

<pre>标签的主要作用是预格式化文本.被包围在 pre 标签中的文本通常会保留空格和换行符.而文本也会呈现为等宽字体. <pre>标签的一个常见应用就是用来表示计算机的源代码.当然你也可以在你需要在网页中预显示格式时使用它. 会使你的文本换行的标签(例如<h>.<p>)绝不能包含在 <pre> 所定义的块里.尽管有些浏览器会把段落结束标签解释为简单地换行,但是这种行为在所有浏览器上并不都是一样的. 更多学习内容,就在码芽网http://www.

Objc基础学习记录5

NSMutableString类继承的NSString类. NSMutableString是动态的字符串. 1.appendingString 方式: 向字符串尾部添加一个字符串. 2.appendingFormat:可以添加多个类型的字符串. int,chat float,double等 3.stringWithString 创建字符串, 4.rangeOfString 返回str1在另一个字符串中的位置. 5.NSMakeRange(0,3) 字符串0位到3位. 6.deleteCharac

Linux新手入门书籍推荐 鸟哥的linux私房菜-基础学习篇

这本书写的不错.赞~\(≧▽≦)/~ 2017-02-24 下午,我开始在Linux下写第一个.c程序,在终端打印hello world.gcc 源代码文件之后,输出可执行文件,但是 当我输入文件名执行它的时候,却提示我 无法找到命令.于是我找百度,查资料,花了半个小时,终于找到解决方法了, 输入"./filename"即可.... 2017-02-25 我看<基础学习篇>这本书,在P158页下面的例题讲解中找到了昨天下午异常的解析.我就很是感慨,心想:要是早看这本书,半个

Java基础学习——数组初识(1)

Java基础学习--数组初识(1) 1什么是数组 Java中常见的一种数据结构就是数组,数组可以分为一维数组.二维数组和多维数组. 数组是由一组相同的变量组成的数据类型,数组中每个元素具有相同的数据类型,数组中的每个元素都可以用一个统一的数组名和下标来确定. 2 数组的使用 数组的一般使用步骤: 声明数组 分配内存给该数组 下面是一维数组为例: 数据类型  数组名 []: 数组名 = new 数据类型 [数据个数]: 2.1一维数组的声明与赋值 1.数组的声明 int  num [];    

零基础学习 Hadoop 如何下手

想学习hadoop,可是苦于自己没有任何的基础,不知道该如何下手,也不知道自己能不能学会.其实零基础学习hadoop,没有想象的那么困难.曾经我也是一位小白,刚接触到云计算,想过培训,但是培训机构的选择也让我很纠结,就自己开始去摸索学习,现在我把自己的学习思路整理一下,希望对大家有帮助. 首先整体说一下学习过程给大家借鉴: 一.了解hadoop: 这里不具体阐述概念,有兴趣的同学可以自己上网去查.我们知道hadoop,有单机安装,伪分布安装和分布安装.同时hadoop的环境是Linux,所以我们

HTML&CSS基础学习笔记13—无序列表

无序列表 有时我们的工作繁忙,杂事很多,怕忘记,就会把事情一件件列出来,防止忘记. 它们的排列顺序对于我们来说并不重要,可以随意调换,我们将它称为无序列表,HTML里用<ul>标签来表示无序列表,列表里的项目则用<li>标签来表示: 1 2 3 4 5 <ul>     <li></li>     <li></li>     ... </ul> 看一段实例代码: 对于的浏览器显示结果是这样的: 更多内容学习,请