A fast and secure multi protocol honeypot.

Related tags

Cryptography medusa
Overview

Medusa

A fast and secure multi protocol honeypot that can mimic realistic devices running ssh, telnet, http, https or any other tcp and udp servers.

Work in progress.

Building

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

Depending on your services configuration this last command line might need additional parameters to open TCP and UDP ports.

You can build from sources if you have Rust installed in your system:

cargo build 

Shodan Host Clone

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

Usage

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'
prompt: '# '
key: '/tmp/example-ssh.key'
timeout: 15
commands:
  - parser: '^exit(\s.+)?$'
    handler: '@exit'

Now run:

medusa --services "/path/to/services.d/" --records "/path/to/output/records"

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.

Commands

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: '# '
key: '/tmp/example-ssh.key'
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>"

Docker Jail

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: '# '
key: '/tmp/example-ssh.key'
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.

Protocols

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: '# '
key: '/tmp/example-ssh.key'
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

License

Medusa was made with by Simone Margaritelli and it's released under the GPL 3 license.

You might also like...
A secure development tool box and fintech application made with Rust to be used for developing cryptocurrencies on the blockchain.

Crypto Fintech Tools for Rust (CFT) Dependencies Rust MacOS Homebrew # xcode cli tools xcode-select --install # install dependencies using Homebrew b

Secure your on-chain approvals and sleep with ease.
Secure your on-chain approvals and sleep with ease.

🇹🇷 Eth Global Istanbul 2023 Hackaton Project 🇹🇷 Table of Contents Table of Contents About The Project Built With Getting Started Installation Cont

Secure storage for cryptographic secrets in Rust

secrets secrets is a library to help Rust programmers safely held cryptographic secrets in memory. It is mostly an ergonomic wrapper around the memory

Use Touch ID / Secure Enclave for SSH Authentication!
Use Touch ID / Secure Enclave for SSH Authentication!

SeKey About SeKey is a SSH Agent that allow users to authenticate to UNIX/Linux SSH servers using the Secure Enclave How it Works? The Secure Enclave

Cross-platform Secure TUI Secret Locker
Cross-platform Secure TUI Secret Locker

SafeCloset keeps your secrets in password protected files. SafeCloset is designed to be convenient and avoid common weaknesses like external editing o

A Secure Capability-Based Runtime for JavaScript Based on Deno
A Secure Capability-Based Runtime for JavaScript Based on Deno

Secure Runtime secure-runtime, as the name implies, is a secure runtime for JavaScript, designed for the multi-tenant serverless environment. It is an

Simplified, secure privledge escalation

doit.rs A simplified privledge escalation tool. Attempting to combine the memory safety guarantees of Rust with a small, auditable codebase. I was rea

A secure file encryption utility, written in rust.

Dexios Dexios What is it? Building notes Checksums Performance Output file sizes Environment Variables Key Inputs Usage Examples To Do What is it? Dex

Monorepo of our ahead-of-time implementation of Secure ECMAScript

Ahead-of-time Secure EcmaScript The monorepo contains a set of packages that helps adopt SES in a pre-compiled way. Security Assumptions This project

