# XSS 跨站脚本攻击

xss 也叫 css 为了和层叠样式表(Cascading Style Sheets,CSS)的缩写区分。因此将跨站脚本攻击缩写为 XSS。

xss 攻击是指攻击者在网页中嵌入客户端脚本,通常是 js 代码,在用户访问时,恶意代码执行

# 原理刨析

攻击者可以通过一些方式向网页中写入恶意代码,导致用户在加载网页时浏览器渲染执行了恶意脚本

上面提到 xss 攻击是嵌入客户端脚本,大多数是 js,少部分使用 AS 和 VBS,那么也就是说在能够利用漏洞的情况下,js 能做到什么效果,xss 的利用就能做到什么效果

javaScript加载外部的代码文件可以是任意文件扩展名,即使是图片扩展名只要包含js代码就能执行

# xss 分类

主要被分为三种,反射型,储存型和 DOM 型,接下来详细说明

# 反射型

首先,先盗个图

image-20221025215134992

反射型 xss 也被称为非持久型的 xss,反射型 xss 是当先最常见的一种 xss 漏洞。攻击者将带有 xss 恶意脚本的连接发给用户诱导其点击,用户向服务器请求了一个带有 xss 脚本的 url 请求,服务器返回给浏览器,浏览器解析 xss 脚本区访问了恶意服务器造成漏洞

demo

<?php
$name=$_GET['name'];
echo "Hello $name";
?>

服务端对用户的 name 没有进行过滤,服务器解析后通过 echo 插入到 HTML 中

image-20221025221057624

这里插入 js,便可执行

image-20221025221207814

# 存储型

还是先盗个图(我发四,本篇最后一张)

image-20221025220126444

刚刚说到反射型也叫非持久性,那么存储型就是持久型 xss,与 xss 的区别就是提交的 xss 代码是否会被存储在服务端,下次访问到这个页面时还会执行恶意脚本。(存储型 xss 不在是攻击者诱导受害者点击连接,而是将 xss 脚本留在目标服务器上,当受害者访问了存有 xss 脚本的页面时就受到了攻击,允许用户进行数据存储的地方都有可能存在 xss 漏洞,这种 xss 攻击比反射型危害更大。)

demo

<?php
echo "<script>alert('xss')</script>";

保存到文件中,每次访问时都会执行

image-20221025221521051

# DOM 型

个人理解其实也算是反射型,但是 DOM 型的 xss 不需要与服务端交互,仅仅发生在客户端处理数据的阶段,DOM 全称 Document Object Model(文档对象模型),对于浏览器来说 DOM 就是一份 xml,JavaScript 重构 HTML 页面的过程中使用 DOM 提供结构化表示,DOM 规定 HTML 中每个成分都是一个结点

DOM规定:
整个文档是一个文档结点
每一个HTML标签是一个元素结点
包含在HTML元素中的文本是文本结点
每个HTML属性是一个属性结点
结点与结点之间都有等级关系

HTML DOM 树

image-20221025224329456

可能触发DOM型XSS的属性
document.referer属性

window.name属性

location属性

innerHTML属性

documen.write属性

# DOM 型 xss 利用原理

利用前提是 js 可以访问 DOM 文本对象模型,如果客户端代码中有 xss 脚本诱导用户点击可以使得用户访问自己构造的 url,达到和反射型类似的效果,因其不与服务器进行交互,可以用来绕过 waf


<script>
    var tem = document.URL;// 获取当前页面的 URL
    var index = document.URL.indexOf("content=")+4;// 获取 content = 后面的内容
    var par = tem.substring(index);// 获取参数
    document.write(decodeURI(par));//decodeURI () 解码 // 输出参数
</script>

image-20221026213845778

# Xss 的检测

检测 xss 主要有两种方法,一种是手工检测,一种是通过自动化工具检测,个人感觉两种方法没有先后各有利弊吧。手工检测的精度更高,但是当一个 web 应用程序过于庞大的情况,手工检测是非常困难的,用工具自动化检测精度相对要低上不少

# 手工检测 xss

手工检测时,主要考虑有输出和能够存储的地方进行测试,可以尝试使用特征明显的字符来进行测试

< > "  ' ( )等字符

同时携带上如 AAAAAAA 字便于查找插入到 HTML 中的位置

# Xss 工具

这里工具很多不再一一赘述,推荐去 GitHub 上寻找开源的工具

# Xss 的利用种类

在一些情况下 xss 漏洞的危害不亚于 sql 注入,常见的利用方法:

  • 盗取用户 cookie
  • 修改网页内容
  • 网站挂马
  • 利用网站重定向
  • xss 蠕虫

# xss 会话劫持

这里多数是指劫持 cookie 或 session 达到目的

cookie 是一种能够将少量文本存储到客户端的磁盘、内存上面或者从客户端的内存、磁盘上面读取的一种技术

一位我尊敬的师长说过,每一种技术或者协议的产生都是由需求驱动的,cookie 的产生主要是为了解决 http 协议的无状态,web 服务器需要额外的数据用于维持会话,cookie 正是一一段随 http 请求的响应的额外数据,他的主要作用是标识用户维持会话

cookie 主要分为持久 cookie 和非持久 cookie,这两种分类的主要区别就是持久 cookie 是存储到客户端的磁盘中的只有到了过期时间或者手动删除才会失效,非辞旧 cookie 是存储到客户端的内存上的,浏览器关闭后就会消失

cookie一般会经过加密,只有服务器的处理程序才知道cookie的含义

