[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#804787: jessie-pu: package servefile/0.4.3-1



I attached a new debdiff with a more meaningful changelog.

+servefile (0.4.4-1~deb8u1) jessie; urgency=high
+
+  * Upstream bugfix release
+  * Fix for path traversal bug in directory listing mode
+  * SSL hardening (prefer TLS1.2/TLS1)

If this is not detailed enough I could also just copy over the upstream
changelog. Christoph also suggested that I attach a git log -p for the
changes between v0.4.3 and v0.4.4.

Greetings,
seba

On 11.11.2015 18:53, Adam D. Barratt wrote:
> Control: tags -1 + moreinfo
> 
> On 2015-11-11 16:39, Sebastian Lohff wrote:
>> there has been a directory traversal bug in servefile, it was fixed in
>> version 0.4.4. I talked to the Debian security team and they said a DSA
>> would not be necessary and recommended doing a stable-pu. Therefore
>> I'd like to propose an update to 0.4.4 (debdiff attached).
> 
> +servefile (0.4.4-1~deb8u1) jessie; urgency=high
> +
> +  * New upstream version
> 
> That's not really a suitable changelog for an upload to unstable,
> particularly one that fixes security issues. It's certainly not suitable
> for a stable update.
> 
> The point of a changelog entry is to explain the purpose of the upload.
> In this case it is to fix a security problem and some other (specific,
> and enumerated in upstream's changelog) issues, not simply because a new
> upstream release is available. Please make the changelog indicate what
> has actually changed - see
> https://www.debian.org/doc/manuals/developers-reference/ch06.en.html#bpp-changelog-do
> , for example.
> 
> Regards,
> 
> Adam

diff -Nru servefile-0.4.3/ChangeLog servefile-0.4.4/ChangeLog
--- servefile-0.4.3/ChangeLog	2013-12-28 01:55:41.000000000 +0100
+++ servefile-0.4.4/ChangeLog	2015-11-10 21:05:35.000000000 +0100
@@ -1,6 +1,18 @@
 servefile changelog
 ===================
 
+2015-11-10 v0.4.4
+-----------------
+
+	0.4.4 released
+
+	* prefer using TLS1.2/TLS1 with --ssl if available
+	* issue v3 certificates for self signed certificates with --ssl
+	* removed lots of unnecessary error output
+	* fixed a bug where wrong ranges were used on a HEAD request in directory listing mode
+	* fixed a bug where directory listing mode allowed path traversal
+
+
 2013-12-28 v0.4.3
 -----------------
 
diff -Nru servefile-0.4.3/debian/changelog servefile-0.4.4/debian/changelog
--- servefile-0.4.3/debian/changelog	2014-08-12 22:11:04.000000000 +0200
+++ servefile-0.4.4/debian/changelog	2015-11-24 17:51:45.000000000 +0100
@@ -1,3 +1,11 @@
+servefile (0.4.4-1~deb8u1) jessie; urgency=high
+
+  * Upstream bugfix release
+  * Fix for path traversal bug in directory listing mode
+  * SSL hardening (prefer TLS1.2/TLS1)
+
+ -- Sebastian Lohff <seba@someserver.de>  Tue, 24 Nov 2015 17:44:40 +0100
+
 servefile (0.4.3-1) unstable; urgency=low
 
   * New upstream version
diff -Nru servefile-0.4.3/debian/control servefile-0.4.4/debian/control
--- servefile-0.4.3/debian/control	2014-08-13 00:41:01.000000000 +0200
+++ servefile-0.4.4/debian/control	2015-11-10 21:27:07.000000000 +0100
@@ -3,7 +3,7 @@
 Priority: optional
 Maintainer: Sebastian Lohff <seba@someserver.de>
 Build-Depends: debhelper (>= 9.0~), python
-Standards-Version: 3.9.5
+Standards-Version: 3.9.6
 Homepage: http://seba-geek.de/stuff/servefile/
 
 Package: servefile
diff -Nru servefile-0.4.3/PKG-INFO servefile-0.4.4/PKG-INFO
--- servefile-0.4.3/PKG-INFO	2013-12-28 02:31:38.000000000 +0100
+++ servefile-0.4.4/PKG-INFO	2015-11-10 21:13:09.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: servefile
-Version: 0.4.3
+Version: 0.4.4
 Summary: Serve files from shell via a small HTTP server
 Home-page: http://seba-geek.de/stuff/servefile/
 Author: Sebastian Lohff
diff -Nru servefile-0.4.3/servefile servefile-0.4.4/servefile
--- servefile-0.4.3/servefile	2013-12-28 02:21:57.000000000 +0100
+++ servefile-0.4.4/servefile	2015-11-10 20:54:36.000000000 +0100
@@ -7,7 +7,7 @@
 
 from __future__ import print_function
 
-__version__ = '0.4.3'
+__version__ = '0.4.4'
 
 import argparse
 import base64
@@ -16,7 +16,6 @@
 import mimetypes
 import urllib
 import os
-import posixpath
 import re
 import select
 import socket
@@ -102,7 +101,7 @@
 					try:
 						fromto[0] = int(fromto[0])
 						fromto[1] = int(fromto[1])
-					except:
+					except ValueError:
 						return (False, None)
 
 					if fromto[0] >= fileLength or fromto[0] < 0 or fromto[1] >= fileLength or fromto[1]-fromto[0] < 0:
@@ -154,11 +153,7 @@
 		self.end_headers()
 		block = self.getChunk(myfile, fromto)
 		while block:
-			try:
-				self.wfile.write(block)
-			except socket.error as e:
-				print("%s ABORTED transmission (Reason %s: %s)" % (self.client_address[0], e[0], e[1]))
-				return False
+			self.wfile.write(block)
 			block = self.getChunk(myfile, fromto)
 		myfile.close()
 		print("%s finished downloading %s" % (self.client_address[0], filePath))
@@ -310,6 +305,15 @@
 		""" Send file or directory index, depending on requested path """
 		path = self.getCleanPath()
 
+		# check if path is in current serving directory
+		currBaseDir = os.path.abspath(self.targetDir) + os.path.sep
+		requestPath = os.path.normpath(os.path.join(currBaseDir, path)) + os.path.sep
+		if not requestPath.startswith(currBaseDir):
+			self.send_response(301)
+			self.send_header("Location", '/')
+			self.end_headers()
+			return
+
 		if os.path.isdir(path):
 			if not self.path.endswith('/'):
 				self.send_response(301)
@@ -325,7 +329,7 @@
 					self.end_headers()
 				else:
 					self.send_response(200)
-					self.sendContentHeaders(self, path, length)
+					self.sendContentHeaders(path, length)
 					self.end_headers()
 			else:
 				self.sendFile(path, head)
@@ -406,7 +410,7 @@
 			</tr>
 		</thead>
 		<tbody>
-		""" % {'path': posixpath.normpath(urllib.unquote(self.path))}
+		""" % {'path': os.path.normpath(urllib.unquote(self.path))}
 		footer = """</tbody></table></div>
 <div class="footer"><a href="http://seba-geek.de/stuff/servefile/";>servefile %(version)s</a></div>
 </body>
@@ -468,7 +472,7 @@
 		return (size, ext.strip())
 
 	def getCleanPath(self):
-		urlPath = posixpath.normpath(urllib.unquote(self.path)).strip("/")
+		urlPath = os.path.normpath(urllib.unquote(self.path)).strip("/")
 		path = os.path.join(self.targetDir, urlPath)
 		return path
 
@@ -626,7 +630,9 @@
 		# never reached
 
 class ThreadedHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
-	pass
+	def handle_error(self, request, client_address):
+		print("%s ABORTED transmission (Reason: %s)" % (client_address[0], sys.exc_value))
+
 
 def catchSSLErrors(BaseSSLClass):
 	""" Class decorator which catches SSL errors and prints them. """
@@ -645,7 +651,19 @@
 class SecureThreadedHTTPServer(ThreadedHTTPServer):
 	def __init__(self, pubKey, privKey, server_address, RequestHandlerClass, bind_and_activate=True):
 		ThreadedHTTPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate)
-		ctx = SSL.Context(SSL.SSLv23_METHOD)
+
+		# choose TLS1.2 or TLS1, if available
+		sslMethod = None
+		if hasattr(SSL, "TLSv1_2_METHOD"):
+			sslMethod = SSL.TLSv1_2_METHOD
+		elif hasattr(SSL, "TLSv1_METHOD"):
+			sslMethod = SSL.TLSv1_METHOD
+		else:
+			# only SSLv23 available
+			print("Warning: Only SSLv2/SSLv3 is available, connection might be insecure.")
+			sslMethod = SSL.SSLv23_METHOD
+
+		ctx = SSL.Context(sslMethod)
 		if type(pubKey) is crypto.X509 and type(privKey) is crypto.PKey:
 			ctx.use_certificate(pubKey)
 			ctx.use_privatekey(privKey)
@@ -661,7 +679,11 @@
 			self.server_activate()
 
 	def shutdown_request(self, request):
-		request.shutdown()
+		try:
+			request.shutdown()
+		except SSL.Error:
+			# ignore SSL errors on connection shutdown
+			pass
 
 
 class SecureHandler():
@@ -782,6 +804,8 @@
 		req.sign(pkey, "sha1")
 
 		cert = crypto.X509()
+		# Mozilla only accepts v3 certificates with v3 extensions, not v1
+		cert.set_version(0x2)
 		# some browsers complain if they see a cert from the same authority
 		# with the same serial ==> we just use the seconds as serial.
 		cert.set_serial_number(int(time.time()))
diff -Nru servefile-0.4.3/servefile.1 servefile-0.4.4/servefile.1
--- servefile-0.4.3/servefile.1	2013-12-28 02:30:48.000000000 +0100
+++ servefile-0.4.4/servefile.1	2015-11-10 21:12:39.000000000 +0100
@@ -1,4 +1,4 @@
-.TH SERVEFILE 1 "December 2013" "servefile 0.4.3" "User Commands"
+.TH SERVEFILE 1 "November 2015" "servefile 0.4.4" "User Commands"
 
 .SH NAME
 servefile \- small HTTP-Server for temporary file transfer
diff -Nru servefile-0.4.3/setup.py servefile-0.4.4/setup.py
--- servefile-0.4.3/setup.py	2013-12-28 02:22:22.000000000 +0100
+++ servefile-0.4.4/setup.py	2015-11-10 21:11:58.000000000 +0100
@@ -7,7 +7,7 @@
 	description='Serve files from shell via a small HTTP server',
 	long_description='Serve files from shell via a small HTTP server. The server redirects all HTTP requests to the file, so only IP and port must be given to another user to access the file. Its main purpose is to quickly send a file to users in your local network, independent of their current setup (OS/software). Beneath that it also supports uploads, SSL, HTTP basic auth and directory listings.',
 	platforms='posix',
-	version='0.4.3',
+	version='0.4.4',
 	license='GPLv3 or later',
 	url='http://seba-geek.de/stuff/servefile/',
 	author='Sebastian Lohff',
commit 2cc0119665ac275f3d53c93dc1a4162c500ba3df
Author: Sebastian Lohff <seba@someserver.de>
Date:   Tue Nov 10 21:05:50 2015 +0100

    Moved to v0.4.4

diff --git a/ChangeLog b/ChangeLog
index 1431bcb..3c0af94 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,18 @@
 servefile changelog
 ===================
 
+2015-11-10 v0.4.4
+-----------------
+
+	0.4.4 released
+
+	* prefer using TLS1.2/TLS1 with --ssl if available
+	* issue v3 certificates for self signed certificates with --ssl
+	* removed lots of unnecessary error output
+	* fixed a bug where wrong ranges were used on a HEAD request in directory listing mode
+	* fixed a bug where directory listing mode allowed path traversal
+
+
 2013-12-28 v0.4.3
 -----------------
 
diff --git a/servefile b/servefile
index 1d6e6ed..0734c79 100755
--- a/servefile
+++ b/servefile
@@ -7,7 +7,7 @@
 
 from __future__ import print_function
 
-__version__ = '0.4.3'
+__version__ = '0.4.4'
 
 import argparse
 import base64

commit cd7eee21be3602ab6118a23eec8e2628d1a6488c
Author: Sebastian Lohff <seba@someserver.de>
Date:   Tue Nov 10 20:51:18 2015 +0100

    Fixed directory traversal bug with direcotry listing

diff --git a/servefile b/servefile
index 9a2733d..1d6e6ed 100755
--- a/servefile
+++ b/servefile
@@ -305,6 +305,15 @@ class DirListingHandler(FileBaseHandler):
 		""" Send file or directory index, depending on requested path """
 		path = self.getCleanPath()
 
+		# check if path is in current serving directory
+		currBaseDir = os.path.abspath(self.targetDir) + os.path.sep
+		requestPath = os.path.normpath(os.path.join(currBaseDir, path)) + os.path.sep
+		if not requestPath.startswith(currBaseDir):
+			self.send_response(301)
+			self.send_header("Location", '/')
+			self.end_headers()
+			return
+
 		if os.path.isdir(path):
 			if not self.path.endswith('/'):
 				self.send_response(301)

commit 11ad07cc7602b7e09592eabcea47f4c2f38c1237
Author: Sebastian Lohff <seba@someserver.de>
Date:   Tue Nov 10 20:39:42 2015 +0100

    Replaced posixpath calls with os.path

diff --git a/servefile b/servefile
index e8d91f0..9a2733d 100755
--- a/servefile
+++ b/servefile
@@ -16,7 +16,6 @@ import datetime
 import mimetypes
 import urllib
 import os
-import posixpath
 import re
 import select
 import socket
@@ -402,7 +401,7 @@ class DirListingHandler(FileBaseHandler):
 			</tr>
 		</thead>
 		<tbody>
-		""" % {'path': posixpath.normpath(urllib.unquote(self.path))}
+		""" % {'path': os.path.normpath(urllib.unquote(self.path))}
 		footer = """</tbody></table></div>
 <div class="footer"><a href="http://seba-geek.de/stuff/servefile/";>servefile %(version)s</a></div>
 </body>
@@ -464,7 +463,7 @@ class DirListingHandler(FileBaseHandler):
 		return (size, ext.strip())
 
 	def getCleanPath(self):
-		urlPath = posixpath.normpath(urllib.unquote(self.path)).strip("/")
+		urlPath = os.path.normpath(urllib.unquote(self.path)).strip("/")
 		path = os.path.join(self.targetDir, urlPath)
 		return path
 

commit 0c781c2b73840fabaf974368f364e16f6c644d04
Author: Sebastian Lohff <seba@someserver.de>
Date:   Mon Aug 3 05:41:51 2015 +0200

    Send correct headers on range/HEAD request

diff --git a/servefile b/servefile
index 81ec250..e8d91f0 100755
--- a/servefile
+++ b/servefile
@@ -321,7 +321,7 @@ class DirListingHandler(FileBaseHandler):
 					self.end_headers()
 				else:
 					self.send_response(200)
-					self.sendContentHeaders(self, path, length)
+					self.sendContentHeaders(path, length)
 					self.end_headers()
 			else:
 				self.sendFile(path, head)

commit cb4ebb017ff6157cabac56f927ec5a2aac9be6d9
Author: Sebastian Lohff <seba@someserver.de>
Date:   Mon Aug 3 05:33:57 2015 +0200

    Only catch ValueError, not all exceptions

diff --git a/servefile b/servefile
index e3aaa9d..81ec250 100755
--- a/servefile
+++ b/servefile
@@ -102,7 +102,7 @@ class FileBaseHandler(BaseHTTPServer.BaseHTTPRequestHandler):
 					try:
 						fromto[0] = int(fromto[0])
 						fromto[1] = int(fromto[1])
-					except:
+					except ValueError:
 						return (False, None)
 
 					if fromto[0] >= fileLength or fromto[0] < 0 or fromto[1] >= fileLength or fromto[1]-fromto[0] < 0:

commit 42949c1403861d81802a04159c7fe1e8edaa2c9b
Author: Sebastian Lohff <seba@someserver.de>
Date:   Wed Mar 18 00:22:21 2015 +0100

    Swallow traces when client aborts transmission

diff --git a/servefile b/servefile
index 1e27462..e3aaa9d 100755
--- a/servefile
+++ b/servefile
@@ -154,11 +154,7 @@ class FileBaseHandler(BaseHTTPServer.BaseHTTPRequestHandler):
 		self.end_headers()
 		block = self.getChunk(myfile, fromto)
 		while block:
-			try:
-				self.wfile.write(block)
-			except socket.error as e:
-				print("%s ABORTED transmission (Reason %s: %s)" % (self.client_address[0], e[0], e[1]))
-				return False
+			self.wfile.write(block)
 			block = self.getChunk(myfile, fromto)
 		myfile.close()
 		print("%s finished downloading %s" % (self.client_address[0], filePath))
@@ -626,7 +622,9 @@ class FilePutter(BaseHTTPServer.BaseHTTPRequestHandler):
 		# never reached
 
 class ThreadedHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
-	pass
+	def handle_error(self, request, client_address):
+		print("%s ABORTED transmission (Reason: %s)" % (client_address[0], sys.exc_value))
+
 
 def catchSSLErrors(BaseSSLClass):
 	""" Class decorator which catches SSL errors and prints them. """

commit 46757ff89b5d408b6ce170d94333c0df292a8297
Author: Sebastian Lohff <seba@someserver.de>
Date:   Tue Mar 17 23:47:51 2015 +0100

    Mute SSL exceptions on connection shutdown
    
    Happens most frequently with SSL errors being sent by the
    client

diff --git a/servefile b/servefile
index 639b169..1e27462 100755
--- a/servefile
+++ b/servefile
@@ -673,7 +673,11 @@ class SecureThreadedHTTPServer(ThreadedHTTPServer):
 			self.server_activate()
 
 	def shutdown_request(self, request):
-		request.shutdown()
+		try:
+			request.shutdown()
+		except SSL.Error:
+			# ignore SSL errors on connection shutdown
+			pass
 
 
 class SecureHandler():

commit 659383bf30169c3a546ccc6d9ac6893a7348bca6
Author: Sebastian Lohff <seba@someserver.de>
Date:   Tue Mar 17 23:38:46 2015 +0100

    Issue v3 certificate with --ssl

diff --git a/servefile b/servefile
index fd82c3e..639b169 100755
--- a/servefile
+++ b/servefile
@@ -794,6 +794,8 @@ class ServeFile():
 		req.sign(pkey, "sha1")
 
 		cert = crypto.X509()
+		# Mozilla only accepts v3 certificates with v3 extensions, not v1
+		cert.set_version(0x2)
 		# some browsers complain if they see a cert from the same authority
 		# with the same serial ==> we just use the seconds as serial.
 		cert.set_serial_number(int(time.time()))

commit 9201b62f1829863bf1ab5d90f10e312890294056
Author: Sebastian Lohff <seba@someserver.de>
Date:   Tue Mar 17 23:32:20 2015 +0100

    Use TLS1.2 / TLS1 with --ssl if available

diff --git a/servefile b/servefile
index 58deec1..fd82c3e 100755
--- a/servefile
+++ b/servefile
@@ -645,7 +645,19 @@ def catchSSLErrors(BaseSSLClass):
 class SecureThreadedHTTPServer(ThreadedHTTPServer):
 	def __init__(self, pubKey, privKey, server_address, RequestHandlerClass, bind_and_activate=True):
 		ThreadedHTTPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate)
-		ctx = SSL.Context(SSL.SSLv23_METHOD)
+
+		# choose TLS1.2 or TLS1, if available
+		sslMethod = None
+		if hasattr(SSL, "TLSv1_2_METHOD"):
+			sslMethod = SSL.TLSv1_2_METHOD
+		elif hasattr(SSL, "TLSv1_METHOD"):
+			sslMethod = SSL.TLSv1_METHOD
+		else:
+			# only SSLv23 available
+			print("Warning: Only SSLv2/SSLv3 is available, connection might be insecure.")
+			sslMethod = SSL.SSLv23_METHOD
+
+		ctx = SSL.Context(sslMethod)
 		if type(pubKey) is crypto.X509 and type(privKey) is crypto.PKey:
 			ctx.use_certificate(pubKey)
 			ctx.use_privatekey(privKey)

Reply to: