Browse Source

reworked code to address path traversal vuln

pull/164/head
White 4 months ago
parent
commit
cba94e8b30
  1. 61
      PVEDiscordDark/serve.py

61
PVEDiscordDark/serve.py

@ -1,63 +1,56 @@
# Script to assist with PVEDiscordDark development
#
# By default serves HTTP on port 3000, any *.js request gets the JS script, any *.css request gets the CSS file and any image request gets corresponding image
# Meant to be used with the "Requestly" browser extension to redirect PVEDD requests from PVE server to localhost:3000
#
from http.server import HTTPServer, BaseHTTPRequestHandler from http.server import HTTPServer, BaseHTTPRequestHandler
import json import json
import os import os
import mimetypes
PORT = 3000 PORT = 3000
DIR_SASS = os.path.join(os.path.dirname(__file__), "sass") DIR_SASS = os.path.join(os.path.dirname(__file__), "sass")
DIR_IMAGES = os.path.join(os.path.dirname(__file__), "images") DIR_IMAGES = os.path.join(os.path.dirname(__file__), "images")
DIR_JS = os.path.join(os.path.dirname(__file__), "js") DIR_JS = os.path.join(os.path.dirname(__file__), "js")
STATUS_OK = 200
STATUS_NOT_FOUND = 404
STATUS_BAD_REQUEST = 400
class Server(BaseHTTPRequestHandler): class Server(BaseHTTPRequestHandler):
def log_message(self, format, *args): def log_message(self, format, *args):
return # Basic logging to console
print(format % args)
def _set_headers(self, status, type): def _send_response(self, status, content_type):
self.send_response(status) self.send_response(status)
self.send_header("Content-type", type) self.send_header("Content-type", content_type)
self.end_headers() self.end_headers()
def do_GET(self): def _read_file(self, directory, filename, default_status, content_type):
status = 200 try:
type = "application/json" with open(os.path.join(directory, filename), "rb") as f:
data = None return f.read(), STATUS_OK, content_type
except FileNotFoundError:
return None, STATUS_NOT_FOUND, "application/json"
def do_GET(self):
file = self.path.rpartition("/")[2] file = self.path.rpartition("/")[2]
ext = file.rpartition(".")[2] ext = file.rpartition(".")[2]
if ext == "css": if ext == "css":
data = open(os.path.join(DIR_SASS, "PVEDiscordDark.css"), "rb").read() data, status, content_type = self._read_file(DIR_SASS, "PVEDiscordDark.css", STATUS_NOT_FOUND, "text/css")
type = "text/css"
elif ext == "js": elif ext == "js":
data = open(os.path.join(DIR_JS, "PVEDiscordDark.js"), "rb").read() data, status, content_type = self._read_file(DIR_JS, "PVEDiscordDark.js", STATUS_NOT_FOUND, "application/javascript")
type = "application/javascript" elif ext in ["png", "jpg", "jpeg", "svg"]:
elif ext == "png" or ext == "jpg" or ext == "jpeg": content_type, _ = mimetypes.guess_type(file)
try: data, status, content_type = self._read_file(DIR_IMAGES, file, STATUS_NOT_FOUND, content_type)
data = open(os.path.join(DIR_IMAGES, file), "rb").read()
type = f"image/{ext}"
except FileNotFoundError:
status = 404
elif ext == "svg":
try:
data = open(os.path.join(DIR_IMAGES, file), "rb").read()
type = f"image/svg+xml"
except FileNotFoundError:
status = 404
else: else:
status = 400 data, status, content_type = None, STATUS_BAD_REQUEST, "application/json"
self._set_headers(status, type)
if status == 200: self._send_response(status, content_type)
self.wfile.write(data)
if status == STATUS_OK:
if data is not None:
self.wfile.write(data)
else: else:
self.wfile.write(json.dumps({"error": status}).encode()) self.wfile.write(json.dumps({"error": status}).encode())
if __name__ == "__main__": if __name__ == "__main__":
print(f"Serving on localhost:{PORT}") print(f"Serving on localhost:{PORT}")
server = HTTPServer(server_address=("", PORT), RequestHandlerClass=Server) server = HTTPServer(server_address=("", PORT), RequestHandlerClass=Server)

Loading…
Cancel
Save