Comments
  • Cannot specify LF at the end of SSH server_id

    Cannot specify LF at the end of SSH server_id

    This may be something I'm just doing wrong. I was playing with impersonating services, nothing specific, but I wanted it to look "real", so I grabbed some banners from /usr/share/nmap/nmap-service-probes. Setting SSH server_id to something expecting a \r\n ending works fine. However, a server_id ending in \n cannot be set:

    Working Example

    From the service probes file I can find this:

    match ssh m|^SSH-([\d.]+)-PSFTPd\. Secure FTP Server ready\r\n| p/PSFTPd/ i/protocol $1/ o/Windows/ cpe:/a:pleis:psftpd/ cpe:/o:microsoft:windows/a
    

    And set my server_id to this:

    SSH-2.3-PSFTPd. Secure FTP Server ready
    

    and Nmap correctly identifies the service as:

    PORT     STATE SERVICE REASON         VERSION
    2222/tcp open  ssh     syn-ack ttl 63 PSFTPd (protocol 2.3)
    Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
    

    Non-working example

    However, if I try something like this:

    match ssh m|^SSH-([\d.]+)-TECHNICOLOR_SW_([\d.]+)\n| p/Technicolor SA sshd/ v/$2/ i/protocol $1/ d/broadband router/
    

    And set my server_id to:

    SSH-1.99-TECHNICOLOR_SW_2.0
    

    I get back:

    1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
    SF-Port2222-TCP:V=7.91%I=7%D=8/29%Time=612B8DBD%P=x86_64-pc-linux-gnu%r(NU
    SF:LL,1D,"SSH-1\.99-TECHNICOLOR_SW_2\.0\r\n");
    

    As near as I can tell that should match except for the ending, I've tried numerous variations though. It seems the problem is Nmap wasn't expecting the carriage return preceding the line feed, e.g the "\r\n" on the last line that wasn't specified by the user.

    If I insert a new line between the end of the string (2.0) and the last single tick ('), this seems to get interpreted in Nmap as \x20 (space?). If I look at this in a hex editor though, it appears to be the correct CR character (0A). Trying to manually insert a CR in vim (e.g. CTRL+V 10) seems to insert a 00 (null) character, and result in the error below (no surprise)

    bbk@ubuntu:~/medusa$ ./medusa 
    thread 'main' panicked at 'error parsing service file: Scan(ScanError { mark: Marker { index: 46, line: 3, col: 11 }, info: "while scanning a quoted scalar, found unexpected end of stream" })', src/main.rs:83:49
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
    

    I might be doing something wrong, I'm going between various escape characters and ascii tables in ocatal/dec/hex but there doesn't appear to be a way to force a CR only at the end of the server_id string, and without being able to do that, it seems some server banners are going to be impossible to impersonate.

    bug 
    opened by BeanBagKing 11
  • Possible to kill @docker handler

    Possible to kill @docker handler

    In some cases (depending on the setup) it is possible to kill the jail docker container with

    kill 1
    
    

    as the command.

    This would kill the init parent process in the container and stop the container. The honeypot would then return errors instead of delegating to the running container for commands that are not already cached.

    This could probably be prevented on the docker/host side by having the container always restart or having different users for starting and running the exec.

    Maybe a configurable blacklist of commands that wont be sent to the container. I know it's not the core of the project, and need not be changed. :-) I am just mentioning it.

    opened by dandare100 5
  • private key incorrect format

    private key incorrect format

    Good morning,

    So I have recently been attempting to configure the medusa honeypot for research and fun purposes and I ran into one particulary annoying issue getting the https protocol to function correctly.

    It would appear that rustls::pemfile::rsa_private_keys requires the private key to be in PKCS#1 format, however the cert/key generation step in the readme openssl req -newkey rsa:2048 -nodes -keyout medusa-https.key -x509 -days 365 -out medusa-https.crt generates a private key in PKCS#8 format, which causes rust to panic and die when running medusa. Not sure if this is an issue with openssl version difference maybe? I'm using OpenSSL 1.1.1

    This was remediated by adding RSA to the header in the key file.

    Before: -----BEGIN PRIVATE KEY----- After: -----BEGIN RSA PRIVATE KEY-----

    Also I noticed that the certificate path in http/config.rs has the cert file as medusa-https.cert whereas the command in the readme generates medusa-https.crt which tripped me up for longer than I would care to admit ha ha ha.

    Kind regards, Kyle.

    opened by kylegbakker 3
Owner
Simone Margaritelli
Simone Margaritelli
User-friendly secure computation engine based on secure multi-party computation

CipherCore If you have any questions, or, more generally, would like to discuss CipherCore, please join the Slack community. See a vastly extended ver

CipherMode Labs 356 Jan 5, 2023
Easy to use cryptographic framework for data protection: secure messaging with forward secrecy and secure data storage. Has unified APIs across 14 platforms.

Themis provides strong, usable cryptography for busy people General purpose cryptographic library for storage and messaging for iOS (Swift, Obj-C), An

Cossack Labs 1.6k Dec 30, 2022
Cryptle: a secure multi-party Wordle clone with Enarx

Cryptle: a secure multi-party Wordle clone with Enarx Wordle is a popular web-based game, where a single player has to guess a five-letter word in six

Nick Vidal 2 May 9, 2022
A safe implementation of the secure remote password authentication and key-exchange protocol (SRP), SRP6a and legacy are as features available.

Secure Remote Password (SRP 6 / 6a) A safe implementation of the secure remote password authentication and key-exchange protocol (SRP version 6a). Ver

Sven Assmann 10 Nov 3, 2022
Pure Rust implementation of components of the Secure Shell (SSH) protocol

RustCrypto: SSH Pure Rust implementation of components of the Secure Shell (SSH) protocol. Crates Name crates.io Docs Description ssh—encoding Decoder

Rust Crypto 27 Dec 27, 2022
Freelance payment protocol written in Rust.. (with multi-sig signing for dispute settling)

Freelance Escrow payment protocol ?? About The freelance protocol is a protocol built on decentralized and open systems such as blockchain and decentr

Femi Bolaji 4 Jan 3, 2023
Web-Scale Blockchain for fast, secure, scalable, decentralized apps and marketplaces.

Building 1. Install rustc, cargo and rustfmt. $ curl https://sh.rustup.rs -sSf | sh $ source $HOME/.cargo/env $ rustup component add rustfmt When buil

Solana Foundation 9.8k Jan 3, 2023
A simple and secure rust command-line tool to protect your text by encrypting and decrypting it using the robust AES-256 algorithm.

Secret Keeper A simple and secure command-line tool to protect your text by encrypting and decrypting it using the robust AES-256 algorithm. Built wit

Kunal Bagaria 9 May 11, 2023
Scrypto Advent Calendar. Learn the new programming langage to build quick and secure DeFi applications.

Scrypto Advent Calendar I am publishing new Christmas related Scrypto examples every day from Dec 1st to Dec 25th. "Watch" this project to get notifie

Clement Bisaillon 26 Nov 13, 2022