HCTF之Black-Eat-Black总结
这次HCTF,我负责黑吃黑这题的出题和运维,最终只有六星一个队日穿了该题。
题目名称:Black eat black(300不足,200有余)
题目描述:使用该DNS(180.153.47.182)后,你会被劫持哦~
分值:300
开题金币:300
奖励金币:400
writeup
先给出writeup脚本
1 | # writeup.py |
通过该脚本可以自由访问到gayhub,然后修改host或者url,可以任意文件读取(见脚本里的注释),读到 /etc/passwd
得到 hctf2015:x:1000:1000::/home/hctf2015:/usr/bin/whereisflag
由于 /usr/bin/whereisflag
不可读,则判断是要通过登陆触发该脚本,接下来就通过上传文件进行任意文件覆盖,上传自己的 id_rsa.pub
, 然后文件名设置为 ../../../../../../../../home/hctf2015/authorized_keys
则可通过ssh远程登陆。
正常情况下这样就getshell,可以结束了,但是为了增加题目的趣(keng)味(die)性,和并不让选手真正getshell,所以我把 /bin/bash
改成了 /usr/bin/whereisflag
六星撸出来的时候, whereisflag脚本是一个 B站答题系统,我从网上随便找了100多题,然后随机出13题作为填空题,无时间限制,一旦答错,将要重新开始,看在六星凌晨3点多还在做我的答题系统,还一直答不对的情况下(其实是被队友打了),我把题目减成了2题,然后六星的成功得到flag去睡觉了,而我还要盯着服务器…- -!
然后我觉得答题挺坑的(迫于队友压力),把答题的彩蛋换了,至于是啥,还没人见过,你们自己去看看吧,比B站答题简单多了。。。。
writeup就到这了,接下来是出题思路….
出题思路
最开始我的题只是一个 gayhub,分值我觉得不到200吧,然后服务端是 Nginx + Uwsgi + flask,但是发现Nginx竟然会吃 ../
(uwsgi也会,后面会说) ,这样就没法实任意文件读取了,如果少了任意文件,我觉得基本没人会想到上传 authorized_keys
,那么这题就变脑洞题了。
但是如果不配上 Nginx + Uwsgi ,然后题目描述直接把Gayhub暴露出来,我怕光flask负担不起各大赛棍的蹂躏。
在一次月黑风高夜夜,灵光一闪,有了现在的黑吃黑。
我用自己的服务器搭了一个dns服务器(怕被菊苣们日,所有服务都光了,只剩53和把ssh端口隐藏了),把所有的域名都指向了我的题目服务器。之后就是模拟DNS劫持,题目的服务器我写了一个flask作为中间人,负责劫持的你http,然后原封不动的进行转发。
通过 url = 'http://' + host + '/' + path ( + query)
这样的形式获取你要访问的网站,然后原封不动的获取的你headers 和 data,服务器进行请求,然后原封不动的返回。
然后 Gayhub 监听127.0.0.1:4444
这题的架构差不多就是这样。
Other
现在的Web题,除非是有啥黑魔法,或者能像P神那样出一道神一样的代码审计题,其他的我都觉得没啥意思,而我手中没有关于php的黑魔法,也出不了有意思的代码审计的题目,所以就想着另辟奇径,而最近flask用多了,就准备用它出一道web题,然后搜到了P神在wooyun发的python 的Tornado框架的任意文件读取,这个也可以在flask里复现,不过光读取也没意思,然后灵光一闪,想到了authorized_keys的没密码登陆。。。就这样gayhub诞生了,而这题的中心思想就是不需要任何过滤的Python Web,不过仍然还是有许多问题。
- 不配上Nginx + uwsgi受不住全国各大赛棍的蹂躏啊
- flask框架是没漏洞的,这两个漏洞都是我人为的。。。也不是很好
- 普通用户写文件默认权限是664,而authorized_keys要是644 或者 600 或者 640, 后两个不现实,但是在root权限下,默认就是644,不过肯定不能让root用户getshell,所以只能修改问题,把普通用户 umask 002。
不过之后加上DNS劫持就完美了,Gayhub放内网,剧情是未完成,因为未完成所以放内网,因为未完成所以只有登陆和传文件,因为未完成所以未做任何过滤。
所以该题的剧情就是,一个黑客对你进行了DNS劫持,你是被他劫持呢?还是找到他的漏洞进行反击? 所以有了黑吃黑的题目
仍然有问题:
只能对http进行劫持,不过我后来想到了方法把所有https换成http返回,然后记录下来,等如果请求的url等于https列表里的,则以https请求,返回数据。不过来不及,没完成。。。。。
redrain大神告知,该服务有个漏洞,可以通过该代理作为跳板去攻击或者dos他人,比如请求一个很大的图片,请求后就把连接断开,这样我的服务器去请求了那张大图片,而这图片却无法返回给攻击者,也就是可以用我服务的流量去攻击他人。 不过在目前情况下不现实,首先有云盾,其次。。特么我一天24小时盯着服务器呢。。我可以ban ip。。。。不过在真实情况下的确是一种攻击思路。。。。解决办法就是做缓存吧,上面说的https的时候就想做了。。。不过也是时间原因。没来得及。。
还有。。。。仍然挂nginx失败,同样会导致任意文件读取失败。。。但是这时候研究除了flask本身自带多线程,比赛第一天都是直接开flask,多线程跑的,不过还是怕负载太大挂了,第二天研究出了只挂uwsgi,成功,。。。。但是发现uwsgi也会吃 ../ (还好第二天没有人姿势是对的。。要不就坑人了),所以只能是80端口的代理服务挂载uwsgi,最后证明我是多虑了,,,我不用盯着服务器,ban人ip,在这种金币开题的赛制下,最后才31个队左右开了我的题,31个队中只有4个队发现了我的gayhub,10个队找上了我题目的服务器,所以说,根本没有压力。。。。。
当host是请求本机80的时候,会无限死循环,,,,特么,,这个最蛋疼。。看下面代码
1
2
3
4if "120.55.181.136" in request.host or request.host == '127.0.0.1' or request.host == '0.0.0.0' or '127.0.0.1:80' in request.host or '0.0.0.0:80' in request.host or "10.117.9.191" in request.host or 'iZ23l4savztZ' in request.host or request.host =='localhost' or 'localhost:80' in request.host:
request.host = 'www.baidu.com'
#各大赛棍一边日,我一边加。。。根本加不完,,,特么,,这确实是我考虑不周到,出现的非预期。。因为临时改,所以坑爹的写了我有生以来最长的一行代码了。。还是端口的问题,提示的有点勉强,如果是监听本地127.0.0.1端口,nmap是扫描不到的,不会显示filtered,按道理是要自己去扫出来,如果是监听0.0.0.0端口,然后iptables再设置下,会显示为filetered,不过却不符合实际。。最后为了降低难度(降低服务器负载),所以我把端口绑定到扫描出来为filtered状态的4444端口….
总结
第一次出题,有很多不足,比如当时有想过把文件写权限给去了,可是最终忘了静态文件了,被六星的改了我的css和js,,心累。。。
也出现了很多非预期,基本是我盯着服务器日志,一发现非预期就停了服务去修改。。写了几次自动化脚本。。反而带来了更多问题。。。
还有因为flask没有gzip模块,所以返回头里还要把gzip这个给去了。。要不然浏览器打不开网页。
还有一个最烦的错误了,至今没解决ConnectionError: ('Connection aborted.', error(104, 'Connection reset by peer'))
我分析应该是阿里云的锅,当爆这个错误时,我会收一个RST包,也就是在TCP三次握手之后,HTTP请求包发送之后,服务器返回了一个TCP的RST包,所以socket端口。。报错。。GG
服务器搭建(centos):
1 | yum install libxslt-devel.x86_64 |
ban ip小记
1 | 要封停一个IP,使用下面这条命令: |
HCTF之Black-Eat-Black总结