Skip to content

Commit

Permalink
Restructured project, better support for sessions and console, new Do…
Browse files Browse the repository at this point in the history
…cker (#7)

- Added GitHub workflows for publishing MSF docker images and
snek-sploit package
- Added MSF Docker image that is running RPC by default (with DB
support)
- Reworked README and updated Compose config to work with the new image
- Updated Python dependencies
- Removed groups since the MSF RPC doesn't provide that much
functionality, and currently, it will fit better into rpc
- `Client` -> `MetasploitClient`
- Updated imports, primarily root (`from snek-sploit import ...`)
- Renamed RPC groups for better readability (`Console` -> `Consoles`)
- Added `Console` class with some basic functionality (read, write,
execute, gather_output)
- Fixed some endpoints' parsing
- Added listing for sessions and their respective classes with some
basic functionality (read, write, execute, gather_output)
- Custom StrEnum since the official one has been supported since 3.11
  • Loading branch information
SadParad1se authored Apr 12, 2024
1 parent e3efbb6 commit 275249f
Show file tree
Hide file tree
Showing 36 changed files with 801 additions and 449 deletions.
73 changes: 73 additions & 0 deletions .github/workflows/msf-docker-images.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: CI
on:
schedule:
- cron: '0 5 1 * *'
release:
types:
- published
jobs:
push_metasploit_images_to_registry:
environment: production
name: Push Metasploit Docker images to Docker Hub
runs-on: ubuntu-latest
steps:
- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}

- name: Check out the Metasploit Framework repo
uses: actions/checkout@v4
with:
repository: rapid7/metasploit-framework
path: metasploit-framework

- name: Switch to the latest MSF tag
id: metasploit_setup
run: |
cd metasploit-framework
git fetch --tags
latest_tag=$(git describe --tags $(git rev-list --tags --max-count=1))
latest_minor_tag=${latest_tag%.*}
latest_major_tag=${latest_minor_tag%.*}
echo "latest_tag=$latest_tag" >> $GITHUB_OUTPUT
echo "latest_minor_tag=$latest_minor_tag" >> $GITHUB_OUTPUT
echo "latest_major_tag=$latest_major_tag" >> $GITHUB_OUTPUT
git checkout $latest_tag
- name: Build and push Docker image for Metasploit Framework
uses: docker/build-push-action@v5
with:
context: ./metasploit-framework
push: true
platforms: linux/amd64,linux/arm64
tags: |
sadparad1se/metasploit-framework:${{ steps.metasploit_setup.outputs.latest_tag }}
sadparad1se/metasploit-framework:${{ steps.metasploit_setup.outputs.latest_minor_tag }}
sadparad1se/metasploit-framework:${{ steps.metasploit_setup.outputs.latest_major_tag }}
sadparad1se/metasploit-framework:latest
labels: |
msf-version=${{ steps.metasploit_setup.outputs.latest_tag }}
snek-sploit-commit=$GITHUB_SHA
- name: Check out the current repo
uses: actions/checkout@v4

- name: Build and push Docker image for MSF running RPC
uses: docker/build-push-action@v5
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: |
sadparad1se/metasploit-framework:rpc-${{ steps.metasploit_setup.outputs.latest_tag }}
sadparad1se/metasploit-framework:rpc-${{ steps.metasploit_setup.outputs.latest_minor_tag }}
sadparad1se/metasploit-framework:rpc-${{ steps.metasploit_setup.outputs.latest_major_tag }}
sadparad1se/metasploit-framework:rpc
labels: |
msf-version=${{ steps.metasploit_setup.outputs.latest_tag }}
snek-sploit-commit=$GITHUB_SHA
18 changes: 18 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: CI
on:
release:
types:
- published
jobs:
upload_package_to_pypi:
environment: production
name: Build and upload Python package to PyPI
runs-on: ubuntu-latest
steps:
- name: Check out the current repo
uses: actions/checkout@v4

- name: Build and publish to pypi
uses: JRubics/[email protected]
with:
pypi_token: ${{ secrets.PYPI_TOKEN }}
19 changes: 19 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM sadparad1se/metasploit-framework:latest

ENV METASPLOIT_RPC_HOST="127.0.0.1"
ENV METASPLOIT_RPC_PORT="55553"
ENV METASPLOIT_RPC_SSL="true"
ENV METASPLOIT_RPC_USERNAME="msf"
ENV METASPLOIT_RPC_PASSWORD="root"
ENV METASPLOIT_DB_HOST="127.0.0.1"
ENV METASPLOIT_DB_PORT="5432"
ENV METASPLOIT_DB_NAME="msf"
ENV METASPLOIT_DB_USERNAME="msf"
ENV METASPLOIT_DB_PASSWORD="msf"
ENV METASPLOIT_DB_PREPARED_STATEMENTS="true"
ENV METASPLOIT_DB_ADVISORY_LOCKS="true"

