HTB - DevOops
DevOops is allegedly more difficult than OSCP but good practice; i actually found it quite easy. Probably because the vulnerabilities to exploit are pointed out.
An nmap scan reveals Gunicorn to be listening on port 5000- this is already a hint at the second attack required for the user flag as this was the same type of server I had to target for root access to Symfonos 4. Basic directory brute force further reveals the presence of three files- upload, the root of the server (index.html) and feed.
Index hints that the server uses Python at the back-end: apparently the root is feed.py while feed simply loads a png image and upload reveals a simple upload file form with reference to XML elements.
With so little to explore, it was quickly obvious that the upload form is probably vulnerable to some form of attack. I started by uploading txt and png files to observe the results- the page is simply reloaded.
This is when I thought to try uploading an XML file to the server- particularly with the hint towards what XML elements to use. 10 minutes research later and I’d put together a simple test.xml file.
I didn’t immediately jump to trying the above file: I firstly confirmed this was a vulnerability by trying to view /etc/passwd which was returned in the content element upon upload of the file.
After this, I spent half an hour or so seeing if RCE was possible through external entity attack; while it could have been if PHP was in use, it isn’t obviously so in the case of Python. This is when I remembered feed.py.
Feed.py revealed the insecure use of pickle on user supplied POST data to /newpost. After facing similar with JSON pickles in the past, I was aware that RCE was possible through this vulnerability and began working towards a reverse shell.
I learned here that things should always be tested locally first before testing them remotely: I was fiddling around with the reverse shell for an hour or two and constantly receiving error 500s. When I tried ti loally and it worked, i knew it was likely that there was something else wrong with my payload.
After 10-20 minutes, I discovered that adding the Content-Type header and setting it to text/html resulted in successful delivery of the payload (I confirmed this with a simple ping at first.)
Now I just needed to get a working payload- netcat was on the victim but a nc reverse shell resulted in immediate disconnection meaning the process was being terminated for some reason on their end. After some trial and error, I uncovered the following working payload:
I created this script from a few I found on Google. The pickle vulnerability arises form the manner in which pickle deserializes data (translating a byte stream to an object in the case of Python, an object being a list or dictionary etc.)
Objects with pickle are serialized using dumps or dump while they are deserialized using load/loads.
To achieve RCE through pickle, however, we must use the __reduce__function: it requires a callable object and an optional tuple of arguments for the called object, thus providing this to the Pickle process will executable the mentioned callable object along with the provided arguments.
The above revere shell succeeded and I had a foothold on the system as Roosa. I could have probably read the user flag back in the external entity attack; I thought I’d save it for when I had achieved RCE.
The root flag is very easy- simple enumeration of Roosa’s home directory reveals a GitHub project called ‘blogfeed’ and the presence of an RSA private key used for the project’s integration. I had my suspicions this key may be relevant and thus saved it for further use later.
Further basic enumeraton (specifically of .bash_history) shows us that Roosa screwed up at one point and accidentally submitted a relevant private key to the GitHub project. Although not an expert, I use GitHub myself and thus am aware that previous commits can be viewed.
Some research showed that it is possible to view patches (I simply refer to it as changes but hey ho) to a GitHub repo via the git log -p command. Executing this reveals the original key submitted to the repo.
From here I discovered that an RSA private key can be used in place of a password for SSH access... Perhaps we have root’s private key here? I tried this with ssh -i old-key [email protected] and sure enough we have root access.
I enjoyed this machine but I don’t feel it should be of medium difficulty- it actually took me longer on the user flag.
Also reminded myself of the importance of trying exploit payloads locally first if doable to discover the source of an error when delivering the exploit remotely.












