1
0
mirror of synced 2024-11-25 18:54:22 +01:00

Prevent exiftool-based parameter-injection

This commit is contained in:
jvoisin 2018-06-06 23:50:25 +02:00
parent fa6c06ed8a
commit 6a832a4104
2 changed files with 33 additions and 16 deletions

View File

@ -1,6 +1,8 @@
import subprocess import subprocess
import json import json
import os import os
import shutil
import tempfile
import cairo import cairo
@ -11,7 +13,26 @@ from gi.repository import GdkPixbuf
from . import abstract from . import abstract
class PNGParser(abstract.AbstractParser): class __ImageParser(abstract.AbstractParser):
def get_meta(self):
""" There is no way to escape the leading(s) dash(es) of the current
self.filename to prevent parameter injections, so we do have to copy it
"""
fname = self.filename
tmpdirname = ""
if self.filename.startswith('-'):
tmpdirname = tempfile.mkdtemp()
fname = os.path.join(tmpdirname, self.filename)
shutil.copy(self.filename, fname)
out = subprocess.check_output(['/usr/bin/exiftool', '-json', fname])
if self.filename.startswith('-'):
shutil.rmtree(tmpdirname)
meta = json.loads(out.decode('utf-8'))[0]
for key in self.meta_whitelist:
meta.pop(key, None)
return meta
class PNGParser(__ImageParser):
mimetypes = {'image/png', } mimetypes = {'image/png', }
meta_whitelist = {'SourceFile', 'ExifToolVersion', 'FileName', meta_whitelist = {'SourceFile', 'ExifToolVersion', 'FileName',
'Directory', 'FileSize', 'FileModifyDate', 'Directory', 'FileSize', 'FileModifyDate',
@ -28,30 +49,16 @@ class PNGParser(abstract.AbstractParser):
except MemoryError: except MemoryError:
raise ValueError raise ValueError
def get_meta(self):
out = subprocess.check_output(['/usr/bin/exiftool', '-json', self.filename])
meta = json.loads(out.decode('utf-8'))[0]
for key in self.meta_whitelist:
meta.pop(key, None)
return meta
def remove_all(self): def remove_all(self):
surface = cairo.ImageSurface.create_from_png(self.filename) surface = cairo.ImageSurface.create_from_png(self.filename)
surface.write_to_png(self.output_filename) surface.write_to_png(self.output_filename)
return True return True
class GdkPixbufAbstractParser(abstract.AbstractParser): class GdkPixbufAbstractParser(__ImageParser):
""" GdkPixbuf can handle a lot of surfaces, so we're rending images on it, """ GdkPixbuf can handle a lot of surfaces, so we're rending images on it,
this has the side-effect of removing metadata completely. this has the side-effect of removing metadata completely.
""" """
def get_meta(self):
out = subprocess.check_output(['/usr/bin/exiftool', '-json', self.filename])
meta = json.loads(out.decode('utf-8'))[0]
for key in self.meta_whitelist:
meta.pop(key, None)
return meta
def remove_all(self): def remove_all(self):
_, extension = os.path.splitext(self.filename) _, extension = os.path.splitext(self.filename)
pixbuf = GdkPixbuf.Pixbuf.new_from_file(self.filename) pixbuf = GdkPixbuf.Pixbuf.new_from_file(self.filename)

View File

@ -17,6 +17,16 @@ class TestParserFactory(unittest.TestCase):
self.assertEqual(parser.__class__, audio.MP3Parser) self.assertEqual(parser.__class__, audio.MP3Parser)
class TestParameterInjection(unittest.TestCase):
def test_ver_injection(self):
shutil.copy('./tests/data/dirty.png', './-ver')
p = images.PNGParser('-ver')
meta = p.get_meta()
self.assertEqual(meta['Comment'], 'This is a comment, be careful!')
self.assertEqual(meta['ModifyDate'], "2018:03:20 21:59:25")
os.remove('-ver')
class TestUnsupportedFiles(unittest.TestCase): class TestUnsupportedFiles(unittest.TestCase):
def test_pdf(self): def test_pdf(self):
shutil.copy('./tests/test_libmat2.py', './tests/clean.py') shutil.copy('./tests/test_libmat2.py', './tests/clean.py')