COPY --chown=root:metasploit --chmod=664 docker/database.yml config/database.yml
COPY --chown=root:metasploit docker/msfconsole.rc docker/msfconsole.rc

CMD ["./msfconsole", "-r", "docker/msfconsole.rc"]
56 changes: 32 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,57 @@ Python typed RPC client for Metasploit Framework.

![](logo.png)

## Installation

```shell
pip install snek-sploit
```

## Usage

```python
from snek_sploit import Client
from snek_sploit import MetasploitClient


if __name__ == '__main__':
client = Client("msf", "root")
client = MetasploitClient("msf", "root")
print(client.core.rpc.version())

```

## Installation

```shell
pip install snek-sploit
```

## Starting MSF RPC server
In console
In Metasploit console:
```shell
load msgrpc ServerHost=127.0.0.1 ServerPort=55553 User=msf Pass='root' SSL=true
```

In the background
In shell:
```shell
msfrpcd -U msf -P root
```

More information can be found in the [MSF official documentation](https://docs.rapid7.com/metasploit/rpc-api/).

### Using the MSF's certificate
Certificate is by default taken from `/root/.msf4/msf-ws-cert.pem` (use the `-c` flag to choose a different location). If it's not, generate it as mentioned [here](https://github.com/rapid7/metasploit-framework/issues/15569#issuecomment-901158008).

## Running MSF with RPC using Docker Compose
Make sure you've installed [Docker Compose](https://docs.docker.com/compose/install/).
With [Docker](https://docs.docker.com/engine/install/):
```shell
docker run --tty --network host --detach sadparad1se/metasploit-framework:rpc
```

In case you don't want to set up MSF RPC on your own, here is a convenient Compose config with MSF RPC and database:
With [Docker Compose](https://docs.docker.com/compose/install/):
```shell
git clone https://github.com/SadParad1se/snek-sploit.git
cd snek-sploit
docker compose up -d
```

[Link to the MSF image documentation](https://cryton.gitlab-pages.ics.muni.cz/cryton-documentation/latest/docker-settings/#metasploit-framework).
You can find more information in the [Metasploit Framework documentation](https://docs.rapid7.com/metasploit/rpc-api/).

## TODO list
- Typing and parameter support for the DB RPC class
- async vs sync version?
- Add custom exceptions
- Wrapper classes for easier [workflows](https://docs.metasploit.com/docs/using-metasploit/advanced/RPC/how-to-use-metasploit-messagepack-rpc.html#example-workflows) (session, console, etc.)
### Using the MSF RPC certificate
MSF RPC loads the SSL certificate by default from `/root/.msf4/msf-ws-cert.pem` (use the `-c` flag to choose a different location). If not, generate it as mentioned [here](https://github.com/rapid7/metasploit-framework/issues/15569#issuecomment-901158008).

To use it in the client, save it locally and pass the path:
```python
from snek_sploit import MetasploitClient


MetasploitClient("msf", "root", certificate="/path/to/cert.pem")

```
24 changes: 9 additions & 15 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,37 +1,31 @@
version: '3.9'
services:
metasploit:
restart: always
image: registry.gitlab.ics.muni.cz:443/cryton/configurations/metasploit-framework:0
image: sadparad1se/metasploit-framework:rpc
container_name: metasploit
network_mode: host
environment:
MSF_RPC_HOST: 127.0.0.1
MSF_RPC_PORT: 55553
MSF_RPC_SSL: true
MSF_RPC_USERNAME: msf
MSF_RPC_PASSWORD: root
MSF_DB_HOST: 127.0.0.1
MSF_DB_PORT: 5432
MSF_DB_NAME: msf
MSF_DB_USERNAME: msf
MSF_DB_PASSWORD: msf
METASPLOIT_DB_HOST: 127.0.0.1
METASPLOIT_DB_PORT: 5432
METASPLOIT_DB_NAME: msf
METASPLOIT_DB_USERNAME: msf
METASPLOIT_DB_PASSWORD: msf
tty: true
depends_on:
metasploit_db:
condition: service_healthy

metasploit_db:
restart: always
image: postgres:15
image: postgres:16
container_name: metasploit-db
environment:
POSTGRES_PASSWORD: msf
POSTGRES_USER: msf
POSTGRES_DB: msf
POSTGRES_HOST_AUTH_METHOD: md5
volumes:
- db_data:/var/lib/postgresql/data
- msf_db_data:/var/lib/postgresql/data
healthcheck:
test: /usr/bin/pg_isready -U $$POSTGRES_USER
interval: 5s
Expand All @@ -41,4 +35,4 @@ services:
- "127.0.0.1:5432:5432"

volumes:
db_data:
msf_db_data:
131 changes: 131 additions & 0 deletions docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
## Disclaimer
This is not the official Metasploit Framework Docker image. It can be found [here](https://hub.docker.com/r/metasploitframework/metasploit-framework).

[Copyright notice](https://github.com/rapid7/metasploit-framework/blob/master/COPYING).

## Why this exists
The Metasploit Framework image is updated usually once every three months and doesn't provide environment variables for DB or RPC setup.

## Quick reference

- The `sadparad1se/metasploit-framework:latest` image is built from the [official MSF repository](https://github.com/rapid7/metasploit-framework), and only the labels are updated
- The `sadparad1se/metasploit-framework:rpc` image automatically tries to connect to the database and starts the RPC server
- The repository for this image can be found [here](https://github.com/SadParad1se/snek-sploit)

## Usage
Always run the images with the `--tty` option. Otherwise, the MSF console will keep restarting.

### Run the Metasploit RPC server using Docker
```shell
docker run --tty --network host --detach sadparad1se/metasploit-framework:rpc
```

### Run the Metasploit RPC server and database using Docker Compose
```yaml
services:
metasploit:
restart: always
image: sadparad1se/metasploit-framework:rpc
container_name: metasploit
network_mode: host
environment:
METASPLOIT_DB_HOST: 127.0.0.1
METASPLOIT_DB_PORT: 5432
METASPLOIT_DB_NAME: msf
METASPLOIT_DB_USERNAME: msf
METASPLOIT_DB_PASSWORD: msf
tty: true
depends_on:
metasploit_db:
condition: service_healthy

metasploit_db:
restart: always
image: postgres:16
container_name: metasploit-db
environment:
POSTGRES_PASSWORD: msf
POSTGRES_USER: msf
POSTGRES_DB: msf
POSTGRES_HOST_AUTH_METHOD: md5
volumes:
- msf_db_data:/var/lib/postgresql/data
healthcheck:
test: /usr/bin/pg_isready -U $$POSTGRES_USER
interval: 5s
timeout: 10s
retries: 5
ports:
- "127.0.0.1:5432:5432"

volumes:
msf_db_data:

```

## Environment variables
These variables are only to be used with the `rpc*` tag.

### `METASPLOIT_RPC_HOST`
Host to serve the RPC server at.

Default: `127.0.0.1`

### `METASPLOIT_RPC_PORT`
Port to serve the RPC server at.

Default: `55553`

### `METASPLOIT_RPC_SSL`
Whether to use SSL for communication with the RPC server.

Default: `true`

### `METASPLOIT_RPC_USERNAME`
Username used for RPC.

Default: `msf`

### `METASPLOIT_RPC_PASSWORD`
Password used for RPC.

Default: `root`

### `METASPLOIT_DB_HOST`
Database host.

Default: `127.0.0.1`

### `METASPLOIT_DB_PORT`
Database port.

Default: `5432`

### `METASPLOIT_DB_NAME`
Name of the database to connect to.

Default: `msf`

### `METASPLOIT_DB_USERNAME`
Username for the database user.

Default: `msf`

### `METASPLOIT_DB_PASSWORD`
Password for the database user.

Default: `msf`

### `METASPLOIT_DB_PREPARED_STATEMENTS`
Whether to use prepared statements.

Default: `true`

Set to `false` if using an external pooler like PgBouncer (before 1.21.0).

### `METASPLOIT_DB_ADVISORY_LOCKS`
Whether to use advisory locks.

Default: `true`

Set to `false` if using an external pooler like PgBouncer (before 1.21.0).
13 changes: 13 additions & 0 deletions docker/database.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
development: &pgsql
adapter: "postgresql"
host: <%= ENV['METASPLOIT_DB_HOST'] %>
port: <%= ENV['METASPLOIT_DB_PORT'] %>
database: <%= ENV['METASPLOIT_DB_NAME'] %>
username: <%= ENV['METASPLOIT_DB_USERNAME'] %>
password: <%= ENV['METASPLOIT_DB_PASSWORD'] %>
reconnect: true
prepared_statements: <%= ENV['METASPLOIT_DB_PREPARED_STATEMENTS'] %>
advisory_locks: <%= ENV['METASPLOIT_DB_ADVISORY_LOCKS'] %>

production: &production
<<: *pgsql
Loading

0 comments on commit 275249f

Please sign in to comment.