So last week UCSB organized another iCTF, crazy as always. This time, they reused 42 services from older iCTFs. Some were modified so that copy-pasting exploits from write-ups didn't work, some were not. Some others were old enough that there just are no write-ups on the internet. A lot of write-ups were apparently taken down during the competition, or (by UCSB) right before it. The Internet Archive saved the day here.
Since there is no point in repeating the old write-ups I used to exploit some of the newer services this blog post will focus on ccauthd which was completely unknown to the internet at the day of the competition and still doesn't seem to have a write-up. Although I just now found what seems to be the source code. It looked a bit weirder in IDA, but not too much.
The service has a text interface usable over telnet or netcat. It allows registering a string, which stores that string and returns a secret auth token that can be used later to retrieve the stored string. This is implemented by creating a file named like the auth token that contains the registered string.
Like in earlier years, UCSB ran uploaded exploits on their own hardware. Other team's vulnboxes were not reachable directly. In the case of ccauthd, the exploit script got the first 14 characters of the auth token and was supposed to return the string stored under the full 31 character token.
The first issue we found in the service was related to the generation of auth
tokens during registration, which is done using rand(3)
. At program startup,
the random number generator is initialized by the current time: srand(time(0))
.
At that time the game server had stored less than 100 flags and the game had run
only for a few hours. So this was clearly in brute-force territory. So I wrote a
simple script that for every second since the CTF had started (where the service
could potentially been started) generated 100 possible auth tokens until one
matched the 14 given characters. This worked great locally and I'm sure it'd
have worked great against 90% of the other teams, but sadly it never got that
far because exploit scripts are first tested against an unpatched vulnbox by
UCSB which was apparently started way earlier, making brute-force unfeasible.
On our own machine, we 'fixed' this by loading a library with LD_PRELOAD
that
modified rand(3)
to get its data from /dev/urandom
.
After this let-down we went back to the service, looking for the intended
vulnerability. Kind of embarrassingly, we only found it by looking at the
traffic of other teams exploiting us. While the authentication command appears
to check the given auth token is all alpha numeric and a file by the same name
really exists, it actually does so only for the first 32 characters. It then used
all input to construct a shell command for system(3)
that retrieved the flag.
We could basically just copy the exploit that was used against us, in order to
fix it I modified the loop checking that the auth token is alpha-numeric to
check the whole length of the buffer. This meant an attacker had a chance
to overflow the id
array, but only into a buffer next to it that already
contained attacker-controlled input.
Later on, we tried to combine both exploits (the second one to get past the correctness check, and the first one to get tht flags), but at that point the CTF already ran for over 6 hours and our server had generated a bit less than 400 flags, which again made brute-force impossible in the few seconds the exploit script had until it was killed.