From 724d0dce6e2ac5e2054f4c524d9d5e177106f11b Mon Sep 17 00:00:00 2001
From: Helmut Grohne <helmut@subdivi.de>
Date: Sat, 29 May 2010 00:44:05 +0200
Subject: security fix: filters.RequestLogWSGIFilter must escape strings

---
 wsgitools/filters.py | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

(limited to 'wsgitools')

diff --git a/wsgitools/filters.py b/wsgitools/filters.py
index 64038c8..11623ef 100644
--- a/wsgitools/filters.py
+++ b/wsgitools/filters.py
@@ -202,6 +202,20 @@ class WSGIFilterMiddleware:
                                  (reqfilter.filter_data(data) for data in ret),
                                  late_append_data())
 
+# Using map and lambda here since pylint cannot handle list comprehension in
+# default arguments. Also note that neither ' nor " are considered printable.
+def escape_string(string, replacer=list(map(
+        lambda i: chr(i) if chr(i).isalnum() or
+                chr(i) in '!#$%&()*+,-./:;<=>?@[\\]^_`{|}~ ' else
+                r"\x%2.2x" % i,
+        range(256)))):
+    """Encodes non-printable characters in a string using \\xXX escapes.
+
+    @type string: str
+    @rtype: str
+    """
+    return "".join(replacer[ord(char)] for char in string)
+
 __all__.append("RequestLogWSGIFilter")
 class RequestLogWSGIFilter(BaseWSGIFilter):
     """This filter logs all requests in the apache log file format."""
@@ -263,16 +277,17 @@ class RequestLogWSGIFilter(BaseWSGIFilter):
     def handle_close(self):
         """BaseWSGIFilter interface"""
         line = '%s %s - [%s]' % (self.remote, self.user, self.time)
-        line = '%s "%s %s' % (line, self.reqmethod, self.path)
+        line = '%s "%s %s' % (line, escape_string(self.reqmethod),
+                              escape_string(self.path))
         if self.proto is not None:
             line = "%s %s" % (line, self.proto)
         line = '%s" %s %d' % (line, self.status, self.length)
         if self.referrer is not None:
-            line = '%s "%s"' % (line, self.referrer)
+            line = '%s "%s"' % (line, escape_string(self.referrer))
         else:
             line += " -"
         if self.useragent is not None:
-            line = '%s "%s"' % (line, self.useragent)
+            line = '%s "%s"' % (line, escape_string(self.useragent))
         else:
             line += " -"
         self.log.write("%s\n" % line)
-- 
cgit v1.2.3