1 min read

Hack.lu 2019 Write-ups

by Vihan Bhargava
  • CTF

Write-ups for the SECCON 2019 capture the flag qualification round.

Hack.lu 2019 was a medium-difficulty CTF. I got a few of the challenges but again couldn’t dedicate much time 😫.

#Nucular Power Plant

In essence, this was a typical easy SQLi but the quirk was it’s through the socket.

Web page looks fine...
Web page looks fine...

Looking at the website, there is no clear initial vulnerability. The source also looks clean except it’s using a Socket to communicate with the server. Given no unusual cookies or headers this looks like it’ll be our attack vector.

Socket data in chrome inspector
Socket data in chrome inspector

Here we can see how the server returns the data given a name of a powerplant. Maybe there’s more to the query? Let’s try to send our own messages and see what responses we get…

Connecting in and hooking to a global
Connecting in and hooking to a global

For ease, I’ll map the ws to window.ws for easy use in the debugger. Now sending some garbage:

ws.send(`"#$`)

I get back an error message from the server:

Error: SqliteFailure(Error { code: Unknown, extended_code: 1 }, Some("near \"#$\": syntax error"))

From this two things can be deduced:

  1. SQLite injection vulnerability is what we’re targeting
  2. Server is using rust

I doubt the second will be useful but let’s see where this goes. The classic ' doesn’t work for injection, however " does…

" OR 1=1--

Sending this payload does in fact return a valid result. Now to try a typical query to obtain the schema of the DB:

" UNION ALL SELECT sql FROM sqlite_master WHERE type='table'--

… and this gives a column error. Assuming the columns are in the order of the response JSON, they can be filled in:

" UNION ALL SELECT sql,"",0,0,"",0 FROM sqlite_master WHERE type='table'--

and bam, we get the schema of the power plant…

Okay, now we're getting somewhere
Okay, now we're getting somewhere

This however, doesn’t have much useful info so using LIMIT  n+1  OFFSET  n\text{LIMIT}\;n+1\;\text{OFFSET}\;n, the next table can be identified:

CREATE TABLE secret (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
value TEXT NOT NULL
)

okay now this is pretty much jackpot. Querying the first one only yields the ☢️ nuclear launch codes but the next one is exactly what we want:

" UNION ALL SELECT value,"",0,0,"",0 FROM secret LIMIT 2 OFFSET 1--

and that’ll give us the flag: flag{sqli_as_a_socket}.