-
Notifications
You must be signed in to change notification settings - Fork 1
/
question3.tex
220 lines (192 loc) · 10.9 KB
/
question3.tex
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
\chapter{Question 3 - Application Code Assessment}
\section{Preparation}
Not much preparation was required for this part of the competition, as the
members of the team were already quite confident in analysing and debugging
application code. Research was undertaken into common problems that can lead to
code being vulnerable to various attacks - for example, buffer overflows that
can allow an attacker to inject arbitrary executable code into an application.
\section{Given Information}
Question 3 centred around an imaginary protocol called VSTP, for the Very
Secure Transfer Protocol. The protocol was implemented in the Python
programming language, and used the gnupg library for public key cryptography
to establish a secure channel to transfer a 256 bit session key, which was then
used to encrypt the rest of the session with AES in cipher feedback mode.
The program then presented a basic command line interface which allowed a user
to transfer files, remove files from the server, list directories, etc.
There was a server running VSTP: 172.16.1.20 port 5678
\\\\
All teams were given the file: vstp-package.zip
It contained the VSTP package, which comprised of the following:
\\- VSTP RFC
\\- Server and Client - Python source code
\\- The server public key
\\- Test client private / public keys (Key password is "password")
\\- Binary Debian package
\\- Installation script and README (please read before use)
\\\\
We were also given an unprivileged login to the server (VSTP):\\
\textbf{Username:} testclient
\\
\textbf{Password:} !321Password
\\\\
There was a server running Snort IDS: 172.16.1.107
\\\\
We were also given an unprivileged login to the server (SSH):\\
\textbf{Username:} test
\\
\textbf{Password:} Password123
\section{Question 3.1}
\textbf{There is a command injection vulnerability in the VSTP server code
(vstp\_server.py). Review the code and exploit the vulnerability to retrieve the
flag from the ".garbage." file}
\subsection{Approach}
An analysis of the code quickly revealed that there was a vulnerability in the
move file (mv) command - when the server received the command from the user,
it used the os.system() command to execute the mv executable on the server,
passing in the paths entered by the user with little sanitisation. This had
two implications - firstly, that the user could use the function to access
files outside the directories that the server was meant to restrict the
program to, and secondly, the statement could be terminated using the
semicolon character and arbitrary commands run on the server.
The flag was a file called '.garbage' located somewhere on the system. To find
the file, the find command was used. There was a problem trying to use this
though - the little sanitisation that was done on the path meant that any
command containing forward slashes would not work. This was worked around
by using the VSTP protocol's built in functionality to upload a script file,
which used the find command to locate the flag file and output the output of
the command to a file so it could be read back:
\\
\texttt{find / -name ".garbage" > find.out}
The command injection vulnerability was exploited to make the script
executable, and then exploited again to run it. This was done by issuing
the following commands:
\\
\texttt{push find.sh ~/vstp/find.sh}
\\
\texttt{mv tmp .tmp; chmod +x find.sh}
\\
\texttt{mv .tmp tmp; sh find.sh}
\\
\texttt{get find.out}
(The VSTP push command uploaded a file from the local side to the server, and
the get command downloaded files from the server.)
Running this script revealed that the file had the path
/home/vstp/.workspace/.garbage on the server. The file was copied into the
server root using a script:
\\
\texttt{cp /home/vstp/.workspace/.garbage /home/vstp/serverroot/}
This was executed the same way as the previous script, and then the flag file
was able to be retrieved with the \texttt{get} command as before.
\section{Question 3.1.1}
\textbf{Explain how the command injection vulnerability can be mitigated}
\subsection{Approach}
The mitigation for the command injection is quite simple. The most important
mitigation is to not use the system move command, and instead to use the
built-in Python filesystem commands to move the file. This would completely
remove the ability for commands to be injected using the command.
Just doing this would still leave the command able to access files outside the
serverroot directory - the paths should be checked that they are descendants
of this directory before the move is performed.
Further security can be added by having the process enter into a
\textit{chroot jail} before it accepts any connections. Using the chroot command
allows the operating system to make it appear to the application that a
particular directory is the root directory of the filesystem. Making the
serverroot directory appear as the filesystem root would make it impossible for
the program to be able to access files outside this directory even without
sanitising the paths properly.
\section{Question 3.2}
\textbf{Located with the previous flag is a PCAP file containing a VSTP session.
Exploit the encryption vulnerability in the server code to decrypt the session,
extract the file transferred and retrieve the flag}
\subsection{Approach}
At first glance, the VSTP protocol seems quite secure, as it is using a 256
bit key, which is too large to brute force and will not be able to be cracked
until a cryptographic weakness on AES is found. As AES is currently one of the
most commonly used ciphers today, it is out of the scope of the competition to
find such a weakness in it.
The vulnerability instead concerned the way the session key was generated. If
the key had been properly random, there would have been no way to crack it. But
the code that generated the key was very badly designed - the first 80 bits of
the key was hardcoded to always be the string "VSTPSERVER", then the next 64
were the date (in ASCII characters, formatted as YYYYMMDD), followed by the IP
address of the client in ASCII with the dot characters removed (32 to 96 bits,
depending on how long the IP was), then a two digit random number between 10
and 74, and the rest with actually random data (produced from the urandom
function).
What this unusual key generation method produced was a key with very little
entropy. The client IP and date were able to be gathered from the network
capture, so straight up the first 216 bits were known. This meant that
only 40 bits needed to be brute forced, which was easily achievable. The
fact that 16 of those bits were known to be an ASCII number between 10
and 40 reduces the entropy in the key by 10 bits to only 30 bits.
A known plaintext was required to be able to run the brute force, and this
was easily found in the network packet capture. Since the packets were not
padded at all, the message length was the length of the unencrypted message
plus the 16 bit initialisation vector. This meant it was very easy to tell
which messages were which because some were unique fixed sizes. The 'exit'
command was used, as it was very obvious which packet contained that message
given that it was the correct length and the server closed the connection
immediately after receiving it.
A script was written in Python to brute-force the key. The Python language
was chosen because it was the easiest way to implement it - although using a
compiled language like C would have made the running time of the program far
shorter, it would have been much more difficult to write. With Python, it was
just a matter of writing the key generation algorithm, and then calling the
VSTP code's AES decryption methods. Using C would have required
re-implementing those parts. The listing for the brute-forcer is included
below.
After the key had been found, the messages could be decrypted. There were
messages in the capture that fitted the size of a file transfer, so the
previous message had to be the command to initiate the transfer. This
assumption proved to be correct, and was decrypted to 'get flag.pdf'.
The subsequent packets (there were many of them) were copied out of the file
as hexadecimal strings, and reconstructed in a text editor. This text was then
taken into Python and decoded using the functions from the VSTP code and the
key found earlier. This produced a PDF file, which contained an image containing
the text of the flag - 'ArmsHungerGiftQuick149'.
The code written to brute force the key was as follows:
\lstinputlisting[style=python]{code/bruteforce.py}
\subsection{Retrospective Approach}
If more care had been taken in understanding the source code, some time could
have been saved - initially, it was thought that the server used its own IP
in the session key, but it actually used the client's address. Had this been
realised earlier, several runs of the brute force script could have been
prevented.
If there had been more time, it may have been more efficient to write a
script to take the PCAP file and reconstruct the data for the PDF file
instead of copying it out of Wireshark manually packet by packet. Although
the time taken writing such a script could easily have taken longer than
doing it manually.
\section{Question 3.2.1}
\textbf{Explain how this cryptographic weakness can be mitigated}
\subsection{Approach}
The way to mitigate this vulnerability is simply to use the urandom function
to generate the entire key, and not hardcoding any part of it. If the key had
been completely random, it would not have been able to be brute-forced.
\section{Question 3.3}
\textbf{There is a buffer overflow vulnerability in the Snort VSTP Preprocessor
code. Review the code and exploit the vulnerability to retrieve the flag from
the snort home directory}
\subsection{Approach}
It was very easy to find the buffer overflow in the C code that was provided.
It was the result of a strcpy call in a logging function. When a block that
looked like a GPG header was detected by the IDS, it would log the block,
temporarily copying it into a 799 byte buffer. If the message was malformed
and longer than this size, it would overflow the bounds of the buffer.
It was quite simple to exploit this at a simple level, to just crash the
process. This proved that it was definitely overflowing, and that arbirary
code would be able to be injected. None of the members on the team were
able to exploit the vulnerability though, as although research had been done
into how to detect and mitigate buffer overflows had been done, it was not
known how the shellcode injected into the application was designed.
\subsection{Retrospective Approach}
Had some more research and practice exploiting buffer overflows been done, the
team may have been able to formulate a payload that could be injected into
the application.
\section{Question 3.3.1}
\textbf{How could this vulnerability be mitigated?}
\subsection{Approach}
The mitigation of the buffer overflow is simply to make sure that the length
of the buffer being copied is not larger than the buffer it's going in to.
This is simply a matter of using the strncpy command instead of strcpy, and
passing in a length that is capped to the size of the destination buffer.