前言
这里是我做《从0到1:CTFer成长之路》上的题的一些记录。
本篇是 Web 篇。
Web 入门
常见的搜集
打开靶机发现啥也没有。因此需要我们进行信息搜集。
使用 dirsearch 一共扫到了这些文件和目录(注意扫描的频次,过高会导致扫不出来):
1 | /index.php |
先看一下 robots.txt
,里面内容如下:
1 | User-agent: * |
访问 /flag1_is_her3_fun.txt
,我们就能拿到 flag 的第一部分了。
接下来访问 /index.php~
,拿到 flag 的第二部分。
最后把 /.index.php.swp
下载到本地,发现里面有这么一段代码:
1 | echo 'flag3:p0rtant_hack}'; |
成功拿到 flag 第三部分,拼起来就是最终的 flag 了。
index.php 是常见的主页文件
index.php~ 是 gedit 编辑文件保存后的备份文件
.index.php.swp 是 vim 编辑文件后的缓存文件
robots.txt 告诉搜索引擎哪些文件希望让爬虫获取哪些不希望让它获取
粗心的小李
启动靶机以后直接就告诉你是 Git 泄露,我们直接使用工具 scrabble 把 .git
爬下来就行,发现一个 index.html
,打开就能看到 flag 了。
正常来说,应该是先用 dirsearch 扫到 .git
文件夹后怀疑存在 Git 泄露再用工具下载。
SQL注入-1
启动靶机后直奔地址栏,发现注入点 /index.php?id=1
直接告诉你了,直接开整。
因为 id 是数字,且页面中有标题有正文,先构造 payload:1+ORDER+BY+2+--+
,发现行不通,怀疑是字符型的了。
再试试 1'+ORDER+BY+2+--+
,发现正常回显了,最后试出来共返回三个数据。
再构造 payload:'+UNION+SELECT+'aaa','bbb','ccc'+--+
来确定是哪两个回显的,得知是后两个。
再构造 payload:'+UNION+SELECT+NULL,NULL,TABLE_NAME+FROM+information_schema.tables+WHERE+TABLE_SCHEMA=DATABASE()+--+
,拿到数据库里的表名 fl4g
。
再构造 payload:'+UNION+SELECT+NULL,NULL,COLUMN_NAME+FROM+information_schema.columns+WHERE%20TABLE_NAME='fl4g'+--+
,拿到表里的列名 fllllag
。
最后使用 payload:'+UNION+SELECT+NULL,NULL,fllllag+FROM+fl4g+--+
,拿到最终的 flag。
Web进阶
XSS闯关
第一关
观察到 url 中有 ?username=xss
,而网页中正好存在 welcome xss
,猜测是直接替换。
payload: level1?username=<script>alert(1)</script>
第二关
一开始以为和第一关一样,但是没有用。
查看网页源代码后发现 document.getElementById('ccc').innerHTML= "Welcome " + escape(username);
。
而 username
定义时如果字符串中有 /
就会报错,于是想到注入点可以在变量定义那里 var username = 'xss';
,闭合语句即可。
payload:level2?username=';alert(1);//
,变量定义的语句变为 var username = '';alert(1);//';
。
第三关
这次先用第二关的 payload,然后直奔网页源代码,发现字符都被转义了。
var username = '\';alert(1);//'
但是莫名其妙的事情发生了,我直接 ?username='';alert(1);//
居然直接过了,看了源代码居然只转义了一个,var username = '\'';alert(1);//'
,就很迷,可能是后端写锅了?
神奇的 payload:level3?username='';alert(1);//
,官方正解是写入标签 level3?username=<img src=233 onerror=alert(1)>
第四关
发现是自动跳转的网页,源代码里发现注入点是 jumpUrl
,使用 JavaScript 伪协议来实现。
payload:level4?jumpUrl=javascript:alert(1)
第五关
直接提交发现不太行,观察源代码。
发现有 autosubmit
action
两个参数,其中需要我们把 autosubmit
置 1,然后会跳转到 action
参数的链接。
比方说,有 level5?autosubmit=1&action=233
,网站会跳转到 /233
上去。
于是再用 JavaScript 伪协议,得到 payload:level5?autosubmit=1&action=javascript:alert(1)
第六关
先随便试了一下,发现对输入进行了转义。
查看源代码后发现使用了 angular.js
模板引擎,就去稍微了解了一下。
angular.js
模板引擎分为 JiT 和 AoT 两种编译方式,Jit 保留了 Angular 的 {{}}
,在浏览器中由 JS 来动态解释,AoT 则是现在本地编译好,再上传到实际环境中。
实际测试发现是 JiT 形式的,且可更改的地方被 ng-app
所包裹。
试着写入模板 level6?username={{2*2}}
,回显是 welcome 4
,源代码是 welcome {{2*2}}
,验证了之前的想法。
现在要想办法让 angular.js
解析的时候执行指定的命令如 alert
,该怎么办呢?
上网查阅了资料,首先发现 angular.js
有对字符串解析为语句的函数 $eval
,但 angular.js
有类似沙箱的机制,会对 $eval
的参数进行解析。
作为一个纯萌新,就开始观摩大佬的文章。
然而东西有点多啊,得开新文章来专门讲一下了。。。
真的佩服这种代码审计的大佬,几万行的代码还要找出逻辑上的漏洞。
先放结论,更为细致的研究请等新文章吧。
payload:level6?username={{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1)//');}}
这种题目是怎么敢只放在进阶的啊,只论 exp 不论原理了吗
文件上传
题目告诉了我们源码,我们先分析代码逻辑。
有一个 check_dir($dir)
函数,对 $dir
文件夹进行递归删除非 .jpg
.gif
.png
的文件。
每次上传文件会随机生成一个临时文件夹用于存放上传的文件,仅允许上传 .zip
.jpg
.gif
.png
文件,如果是压缩包,则会对压缩包进行解压,并对解压后的文件夹进行 check_dir
。关键的一点,本题不含文件包含,因此上传的文件必须能被服务器解析才行。
本题提示每5分钟会清除一次目录下上传的文件,做题的时候没注意时间,意外发现 404 报错时给了服务器提示 Apache/2.4.7 (Ubuntu) Server
,而 Apache 存在多后缀文件解析漏洞。
检查十分严格,只能从压缩包解压入手,做 MISC 题的时候常有压缩包带密码的情景,这时候会把里面未加密的文件解压出来,但最后解压还是失败的,但出题人连这个都过滤了,就算异常解压也会检查目录下的文件。这个代码逻辑完全正确,一时没有办法。
后来得知 PclZip 有目录穿越漏洞,解题的法则便确定了。
我们新建一个 000000shell.php.PHP
,文件名中的 0 是占位符,文件内容随意,打包成一个 zip 文件。然后用 010 Editor 将压缩包里的 frFileName
和 deFileName
改成 ../../shell.php.PHP
,因为解压的目录是临时目录,所以返回两层才是网站根目录,而且并不会被定时删除。
然后访问 /shell.php.PHP
就能拿到 flag。
P.S. 这题环境挺奇怪的,一般都是一句话木马之类的,但这题只要正常解析就行,还必须是 .php
,而且蚁剑还不能连,不知道能不能拿到服务器配置看一下。
逻辑漏洞
进去发现是个登录界面,随便输啥都能登录成功,发现是个买东西的界面,显而易见我们需要购买 flag 这个商品。
但是 flag 需要 2000 块钱,我们买不了,但是我们可以买别的东西,发现购买成功,且传递的参数有 cost
和 goods
,而 cost
的值正好是标价。
一个正常的商店肯定是不需要传递 cost
值的,说明我们可以在这个参数上做文章。
我们先 /buy.php?cost=0&goods=1
,发现钱不够,猜测判断能否购买是根据数据库来的。那么这个 cost
有什么用呢?看来是余额去减的值了。
我们只需要找到能买的商品,然后将 cost
设为负数即可。payload:/buy.php?cost=-100000&goods=3
,然后再去购买就能拿到 flag 了。