关于

简介

XSS(Cross Site Scripting),跨站脚本攻击。攻击者通过网站注入点注入客户端可执行解析的payload,当用户访问网页时,恶意payload自动加载并执行,以达到攻击者目的(窃取Cookie、恶意传播、钓鱼欺骗等)。

危害

  1. 获取用户信息:浏览器信息、IP地址、Cookie等;
  2. 钓鱼:构造与原网站相似的网站,骗取账号密码;
  3. 注入密码或广告链接:在主站注入非法网站的链接;
  4. 后台增删改查数据:配合CSRF,骗取用户点击,利用JS模拟浏览器发包;
  5. XSS蠕虫:进入网站自动进行某些操作,例如关注博主或者自动回复。

基本类型

主要分为三种:

  • 反射型XSS:非持久化,需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),一般容易出现在搜索页面。反射型XSS大多数是用来盗取用户的Cookie信息。

  • 储存型XSS:持久化,代码是存储在服务器中的,如在个人信息或发表文章等地方,插入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,用户访问该页面的时候触发代码执行。这种XSS比较危险,容易造成蠕虫,盗窃cookie。

  • DOM型XSS:不经过后端,DOM-XSS漏洞是基于文档对象模型(Document Objeet Model,DOM)的一种漏洞,DOM-XSS是通过url传入参数去控制触发的,其实也属于反射型XSS。

反射型

特点

  • 仅执行一次,非持久型;
  • 参数型跨站脚本。

攻击流程

源代码

  • 前端页面:
<html>

<head>
  <title>反射型XSS</title>
</head>

<body>
  <form action="xss1.php" method="get">
    Please input your name:
    <input type="text" name="name" />
    <input type="submit" />
  </form>
</body>

</html>
  • 后端页面:
<?php
  if (array_key_exists("name", $_REQUEST) && $_REQUEST['name'] != NULL) {
    $name = $_REQUEST['name'];
    echo 'Welcome *' . $name . '*';
  }
?>

演示

前端是一个提交框,提交数据到后端

后端会把输入的数据展示出来

注入JS:<script>alert(1)</script>,进入页面会执行

在源码中可以看到已经成功注入

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

储存型

特点

  • 持久型;
  • 恶意脚本直接储存到数据库中。

攻击流程

源代码

  • 前端页面
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>储存型XSS</title>
</head>

<body>
  <form action="xss2.php" method="post">
    <table>
      <tr>
        <td>昵称:</td>
        <td><input type="text" name="nickName" /></td>
      </tr>
      <tr>
        <td>留言:</td>
        <td><textarea name="message" rows="3"></textarea></td>
      </tr>
      <tr>
        <td>&nbsp;</td>
        <td>
          <input name="sign" value="添加留言" type="submit" onclick="return validate_form(this.form);"></input>
          <input name="delete" value="清除留言" type="submit" onclick="return firm();"></input>
        </td>
      </tr>
    </table>
  </form>
</body>
<script type="text/javascript">
  function validate_required(field, info) {
    with (field) {
      if (value == null || value == "") {
        alert(info);
        return false;
      } else {
        return true;
      }
    }
  }
  function validate_form(form) {
    with (form) {
      if (!validate_required(nickName, "昵称不能为空!")) {
        nickName.focus();
        return false;
      }
      if (!validate_required(message, "消息内容不能为空!")) {
        message.focus();
        return false;
      }
    }
  }
  function firm() {
    return confirm("确定清除所有留言吗?");
  }
</script>

</html>
  • 后端页面
<?php
$conn = @mysql_connect('localhost', 'root', 'root') or die('failed');
@mysql_select_db('xss', $conn);

if (array_key_exists("delete", $_POST)) {
  $query = "TRUNCATE xss";;
  $result = @mysql_query($query, $conn) or die(mysql_error());
  echo "<script>alert('清除成功!')</script>";
}

if (isset($_POST['sign'])) {
  $message = trim($_POST['message']);
  $username = trim($_POST['nickName']);

  $query = "INSERT INTO xss ( username, message) VALUES ('$username', '$message');";
  $result = @mysql_query($query, $conn) or die(mysql_error());
  echo "<script>alert('添加成功!')</script>";
}

$query = "SELECT username, message FROM xss;";
$result = mysql_query($query, $conn) or die(mysql_error());

while ($row = mysql_fetch_assoc($result)) {
  $name = $row['username'];
  $message = $row['message'];

  echo "<div> Name:" . $name . "<br>";
  echo " Message:" . $message . "</div><br>";
}
?>

演示

前端是一个表单,用于将数据提交到后端

后端用于接收数据,并将数据展示给用户

注入JS代码:<script>alert(1)</script>,成功弹窗

查看数据库,成功插入数据

每次进入页面都会执行代码

DOM型

特点

  • 全程在前端执行,不经过后端;
  • 主要存在于能修改页面的dom。

攻击流程

无交互,全程在前端执行

源代码

<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>DOM型XSS</title>
</head>

<body>
  <script type="text/javascript">
    var pos = document.URL.indexOf("name=") + 5;
    eval(document.URL.substring(pos, document.URL.length));
  </script>
  <h2>This is a xss test ...</h2>
</body>

</html>

演示

一个简单的页面

传入参数后会被执行

防护

总体思路是对用户的输入进行过滤,对输出进行编码阻止恶意操作的执行

不管是哪种类型的XSS,都可以在服务端进行过滤。

黑(白)名单

  • 黑名单:过滤特殊符号及字符
  • 白名单:限制类型或符号

httponly

在setcookie中将httponly选项设置为true

str_replace()

  1. 功能:替换字符串,区分大小写

  2. 用法:

    $name = str_replace('<script>', '', $name);

preg_replace()

  1. 功能:对目标字符串进行一次正则替换,i模式下不区分大小写

  2. 用法:

    $name = preg_replace('/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t(.*)>/i', '', $name);

htmlspecialchars()

  1. 功能:把预定义的字符转换为HTML实体,防止被浏览器当做HTML元素

  2. 用法

    $name = htmlspecialchars($name);

绕过

<>

<>被过滤时,可以利用标签自带的事件绕过

  • 输入框:onfocus、onclick
  • svg:onload

script

利用img标签的onerror属性执行JS

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

友链

XSS载荷大全

XSS平台

xss-labs