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基础学习的更多相关文章

  1. Python web框架 Tornado(一)基础学习

    概述 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过为了 ...

  2. salesforce 零基础学习(五十二)Trigger使用篇(二)

    第十七篇的Trigger用法为通过Handler方式实现Trigger的封装,此种好处是一个Handler对应一个sObject,使本该在Trigger中写的代码分到Handler中,代码更加清晰. ...

  3. 如何从零基础学习VR

    转载请声明转载地址:http://www.cnblogs.com/Rodolfo/,违者必究. 近期很多搞技术的朋友问我,如何步入VR的圈子?如何从零基础系统性的学习VR技术? 本人将于2017年1月 ...

  4. IOS基础学习-2: UIButton

    IOS基础学习-2: UIButton   UIButton是一个标准的UIControl控件,UIKit提供了一组控件:UISwitch开关.UIButton按钮.UISegmentedContro ...

  5. HTML5零基础学习Web前端需要知道哪些?

    HTML零基础学习Web前端网页制作,首先是要掌握一些常用标签的使用和他们的各个属性,常用的标签我总结了一下有以下这些: html:页面的根元素. head:页面的头部标签,是所有头部元素的容器. b ...

  6. python入门到精通[三]:基础学习(2)

    摘要:Python基础学习:列表.元组.字典.函数.序列化.正则.模块. 上一节学习了字符串.流程控制.文件及目录操作,这节介绍下列表.元组.字典.函数.序列化.正则.模块. 1.列表 python中 ...

  7. python入门到精通[二]:基础学习(1)

    摘要:Python基础学习: 注释.字符串操作.用户交互.流程控制.导入模块.文件操作.目录操作. 上一节讲了分别在windows下和linux下的环境配置,这节以linux为例学习基本语法.代码部分 ...

  8. CSS零基础学习笔记.

    酸菜记 之 CSS的零基础. 这篇是我自己从零基础学习CSS的笔记加理解总结归纳的,如有不对的地方,请留言指教, 学前了解: CSS中字母是不分大小写的; CSS文件可以使用在各种程序文件中(如:PH ...

  9. Yaf零基础学习总结5-Yaf类的自动加载

    Yaf零基础学习总结5-Yaf类的自动加载 框架的一个重要功能就是类的自动加载了,在第一个demo的时候我们就约定自己的项目的目录结构,框架就基于这个目录结构来自动加载需要的类文件. Yaf在自启动的 ...

随机推荐

  1. css技巧 1200px居中容器中某个div增加横屏背景

    <div class='container' style='width:1200px;margin:0 auto;'> <div style='width:200px;margin: ...

  2. 纯JS前端分页方法(JS分页)

    1.JS分页函数:开发过程中,分页功能一般是后台提供接口,前端只要传page(当前页码)和pageSize(每页最大显示条数)及对应的其他查询条件,就可以返回所需分页显示的数据. 但是有时也需要前端本 ...

  3. HDU 1850 Nim-Sum思想总结、

    算法介绍: Nim游戏是指两个对手在m个堆中轮流随意从某一个堆中拿出n个元素,假定两个对手都是足够聪明,直至最后一次取的人将所有元素取出,此人取得胜利.与之相反的是Misere游戏,相同的游戏规则,但 ...

  4. 2019-7-29-WPF-元素裁剪-Clip-属性

    title author date CreateTime categories WPF 元素裁剪 Clip 属性 lindexi 2019-7-29 10:0:13 +0800 2019-1-3 15 ...

  5. laravel-admin新手的使用

    1.添加页面 配置好laravel-admin的模板后 点击管理员管理里的菜单列表,输入如下信息即可 提交之后刷新页面,左侧菜单就会显示新增的广告管理的标签 2.定义路由 配置好前端的页面显示之后就要 ...

  6. word 筛选过的网页,网页,单个文件网页

    1)筛选过的网页:保存后会生成 xxx.htm和xxx.files文件夹,删除了还原成Word文档所需的格式标记和功能,也就是说存为纯网页了,文件尺寸小:2)网页:保存后会生成 xxx.htm和xxx ...

  7. H3C配置设备的FTP服务

  8. 【t081】序列长度

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 有一个整数序列,我们不知道她的长度是多少(即序列中整数的个数),但我们知道在某些区间中至少有多少个整数 ...

  9. eslint的使用和配置

    eslint的使用和配置 什么是eslint ESLint 是在 ECMAScript/JavaScript 代码中识别和报告模式匹配的工具,它的目标是保证代码的一致性和避免错误.在许多方面,它和 J ...

  10. Nginx与PHP交互过程 + Nginx与PHP通信的两种方式

    一.Nginx与PHP交互过程的7步走(用户对动态PHP网页访问过程) step1:用户将http请求发送给nginx服务器(用户和nginx服务器进行三次握手进行TCP连接) step2:nginx ...