# Provenance: stamparm/DSVW do_GET (fixed). # repo: stamparm/DSVW # commit: 7d40f4b7939c901610ed9b85724552d60e7d63fa # parent: 7d40f4b7939c901610ed9b85724552d60e7d63fa # commit_url: https://github.com/stamparm/DSVW/blob/7d40f4b7939c901610ed9b85724552d60e7d63fa/dsvw.py#L30 # cve: # license: Unlicense # function: do_GET # relpath: dsvw.py # provenance: human # mechanism: source_reaches_sink def do_GET(self): path, query = self.path.split('?', 1) if '?' in self.path else (self.path, "") code, content, params, cursor = http.client.OK, HTML_PREFIX, dict((match.group("parameter"), urllib.parse.unquote(','.join(re.findall(r"(?:\A|[?&])%s=([^&]+)" % match.group("parameter"), query)))) for match in re.finditer(r"((\A|[?&])(?P[\w\[\]]+)=)([^&]+)", query)), connection.cursor() try: if path == '/': if "id" in params: cursor.execute("SELECT id, username, name, surname FROM users WHERE id=" + params["id"]) content += "
Result(s):
%s
idusernamenamesurname
%s" % ("".join("%s" % "".join("%s" % ("-" if _ is None else _) for _ in row) for row in cursor.fetchall()), HTML_POSTFIX) elif "v" in params: content += re.sub(r"(v)[^<]+()", r"\g<1>%s\g<2>" % params["v"], HTML_POSTFIX) elif "object" in params: content = str(pickle.loads(params["object"].encode())) elif "path" in params: content = (open(os.path.abspath(params["path"]), "rb") if not "://" in params["path"] else urllib.request.urlopen(params["path"])).read().decode() elif "domain" in params: content = subprocess.run("nslookup " + params["domain"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, text=True).stdout elif "xml" in params: content = lxml.etree.tostring(lxml.etree.parse(io.BytesIO(params["xml"].encode()), lxml.etree.XMLParser(load_dtd=True, resolve_entities=True, no_network=False)), pretty_print=True).decode() elif "name" in params: found = lxml.etree.parse(io.BytesIO(USERS_XML.encode())).xpath(".//user[name/text()='%s']" % params["name"]) content += "Surname: %s%s" % (found[-1].find("surname").text if found else "-", HTML_POSTFIX) elif "size" in params: start, _ = time.time(), "
".join("#" * int(params["size"]) for _ in range(int(params["size"]))) content += "Time required (to 'resize image' to %dx%d): %.6f seconds%s" % (int(params["size"]), int(params["size"]), time.time() - start, HTML_POSTFIX) elif "comment" in params or query == "comment=": if "comment" in params: cursor.execute("INSERT INTO comments VALUES(NULL, '%s', '%s')" % (params["comment"], time.ctime())) content += "Thank you for leaving the comment. Please click here here to see all comments%s" % HTML_POSTFIX else: cursor.execute("SELECT id, comment, time FROM comments") content += "
Comment(s):
%s
idcommenttime
%s" % ("".join("%s" % "".join("%s" % ("-" if _ is None else _) for _ in row) for row in cursor.fetchall()), HTML_POSTFIX) elif "include" in params: backup, sys.stdout, program, envs = sys.stdout, io.StringIO(), (open(params["include"], "rb") if not "://" in params["include"] else urllib.request.urlopen(params["include"])).read(), {"DOCUMENT_ROOT": os.getcwd(), "HTTP_USER_AGENT": self.headers.get("User-Agent"), "REMOTE_ADDR": self.client_address[0], "REMOTE_PORT": self.client_address[1], "PATH": path, "QUERY_STRING": query} exec(program, envs) content += sys.stdout.getvalue() sys.stdout = backup elif "redir" in params: content = content.replace("", "" % params["redir"]) if HTML_PREFIX in content and HTML_POSTFIX not in content: content += "
Attacks:
\n\n" % ("".join("\n%s - vulnerable|exploit|info" % (" class=\"disabled\" title=\"module 'python-lxml' not installed\"" if ("lxml.etree" not in sys.modules and any(_ in case[0].upper() for _ in ("XML", "XPATH"))) else "", case[0], case[1], case[2], case[3]) for case in CASES)).replace("vulnerable|", "-|") elif path == "/users.json": content = "%s%s%s" % ("" if not "callback" in params else "%s(" % params["callback"], json.dumps(dict((_.findtext("username"), _.findtext("surname")) for _ in xml.etree.ElementTree.fromstring(USERS_XML).findall("user"))), "" if not "callback" in params else ")") elif path == "/login": cursor.execute("SELECT * FROM users WHERE username='" + re.sub(r"[^\w]", "", params.get("username", "")) + "' AND password='" + params.get("password", "") + "'") content += "Welcome %s" % (re.sub(r"[^\w]", "", params.get("username", "")), "".join(random.sample(string.ascii_letters + string.digits, 20))) if cursor.fetchall() else "The username and/or password is incorrect" else: code = http.client.NOT_FOUND except Exception as ex: content = ex.output if isinstance(ex, subprocess.CalledProcessError) else traceback.format_exc() code = http.client.INTERNAL_SERVER_ERROR finally: self.send_response(code) self.send_header("Connection", "close") self.send_header("X-XSS-Protection", "0") self.send_header("Content-Type", "%s%s" % ("text/html" if content.startswith("") else "text/plain", "; charset=%s" % params.get("charset", "utf8"))) self.end_headers() self.wfile.write(("%s%s" % (content, HTML_POSTFIX if HTML_PREFIX in content and GITHUB not in content else "")).encode()) self.wfile.flush()