部分开发者将 cookie 作为用户的标识,那么我们就可以通过劫持 cookie 来登录账号,而部分开发者不会将 cookie 当作用户的标识,而是储存一些临时信息,那么我们拿到 cookie 也是没用的

# session

除去 cookie 外维持会话的另一种形式就是 session,session 在网络应用中被称为会话是一种服务端的机制,我们打开网站到关闭浏览器这段时间被称为会话,如果我们在服务端与客户端的会话没结束时就拿到 session 就能做到劫持会话的效果

# xss 漏洞攻与防

xss 跨站脚本漏洞的根本原因还是开发者对用户的输入输出没有进行严格的过滤,而导致的客户端脚本被浏览器正常执行导致,这也就意味着如果我们能够将敏感字符过滤就能够修补 xss 漏洞

# 特定的标签过滤

部分开发者认为将危险的标签过滤掉就不会执行 js 脚本,但是实际上任何一种标签无论是否合法都能够正常执行 js 脚本

<not_real_tag onclick="alert(/xss/)" >click me</not_real_tag>

像这样构造也能正常执行 xss 脚本,也就是说如果输出点在 HTML 标签中或者 js 脚本中,那么我们可以通过简单的闭合拼接属性那么就可以成功执行 xss

# 事件过滤

很多时候开发者者会选择过滤事件来防止 xss,但是不排除有漏网之鱼,这里可以 fuzz 尝试

Fuzz字典分享:
onafterprint
oninput
onscrol1
onbeforeprint
oninvalid
onabort
onbeforeunload
onreset
oncanplay
onerror
onselect
oncanplaythrough
onhaschange
onsubmit
ondurationchange
onload
onkeydown
onemptied
onmessage
onkeypress
onended
onoffline
onkeyup
onerror
ononline
onclick
onloadeddata
onpagehide
ondblclick
onloadedmetadata
onpageshow
ondrag
onloadstart
onpopstate
ondragend
onpause
onredo
ondragenter
onplay
onresize
ondragleave
onplaying
onstorage
ondragover
onprogress
onundo
ondragstart
onratechange
onunload
ondrop
onreadystatechange
onblur
onmous edown
onseeked
onchange
onmous emove
onseeking
oncontextmenu
onmouseout
onstalled
onfocus
onmouseover
onsuspend
onformchange
onmouseup
ontimeupdate
onforminput
onmousewheel
onvolumechange

同样还有一些不属于事件属性,但可以用于执行 js 代码,比如常见的 js 伪协议

<a herf="javascript:alert(/xss/)">click me </a>

# 敏感字符的过滤

在 html 中,<>" 和 '& 都有特殊的意义,HTML 的标签属性就是由这几个字符组成的,如果直接输出可能会导致整个 HTML 文档的结构,所以我们通常情况将这些字符转义,比如 php 提供了 htmlspeciachars 和 htmlentities 两个函数把一些预定字符转义转换成 HTML 实体

  • (&) 成为 & amp
  • (") 成为 & quot
  • (') 成为 &#039
  • (<) 成为 & lt
  • (>) 成为 & gt

关键字过滤其实大部分是针对敏感变量或者函数进行的,如 eval,cookie 等,这部分的过滤可以通过字符串拼接,编码解码等方法绕过

# 字符串拼接混淆

js 中的对象方法可以通过数组的方式进行调用,比如调用 alert 函数

window['alert'](/xss/);

这里数组的下标是先要调用函数名字的字符串,既然说是字符串那么就可以通过字符串拼接的方式

window['al'+'ert'](/xss/);

或者通过 js 自带的 base 编码来实现字符串的绕过

window[atob("YWxl"+"cnQ=")](/xss/);

# 编码解码

基于字符串的代码混淆不仅可以通过字符串拼接的方式,还可以通过各种编码的方式,常用的有:

  • HTML 进制编码
  • css 进制编码
  • js 进制编码
  • url 编码
  • jsfuck 编码(一种只有!+6 个字符来编写 js 程序)

# location*,window.name

既然开发者会对输入的敏感字符进行过滤,可以将 xss 脚本放到不会交付到服务端的部分

# 过滤 "."

事件拼接都由点组成,可以过滤点来防御

但是在 js 中可以用 with 关键字设置变量的作用域。利用这个特性可以绕过点的过滤

with(document)with(cookie)

# 过滤 "()"

js 脚本中调用对象方法要使用 (), 使用 throw 关键字传递阐述可以绕过限制

window.onerror=alert; throw 1;

# 过滤空格

在标签属性间可以通过换行符 0x09、0x10、0x12、0x13、0x0a 等字符代替空格绕过过滤

<img%0asrc=x%0aonerror=alert(/xss/)>

在标签名称和第一个属性间也可以使用 "/" 代替空格

<input/onfocus=alert(/xss/)>

# HTTPonly 绕过

HTTPonly 是 cookie 的一个安全属性,设置后可以防止 xss 漏洞产生的时候避免 js 脚本获取到 cookie

# cve-2012-0053

Apache 服务器在 2.2.0-2.2.21 版本中存在一个漏洞,我们可以通过向网站植入一个超大的 cookie,令其 HTTP 头超过 Apache 的最大请求长度(4192 字节),使得 apache 返回 400 错误,状态也中包含了 HTTPonly 保护的 Cookie

# phpinfo 页面

无论设置是否设置了 HTTPonly 在 phpinfo 中都能看到 Cookie