Security ❀ CSP Bypass 内容安全策略绕过
Posted 无糖可乐没有灵魂
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Security ❀ CSP Bypass 内容安全策略绕过相关的知识,希望对你有一定的参考价值。
文章目录
内容安全策略绕过 CSP Bypass
CSP - 内容安全策略:为了缓解很大一部分潜在的跨站脚本XSS问题,浏览器的扩展程序系统引入了内容安全策略CSP 的概念。通过引入一些相当严格的策略使扩展程序在默认情况下更加安全,开发者可以创建并强制应用一些规则,管理网站允许加载的内容。
CSP以白名单的机制对网站加载或执行的资源起作用,在网页中策略通过HTTP头部信息或meta元素定义。CSP虽然提供了强大的安全保护,但是它也令eval()及相关函数被禁用、内嵌的javascript代码将不会执行、只能通过白名单来加载远程脚本。如果要使用CSP技术保护自己的网站,开发者就不得不花费大量时间分离内嵌的JavaScript代码和做一些调整。
1 Low Level
源码:
<?php
# 指定headerCSP变量,防置了一些url
$headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com hastebin.com example.com code.jquery.com https://ssl.google-analytics.com ;"; // allows js from self, pastebin.com, hastebin.com, jquery and google analytics.
# 使用header函数调用变量headerCSP发送到客户端或浏览器
header($headerCSP);
# These might work if you can't create your own for some reason
# 绕过案例
# https://pastebin.com/raw/R570EE00
# https://hastebin.com/raw/ohulaquzex
?>
# 使用script src指令指向一个外部JavaScript文件
<?php
if (isset ($_POST['include']))
$page[ 'body' ] .= "
<script src='" . $_POST['include'] . "'></script>
";
$page[ 'body' ] .= '
<form name="csp" method="POST">
<p>You can include scripts from external sources, examine the Content Security Policy and enter a URL to include here:</p>
<input size="50" type="text" name="include" value="" id="include" />
<input type="submit" value="Include" />
</form>
';
源码对HTTP头部定义了CSP标签,定义了可以接受外部JavaScript资源的白名单,可以通过抓包确认是哪些网站;
其中https://pastebin.com
是一个快速分享文本内容的网站,若文本的内容是一段JavaScript代码,网页就会把代码包含起来;可以使用该域名进行创建包含JavaScript代码的URL,也可直接使用源码中的案例进行绕过操作。
# https://pastebin.com/raw/R570EE00
# URL回显内容:alert("pastebin");
2 Medium Level
源码:
<?php
# script src有了新的变化,unsafe-inline允许执行页面内嵌的<script>标签和事件监听函数,nonce值会在每次HTTP回应给出一个授权token
$headerCSP = "Content-Security-Policy: script-src 'self' 'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=';";
header($headerCSP);
# 禁用XSS保护
// Disable XSS protections so that inline alert boxes will work
header ("X-XSS-Protection: 0");
# 绕过案例
# <script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert(1)</script>
?>
<?php
if (isset ($_POST['include']))
$page[ 'body' ] .= "
" . $_POST['include'] . "
";
$page[ 'body' ] .= '
<form name="csp" method="POST">
<p>Whatever you enter here gets dropped directly into the page, see if you can get an alert box to pop up.</p>
<input size="50" type="text" name="include" value="" id="include" />
<input type="submit" value="Include" />
</form>
';
源码中nonce参数无任何过滤,对其进行注入即可。将绕过案例<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert(1)</script>
内容复制到输入框内,进行绕过弹窗测试。
3 High Level
源码:
<?php
$headerCSP = "Content-Security-Policy: script-src 'self';";
header($headerCSP);
?>
<?php
if (isset ($_POST['include']))
$page[ 'body' ] .= "
" . $_POST['include'] . "
";
$page[ 'body' ] .= '
<form name="csp" method="POST">
<p>The page makes a call to ' . DVWA_WEB_PAGE_TO_ROOT . '/vulnerabilities/csp/source/jsonp.php to load some code. Modify that page to run your own code.</p>
<p>1+2+3+4+5=<span id="answer"></span></p>
<input type="button" id="solve" value="Solve the sum" />
</form>
# script src指向了source/high.js代码文件
<script src="source/high.js"></script>
';
high.js代码:
function clickButton()
// src指向source/jsonp.php?callback=solveNum,document对象使我们可以从脚本中对html页面中的所有元素进行访问,createElement()方法通过指定名称创建一个元素
var s = document.createElement("script");
s.src = "source/jsonp.php?callback=solveSum";
// body 属性提供对 < body > 元素的直接访问,对于定义了框架集的文档将引用最外层的<frameset>,appendChild()方法可向节点的子节点列表的末尾添加新的子节点,也就是网页会把“source/jsonp.php?callback=solveNum”加入到DOM中
document.body.appendChild(s);
function solveSum(obj)
if ("answer" in obj)
// 定义solveNum函数,函数传入参数obj,字符串“answer”在obj中就会执行下面代码
document.getElementById("answer").innerHTML = obj['answer'];
// getElementById()方法可返回对拥有指定ID的第一个对象的引用,innerHTML属性设置或返回表格行的开始和结束标签之间的HTML。这里的script标签会把远程加载的solveSum("answer":"15")当作js代码执行,然后这个函数就会在页面显示答案
var solve_button = document.getElementById ("solve");
if (solve_button)
solve_button.addEventListener("click", function()
clickButton();
);
jsonp.php代码:
<?php
header("Content-Type: application/json; charset=UTF-8");
if (array_key_exists ("callback", $_GET))
$callback = $_GET['callback'];
else
return "";
# 代码中对callback参数无任何过滤限制,对其进行注入即可进行绕过
$outp = array ("answer" => "15");
echo $callback . "(".json_encode($outp).")";
?>
注入代码:include=<script src="source/jsonp.php?callback=alert(1);"></script>
4 Impossible Level
源码:
<?php
$headerCSP = "Content-Security-Policy: script-src 'self';";
header($headerCSP);
?>
<?php
if (isset ($_POST['include']))
$page[ 'body' ] .= "
" . $_POST['include'] . "
";
$page[ 'body' ] .= '
<form name="csp" method="POST">
<p>Unlike the high level, this does a JSONP call but does not use a callback, instead it hardcodes the function to call.</p><p>The CSP settings only allow external JavaScript on the local server and no inline code.</p>
<p>1+2+3+4+5=<span id="answer"></span></p>
<input type="button" id="solve" value="Solve the sum" />
</form>
<script src="source/impossible.js"></script>
';
impossible.js代码:
function clickButton()
var s = document.createElement("script");
s.src = "source/jsonp_impossible.php";
// JSONP调用的回调函数是硬编码的,CSP策略被锁定为只允许外部脚本
document.body.appendChild(s);
function solveSum(obj)
if ("answer" in obj)
document.getElementById("answer").innerHTML = obj['answer'];
var solve_button = document.getElementById ("solve");
if (solve_button)
solve_button.addEventListener("click", function()
clickButton();
);
jsonp_impossible.php代码:
<?php
header("Content-Type: application/json; charset=UTF-8");
$outp = array ("answer" => "15");
# outp值被锁死
echo "solveSum (".json_encode($outp).")";
?>
以上是关于Security ❀ CSP Bypass 内容安全策略绕过的主要内容,如果未能解决你的问题,请参考以下文章
Security ❀ CSP Bypass 内容安全策略绕过
Security ❀ CSP Bypass 内容安全策略绕过
DVWA 黑客攻防实战(十五) 绕过内容安全策略 Content Security Policy (CSP) Bypass