A fast and secure multi protocol honeypot that can mimic realistic devices running ssh
, telnet
, http
, https
or any other tcp
and udp
servers.
Using Docker (recommended):
docker build -t medusa .
docker run \
-v /path/to/services.d:/etc/medusa/services.d \
-v /path/to/records:/var/lib/medusa/records \
--network host \
medusa
Lastly, you can build from sources if you have Rust installed in your system (it requires openssl
and libpcap-dev
):
cargo build
You can use medusa
to create a (best-effort) clone of a device that's indexed on shodan.io.
In order to do this you'll need an API key:
export SHODAN_API_KEY=your_api_key_here
Then you can clone a host (38.18.235.213
in this example) with:
docker run -v $(pwd)/mikrotik:/mikrotik medusa \
--shodan-api-key $SHODAN_API_KEY \
--shodan-clone 38.18.235.213 \
--output /mikrotik
This will create the YAML service files inside the mikrotik
folder. This folder can then be used with:
docker run \
-v $(pwd)/mikrotik:/etc/medusa/services.d \
-v $(pwd)/records:/var/lib/medusa/records \
--network host \
medusa
First you need to create at least one service file. Let's begin by defining a simple SSH honeypot that accepts any combination of user and password:
mkdir -p /path/to/services.d/
touch /path/to/services.d/example-ssh.yml
Open /path/to/services.d/example-ssh.yml
with your favorite editor and paste these contents:
proto: ssh
address: '127.0.0.1:2222'
server_id: 'SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.10'
banner: 'Last login: Mon Sep 5 14:12:09 2022 from 127.0.0.1'
prompt: '# '
timeout: 15
commands:
- parser: '^exit(\s.+)?$'
handler: '@exit'
In some cases, custom SSH servers do not respect the RFC standard for server id termination characters \r\n
, but rather use only \n
. In this case it is possible to use the server_id_raw
directive and include custom terminators in the string, while of server_id
is used the default \r\n
will be used.
proto: ssh
address: '127.0.0.1:2222'
server_id_raw: "SSH-1.99-TECHNICOLOR_SW_2.0\n"
banner: 'Last login: Mon Sep 5 14:12:09 2022 from 127.0.0.1'
prompt: '# '
timeout: 15
commands:
- parser: '^exit(\s.+)?$'
handler: '@exit'
Now run:
medusa --services "/path/to/services.d/" --records "/path/to/output/records" --capture-device "<your network interface name>"
This will start a single honeypoint on port 2222 and all the resulting events will be saved as JSON files in the folder indicated by --records
. Additionally a pcap of the entire traffic will be saved as capture.pcap
.
The previous example won't do much if somebody tries to execute actual commands. It only captures the exit
command in order to terminate the session (via the @exit
special handler). Let's add another command, for instance to parse simple echo
inputs:
proto: ssh
address: '127.0.0.1:2222'
server_id: 'SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.10'
prompt: '# '
timeout: 15
commands:
- parser: '^exit(\s.+)?$'
handler: '@exit'
- parser: '^echo(\s"?([^"]*)"?)?$'
handler: '{$2}'
The parser
expression will now capture the echo
command and its argument (captured as $2
), that will be echoed back via the handler ({$2}
is replaced with the value of $2
).
In other cases, the handler can contain the entire output as a raw string, like for the case of an http
service honeypot:
proto: http
address: '127.0.0.1:8080'
commands:
- parser: '.*'
handler: "<html><body>hello world</body></html>"
Another useful handler is @docker
. As the name suggests it executes any shell command it receives as an argument inside a docker container, therefore we could create a "jailed" ssh
honeypot by doing:
proto: ssh
address: '127.0.0.1:2222'
server_id: 'SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.10'
prompt: '# '
timeout: 15
commands:
- parser: '^exit(\s.+)?$'
handler: '@exit'
- parser: '^(.+)$'
handler: '@docker jail {$1}'
You can create and start a jail
container with:
docker container create --name jail busybox tail -f /dev/null # feel free to pick any image
docker start jail
This will execute any command that the client is sending on the jail
container and it will transparently pass the output to the client.
Configuring a realistic docker container is beyond the purpose of this document, you can find useful images here.
SSH server emulation (with docker jail):
proto: ssh
address: '127.0.0.1:2222'
server_id: 'SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.10'
prompt: '# '
timeout: 15
commands:
- parser: '^exit(\s.+)?$'
handler: '@exit'
- parser: '^(.+)$'
handler: '@docker medusajail {$1}'
Telnet server emulation (with docker jail):
proto: telnet
address: '127.0.0.1:2323'
banner: 'TNAS v1.0'
login_prompt: 'TNAS login: '
password_prompt: 'Password: '
prompt: '[admin@TNAS ~]$ '
timeout: 15
commands:
- parser: '^exit(\s.+)?$'
handler: '@exit'
- parser: '^(.+)$'
handler: '@docker medusajail {$1}'
HTTP server emulation with custom headers:
proto: http
address: '127.0.0.1:8181'
headers:
- 'Content-Type: text/html; charset=UTF-8'
- 'X-Powered-By: TerraMaster'
- 'Server: TOS/1.16.1'
commands:
- parser: '.*'
handler: |
<!--user login-->
<!DOCTYPE HTML>
<html>
<head>
<title>TOS</title>
</head>
<div>
Hello World
</div>
</html>
HTTPS is also supported, you'll need to generate a new RSA key and certificate first:
openssl req -newkey rsa:2048 -nodes -keyout medusa-https.key -x509 -days 365 -out medusa-https.crt
Then just enable tls
in your http
service configuration:
proto: http
address: '127.0.0.1:8181'
tls: true
key: medusa-https.key
certificate: medusa-https.crt
headers:
- 'Content-Type: text/html; charset=UTF-8'
- 'X-Powered-By: TerraMaster'
- 'Server: TOS/1.16.1'
commands:
- parser: '.*'
handler: |
<!--user login-->
<!DOCTYPE HTML>
<html>
<head>
<title>TOS</title>
</head>
<div>
Hello World
</div>
</html>
Other TCP servers can be simulated by exposing a banner:
proto: tcp
address: '127.0.0.1:1723'
banner: |
Firmware: 1
Hostname: ASBN-BB-RT01
Vendor: MikroTik
And UDP servers as well:
proto: udp
address: '0.0.0.0:5353'
banner: |
dnsmasq-2.73
Recursion: enabled
Resolver name: X4200
Run medusa --help
for the complete list of options.
Medusa was made with โฅ by Simone Margaritelli and it's released under the GPL 3 license.