Web1:签到题
1、打开题目,源码直接显示在网页上。
2、发现构造0ver、0ver1、0ver2即可,下面就进行代码审计:
(1)首先构造 0ver,有以下三个条件:
① ereg("^[0-9]+$", $a) === FALSE)
,即要进行一次或多次 0-9 数字正则表达式匹配
② in_array($a,$white_list)
,即0ver 中要有 range(0,9)
③ strlen($a)>1
,即0ver 的长度要大于 1
一开始以为要考ereg()截断漏洞,其实是in_array()松散比较,即
1 | var_dump(in_array('b', array('a'=>true))); |
为什么是这样呢?
in_array('b', array('a'=>true))
实质上是'b'==true
这样的类型比较,b 是变量或者一个字符串string,和bool 类型比较,结果是true。
但是如果'b'===true
结果可能就不一样了,返回值:false,就是类型比较的问题。- 第二个例子,也就是本题的考点之一。
1
2var_dump('01'==1); 返回值:true
var_dump('01'===1); 返回值:false
因此构造: 0ver=01
(2)构造 0ver1 和 0ver2,有以下条件:
md5($c) === md5($b) && ($b !== $c)
所以要构造 md5 相同,真值不同的两个参数,但注意这里 md5 用===判断,所以不能利用md5 开头是 0e 的字符串来绕过,但可以利用数组绕过。
因此构造:0ver1[]=1&0ver2[]=2
3、最终构造的payload为:?0ver=01&0ver1[]=1&0ver2[]=2
,得到 flag。
Web2:SimpleUpload签到
1、只允许png/gif/jpg文件格式,查看源码,判断为前端验证,并且提示flag在当前目录的flag.php
2、上传后缀为png的一句话木马,BurpSuite抓包改后缀为php,拿到链接。
3、用菜刀链接木马,根据提示在flag.php中找到flag。
Web3:小型线上赌场
1、 这一题要求下注并猜测赚的钱,但是赔率没刷新或提交一次页面都会变化。
2、根据题目及后续的hint可知存在vim备份文件泄露,.index.swp
下载swp。
3、在kali下面对得到的index.swp文件进行恢复,进入文件的目录后vim -r index.swp
,得到源码。
4、进行代码审计
1 |
|
最后的判断逻辑为:猜测的数(guess)与money相等,且money的长度与invest的长度相等。
问题出现在intval()
函数上,关于此函数返回值如下:
也就是说当传入intval()
的参数足够大时,其返回值根据操作系统的不同,是固定的数值(32位:2147483647,64位:9223372036854775807),这一题也就是传入的invest的数足够大时,无论随机数是多少,经过intval()
函数处理过的money的值均是不变的。
这样思路也就很清楚了,只需将guess的值等于money的64位上限值,也就是9223372036854775807,invest的长度要等于money的长度(任意19位数字),即可得到flag。
Web4:SimpleSQLi
一道没有任何过滤的SQL注入题
(1)手工注入过程如下:
1 | 爆表名 |
1 | 爆字段名 |
1 | 爆字段 |
(2)sqlmap注入:
1 | python2 sqlmap.py -u "http://bxs.cumt.edu.cn:30007/test/index.php?id=1" -D security -T flagishere -C flag --dump |
Web5:真的简单。。
(1)也是一道SQL注入题,但是过滤了 union
、select
、or
、and
等关键词,可以通过双写绕过。
1 | payload: |
最终得到:
并没有直接爆出flag,看来不是一道简单的SQL注入题。
(2)打开admin_08163314/exec.php页面,是后台命令执行。
输入如下命令进行执行,即可获得flag:
1 | `echo$IFS"Y2F0IC9mbGFnXzMzMTQvZmxhZw=="|base64$IFS-d` |
(对命令执行的绕过方法还不太熟悉,题目不能复现了,等学习后再详细解释吧…)
Web6:SimpleSQLi2
(1)这还是一道SQL注入题,但是只会回显Welcome to CUMTCTF'2019~
和NoNoNo~
两个页面,因此可以判断为SQL盲注。
(2)过滤方式和上一题差不多,但测试发现只要构造的payload里有含有空格,均返回NoNoNo~
页面,所以判断空格被过滤了。
(3)关键词依旧可以通过双写绕过,空格可以通过/**/
绕过,通过下面判断出为数字型注入,构造的代码可以直接执行。
id | 返回页面 |
---|---|
id=1 | Welcome to CUMTCTF’2019~ |
id=1’ | NoNoNo~ |
id=1/**/anandd/**/1=1--+ | Welcome to CUMTCTF’2019~ |
id=1/**/anandd/**/1=2--+ | NoNoNo~ |
id=1’/**/anandd/**/1=1--+ | NoNoNo~ |
id=1’/**/anandd/**/1=2--+ | NoNoNo~ |
知道过滤方式之后,就可以写脚本来爆破:
1 | import requests |
最终获得flag如下:
Web7:文件管理系统
1、先扫目录,发现可以下载源码,进行代码审计。
2、查看upload.php代码,发现是如下白名单验证,无法上传绕过。
1 |
|
3.问题主要出现在rename.php里,代码如下:
1 |
|
第一个select
语句显示根据 $req['filename']
从数据库里查询到已存在的一行,再用第二个update
语句进行修改,这里的'oldname'='{$result['filename']}'
将从数据库里查出的$result['filename']
再一次入库,因此存在二次注入。
4、观察发现oldname
和newname
,有几个特点:
- 后缀相同,都是
$result[‘extension’]
oldname
的文件名来自数据库,newname
的文件名来自用户输入
虽然代码要求oldname
和newname
要求后缀相同,可以通过update型注入将extension
改为空,同时可修改filename
的值。
因此构造的文件名payload为:',extension='',filename='webshell.jpg.jpg
5、上传文件名为:',extension='',filename='webshell.jpg.jpg
的文件后,根据upload.php知:
1 | $path_parts["extension"] = ".jpg" |
6、下来才是真正的updata注入过程
进入到rename.php页面,进行如下操作,将文件名修改为由',extension='',filename='webshell.jpg
修改为webshell.jpg
(这里rename页面输入的文件名均是要求不含后缀的,在数据库里文件名和后缀是分两个字段进行存储的)
上述操作改名后:
1 | $req['oldname'] = "',extension='',filename='webshell.jpg" |
接下来执行:select * from 'file' where 'filename'='{$req['oldname']}'
因为filename
在上传后经过addslashes()
转义的,所以此条语句正常执行
但是在执行下条语句,也就是:
update 'file' set 'filename'='{$req['newname']}', 'oldname'='{$result['filename']}' where 'fid'={$result['fid']}
出现了注入,将构造的文件名插入这条语句得到实际执行的sql语句:
update 'file' set 'filename'='webshell.jpg', 'oldname'='',extension='',filename='webshell.jpg' where 'fid'={$result['fid']}
可以发现通过updata语句,修改了数据中的字段值,此时数据库中各字段:
filename = webshell.jpg
oldname = 空
extension = 空
这样思路就很清楚了:
- 虽然数据库中的
filename
通过注入改变了,但真实系统目录里的文件名为其实并没有变。
但是通过前面的注入,这条记录的extension
值为空,因此只要能够调用rename()
函数,就直接把输入的filename
里的后缀当成文件后缀。 - 执行
rename()
函数还有一个判断:if(file_exists($oldname))
,但实际上我们系统目录并没有webshell.jpg
这个文件,这样就需要再上传一个webshell.jpg
文件。
7、因此接下来就可以上传真正包含一句话木马的文件:webshell.jpg
,上传后:
1
2
3
4
5
6 $path_parts["extension"] = ".jpg"
$path_parts['filename'] = "webshell"
并在数据库中插入了新的一条记录:
filename字段的值为经过addslashes()转义的webshell
extension字段的值为.jpg
且系统目录下存在真实文件:webshell.jpg
接下来再次进入rename.php页面进行改名,这也是很关键的一步:
将webshell.jpg
改为webshell.php
,这样操作后:
因为注入后,数据库中存在filename
为webshell.jpg
的记录,因此可以绕过这条语句:
select * from 'file' where 'filename'='{$req['oldname']}'
然后再次通过updata语句:
update 'file' set 'filename'='{$req['newname']}', 'oldname'='{$result['filename']}' where 'fid'={$result['fid']}
将filename
的值从webshell.jpg
修改为webshell.php
,oldname
修改为原来filename
的值,其他不变,此时数据库中这条记录的字段值为:
filename = webshell.php
oldname = webshell.jpg
extension = 空
接下来,因为后缀extension为空,所以通过这两条语句赋值后:
1 | $oldname = ROOT.UPLOAD_DIR . $result["filename"].$result["extension"]; |
实际上得到:
$oldname = webshell.php
$newname = webshell.jpg
最后,在进行if(file_exists($oldname))
判断时,因为第二次上传到目录的文件就是webshell.jpg
,所以可以通过判断。
这样就可以执行rename($oldname, $newname)
,将目录下的包含木马的文件webshell.jpg
改名为webshell.php
,也就成功上传了php木马到后台。
8、既然已经成功上传了webshell,那么直接用菜刀链接,即可getshell,获得flag。