From 48dca560694c1caedd088da039e029022eaef697 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Sun, 30 Jul 2023 11:06:37 -0500 Subject: [PATCH 1/5] initial hardening --- adafruit_httpserver/request.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/adafruit_httpserver/request.py b/adafruit_httpserver/request.py index a589b28..aed7862 100644 --- a/adafruit_httpserver/request.py +++ b/adafruit_httpserver/request.py @@ -33,9 +33,33 @@ def _add_field_value(self, field_name: str, value: Union[str, bytes]) -> None: else: self._storage[field_name].append(value) - def get(self, field_name: str, default: Any = None) -> Union[str, bytes, None]: + def _html_output_encode(self, value): + return ( + str(value) + .replace("&", "&") + .replace("<", "<") + .replace(">", ">") + .replace('"', """) + .replace("'", "'") + ) + + def _debug_warning_nonencoded_output(self): + """Warns about exposing all files on the device.""" + print( + f"WARNING: Setting html_output_encode to False will make XSS vulnerabilities possible by " + "allowing access to raw untrusted values submitted by users. If this data is reflected " + "or shown within HTML without proper encoding it could enable Cross-Site Scripting attacks." + ) + + def get( + self, field_name: str, default: Any = None, html_output_encode=True + ) -> Union[str, bytes, None]: """Get the value of a field.""" - return self._storage.get(field_name, [default])[0] + if html_output_encode: + return self._html_output_encode(self._storage.get(field_name, [default])[0]) + else: + self._debug_warning_nonencoded_output() + return self._storage.get(field_name, [default])[0] def get_list(self, field_name: str) -> List[Union[str, bytes]]: """Get the list of values of a field.""" From 7753ec0f54c3b6baed1cc64895b3425ac06d74db Mon Sep 17 00:00:00 2001 From: foamyguy Date: Sun, 30 Jul 2023 11:12:24 -0500 Subject: [PATCH 2/5] pylint fixes --- adafruit_httpserver/request.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/adafruit_httpserver/request.py b/adafruit_httpserver/request.py index aed7862..f9007ee 100644 --- a/adafruit_httpserver/request.py +++ b/adafruit_httpserver/request.py @@ -33,7 +33,8 @@ def _add_field_value(self, field_name: str, value: Union[str, bytes]) -> None: else: self._storage[field_name].append(value) - def _html_output_encode(self, value): + @staticmethod + def _html_output_encode(value): return ( str(value) .replace("&", "&") @@ -43,12 +44,13 @@ def _html_output_encode(self, value): .replace("'", "'") ) - def _debug_warning_nonencoded_output(self): + @staticmethod + def _debug_warning_nonencoded_output(): """Warns about exposing all files on the device.""" print( - f"WARNING: Setting html_output_encode to False will make XSS vulnerabilities possible by " + "WARNING: Setting html_output_encode to False makes XSS vulnerabilities possible by " "allowing access to raw untrusted values submitted by users. If this data is reflected " - "or shown within HTML without proper encoding it could enable Cross-Site Scripting attacks." + "or shown within HTML without proper encoding it could enable Cross-Site Scripting." ) def get( @@ -57,9 +59,9 @@ def get( """Get the value of a field.""" if html_output_encode: return self._html_output_encode(self._storage.get(field_name, [default])[0]) - else: - self._debug_warning_nonencoded_output() - return self._storage.get(field_name, [default])[0] + + self._debug_warning_nonencoded_output() + return self._storage.get(field_name, [default])[0] def get_list(self, field_name: str) -> List[Union[str, bytes]]: """Get the list of values of a field.""" From 96a6d0e57092b71157697b5ff60c186ce001e846 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Sun, 30 Jul 2023 11:14:28 -0500 Subject: [PATCH 3/5] fix docstrings --- adafruit_httpserver/request.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/adafruit_httpserver/request.py b/adafruit_httpserver/request.py index f9007ee..27b0090 100644 --- a/adafruit_httpserver/request.py +++ b/adafruit_httpserver/request.py @@ -35,6 +35,7 @@ def _add_field_value(self, field_name: str, value: Union[str, bytes]) -> None: @staticmethod def _html_output_encode(value): + """Encodes unsafe HTML characters.""" return ( str(value) .replace("&", "&") @@ -46,7 +47,7 @@ def _html_output_encode(value): @staticmethod def _debug_warning_nonencoded_output(): - """Warns about exposing all files on the device.""" + """Warns about XSS risks.""" print( "WARNING: Setting html_output_encode to False makes XSS vulnerabilities possible by " "allowing access to raw untrusted values submitted by users. If this data is reflected " From a55bfe933dc4e840e4f60221a94902d27a801067 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 31 Jul 2023 09:10:12 -0500 Subject: [PATCH 4/5] move debug def, rename arg to safe, rename encoding def, use more descriptive encoded value. --- adafruit_httpserver/request.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/adafruit_httpserver/request.py b/adafruit_httpserver/request.py index 27b0090..9442a89 100644 --- a/adafruit_httpserver/request.py +++ b/adafruit_httpserver/request.py @@ -34,7 +34,7 @@ def _add_field_value(self, field_name: str, value: Union[str, bytes]) -> None: self._storage[field_name].append(value) @staticmethod - def _html_output_encode(value): + def _encode_html_entities(value): """Encodes unsafe HTML characters.""" return ( str(value) @@ -42,26 +42,17 @@ def _html_output_encode(value): .replace("<", "<") .replace(">", ">") .replace('"', """) - .replace("'", "'") - ) - - @staticmethod - def _debug_warning_nonencoded_output(): - """Warns about XSS risks.""" - print( - "WARNING: Setting html_output_encode to False makes XSS vulnerabilities possible by " - "allowing access to raw untrusted values submitted by users. If this data is reflected " - "or shown within HTML without proper encoding it could enable Cross-Site Scripting." + .replace("'", "'") ) def get( - self, field_name: str, default: Any = None, html_output_encode=True + self, field_name: str, default: Any = None, *, safe=True ) -> Union[str, bytes, None]: """Get the value of a field.""" - if html_output_encode: - return self._html_output_encode(self._storage.get(field_name, [default])[0]) + if safe: + return self._encode_html_entities(self._storage.get(field_name, [default])[0]) - self._debug_warning_nonencoded_output() + _debug_warning_nonencoded_output() return self._storage.get(field_name, [default])[0] def get_list(self, field_name: str) -> List[Union[str, bytes]]: @@ -375,3 +366,12 @@ def _parse_headers(header_bytes: bytes) -> Headers: for name, value in [header_line.split(": ", 1)] } ) + + +def _debug_warning_nonencoded_output(): + """Warns about XSS risks.""" + print( + "WARNING: Setting safe to False makes XSS vulnerabilities possible by " + "allowing access to raw untrusted values submitted by users. If this data is reflected " + "or shown within HTML without proper encoding it could enable Cross-Site Scripting." + ) \ No newline at end of file From be5c8d1dfce88d657f915670f45c535b87431d4f Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 31 Jul 2023 09:10:39 -0500 Subject: [PATCH 5/5] code format --- adafruit_httpserver/request.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/adafruit_httpserver/request.py b/adafruit_httpserver/request.py index 9442a89..cda348e 100644 --- a/adafruit_httpserver/request.py +++ b/adafruit_httpserver/request.py @@ -50,7 +50,9 @@ def get( ) -> Union[str, bytes, None]: """Get the value of a field.""" if safe: - return self._encode_html_entities(self._storage.get(field_name, [default])[0]) + return self._encode_html_entities( + self._storage.get(field_name, [default])[0] + ) _debug_warning_nonencoded_output() return self._storage.get(field_name, [default])[0] @@ -374,4 +376,4 @@ def _debug_warning_nonencoded_output(): "WARNING: Setting safe to False makes XSS vulnerabilities possible by " "allowing access to raw untrusted values submitted by users. If this data is reflected " "or shown within HTML without proper encoding it could enable Cross-Site Scripting." - ) \ No newline at end of file + )