Browse Source

HUE-4651 [fb] Prevent inline display of non authorized mime types

Romain Rigaux 9 years ago
parent
commit
3d8965b

+ 8 - 5
apps/filebrowser/src/filebrowser/views.py

@@ -104,7 +104,7 @@ def index(request):
 
 
   try:
   try:
     if not request.fs.isdir(path):
     if not request.fs.isdir(path):
-       path = '/'
+      path = '/'
   except Exception:
   except Exception:
     pass
     pass
 
 
@@ -146,7 +146,7 @@ def download(request, path):
     response = HttpResponse(_file_reader(fh), content_type=content_type)
     response = HttpResponse(_file_reader(fh), content_type=content_type)
     response["Last-Modified"] = http_date(stats['mtime'])
     response["Last-Modified"] = http_date(stats['mtime'])
     response["Content-Length"] = stats['size']
     response["Content-Length"] = stats['size']
-    response['Content-Disposition'] = request.GET.get('disposition', 'attachment')
+    response['Content-Disposition'] = request.GET.get('disposition', 'attachment') if _can_inline_display(path) else 'attachment'
     return response
     return response
 
 
 
 
@@ -556,9 +556,7 @@ def display(request, path):
 
 
     # display inline files just if it's not an ajax request
     # display inline files just if it's not an ajax request
     if not request.is_ajax():
     if not request.is_ajax():
-      mimetype = mimetypes.guess_type(path)[0]
-      print mimetype
-      if mimetype is not None and INLINE_DISPLAY_MIMETYPE.search(mimetype) and INLINE_DISPLAY_MIMETYPE_EXCEPTIONS.search(mimetype) is None:
+      if _can_inline_display(path):
         return redirect(reverse('filebrowser.views.download', args=[path]) + '?disposition=inline')
         return redirect(reverse('filebrowser.views.download', args=[path]) + '?disposition=inline')
 
 
     stats = request.fs.stats(path)
     stats = request.fs.stats(path)
@@ -653,6 +651,11 @@ def display(request, path):
     return render("display.mako", request, data)
     return render("display.mako", request, data)
 
 
 
 
+def _can_inline_display(path):
+  mimetype = mimetypes.guess_type(path)[0]
+  return mimetype is not None and INLINE_DISPLAY_MIMETYPE.search(mimetype) and INLINE_DISPLAY_MIMETYPE_EXCEPTIONS.search(mimetype) is None
+
+
 def read_contents(codec_type, path, fs, offset, length):
 def read_contents(codec_type, path, fs, offset, length):
     """
     """
     Reads contents of a passed path, by appropriately decoding the data.
     Reads contents of a passed path, by appropriately decoding the data.

+ 24 - 0
apps/filebrowser/src/filebrowser/views_test.py

@@ -769,6 +769,30 @@ class TestFileBrowserWithHadoop(object):
     assert_equal(None, response.context['home_directory'])
     assert_equal(None, response.context['home_directory'])
 
 
 
 
+  def test_download(self):
+    prefix = self.cluster.fs_prefix + '/test_download'
+    self.cluster.fs.mkdir(prefix)
+
+    f = self.cluster.fs.open(prefix + '/xss', "w")
+    sdf_string = '''<html>
+<head>
+<title>Hello</title>
+<script>
+alert("XSS")
+</script>
+</head>
+<body>
+<h1>I am evil</h1>
+</body>
+</html>'''
+    f.write(sdf_string)
+    f.close()
+
+    response = self.c.get('/filebrowser/download=%s/xss?disposition=inline' % prefix, follow=True)
+    assert_equal(200, response.status_code)
+    assert_equal('attachment', response['Content-Disposition'])
+
+
   def test_edit_i18n(self):
   def test_edit_i18n(self):
     prefix = self.cluster.fs_prefix + '/test_view_gz'
     prefix = self.cluster.fs_prefix + '/test_view_gz'
     self.cluster.fs.mkdir(prefix)
     self.cluster.fs.mkdir(prefix)