Rating:

## TAMUctf Spring 2019 "Bird Box Challenge"
478 pts.\
Written by Alejandro N. Rivera\
University of Florida: Student InfoSec Team (UFSIT)

Description given by challenge:
```
http://web2.tamuctf.com
We've got Aggies, Trucks, and Eggs!

Difficulty: hard
```

The challenge page has an text input box and button that allow you to submit a search query. Typing in `aggies`, `trucks`, or `eggs` yields a valid search result page.

The name of the challenge seemed to insinuate that solving it involved using blind SQL Injection. I used the valid search queries to try to gain information about the structure of the underlying SQL statement (e.g., single quotes vs. double quotes, statement terminators, comment tags, etc.)

After a few tries, entering `aggies'; #` returned the valid search result page for `aggies`. This confirms my guess that Blind SQLi is the way to go, and means I now know the underlying SQL statement uses single quotes. Also, the semicolon lets me know I'm at the end of the SQL statement and that `#` is used for comments.

Naturally the next thing to try was a basic statement that always evaluates to true:\
`aggies' OR '1=1'; #`\
This yielded a search result page that said "Nice try, nothing to see here."

Hmm...how about a statement that always evaluates to false?:\
`aggies' AND '0=1'; #`\
No dice. The query didn't return any results, just a page that says "Our search isn't THAT good.."

Maybe I can `UNION` my search query with something and see what that returns?:\
`aggies' UNION SELECT 1; #`\
This returns a result page that says "Nope. Not gonna let you use that command."

Hmm...the two commands I introduced in that statement are `UNION` and `SELECT`. Is the server blocking one or both of these commands?

I try the following two statements for the sake of testing the server-side input filtering (even though these are invalid SQL statements):\
`aggies' SELECT 1; #`\
This returns the standard "Our search isn't THAT good..." no results page as expected.\
`aggies' UNION 1; #`\
But this returns "Nope. Not gonna let you use that command."!\
Cool. Now I know the keyword being filtered is `UNION`, but this severely limits what I can do to gain more information about the database.

After playing around with the input for some time, a thought occurred to me: what would happen if I put the `UNION` keyword right up against the single quote? Like so:\
`aggies'UNION SELECT 1; #`\
Aha! This returns the "Nice try, nothing to see here." page. From this I gather that the server was filtering the word `UNION` out of the search query, but did nothing this time since it saw `aggies'UNION` all as one word. The SQL parser, however, still differentiates the string literal from the `UNION` keyword even without the space.

Now my next thought was to get rid of `aggies` in the statement like so:\
`'UNION SELECT 1; #`\
Nice! This yield a page that just says "1". The vulnerability was successfully exploited; now to use it to get more useful data.

Let's try to get the SQL version number:\
`'UNION SELECT @@VERSION #`\
This yields "5.7.25-0ubuntu0.18.04.2", maybe it'll be useful later.

Next I constructed a series of statements that got me all the schema, table, and column names of the database (that weren't part of the standard SQL "INFORMATION_SCHEMA" database):
```
'UNION ALL SELECT GROUP_CONCAT(table_schema) FROM information_schema.tables WHERE table_schema != 'information_schema' #

'UNION ALL SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema != 'information_schema' #

'UNION ALL SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_schema != 'information_schema' #
```
These yield some names of interest for the schema ("SqliDB"), table ("Search"), and column ("items").

Now that I know the schema, table, and column names of interest, let's see what I can gather from the table by printing all the items:\
`'UNION ALL SELECT GROUP_CONCAT(items) FROM Search #`\
This returns "Eggs,Trucks,Aggies". Well we already knew these were there from the start, so this doesn't yield any new information.

At this point it was clear the flag was hidden elsewhere in the database. After searching and poking around for a while, I decided to try using a command found in the SQL docs to print the name of the privileged user from the "INFORMATION_SCHEMA":\
`'UNION ALL SELECT grantee FROM information_schema.user_privileges #`\
And there it is! This command returned the flag.