bundled exiftool does not use own libs when distribution-packaged exiftool is also installed, leading to crashes and prevents JPGs to be attached to comments
Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.
I think this issue is loosely related to #369929 (closed) , but definately not the same.
Setup:
- Ubuntu 20.04 (this is important due to the exiftools-version)
- GitLab (16.3.5, Omnibus-Install. We're using gitlab-ee, but this should apply to ce as well)
- Have the distribution-provided exiftool installed (in case of ubuntu this is
libimage-exiftool-perl
)
With the setup given above you will likely notice, that you cannot attach JPGs (or TIFFs for this exercise) to anything that uses the Richtext-Editor in the WebUI (this especially affects Issues and Comments to Issues). Image Upload just fails with Failed to process image
, while PNGs ans GIFs are working fine.
Crawling the log reveals, that exiftool tries to strip metadata from images and fails by doing so:
{"correlation_id":"[redacted]","filename":"test.jpg","level":"info","msg":"running exiftool to remove any metadata","time":"2023-10-13T13:31:12+02:00"}
{"command":["exiftool","-all=","--IPTC:all","--XMP-iptcExt:all","-tagsFromFile","@","-ResolutionUnit","-XResolution","-YResolution","-YCbCrSubSampling","-YCbCrPositioning","-BitsPerSample","-ImageHeight","-ImageWidth","-ImageSize","-Copyright","-CopyrightNotice","-Orientation","-"],"correlation_id":"[redacted]","error":"exit status 2","level":"info","msg":"exiftool command failed","stderr":"Undefined subroutine Image::ExifTool::SplitFileName called at /usr/share/perl5/Image/ExifTool.pm line 4486\n","time":"2023-10-13T13:31:13+02:00"}
{"correlation_id":"[redacted]","error":"error while removing EXIF","level":"error","method":"POST","msg":"","time":"2023-10-13T13:31:13+02:00","uri":"/test-git/test/uploads"}
{"content_type":"text/plain; charset=utf-8","correlation_id":"[redacted]","duration_ms":179,"host":"[redacted]","level":"info","method":"POST","msg":"access","proto":"HTTP/1.1","referrer":"https://[redacted]/test/test/-/issues/3","remote_addr":"[redacted]:0","remote_ip":"[redacted]","route":"^/([^/]+/){1,}[^/]+/uploads\\z","status":422,"system":"http","time":"2023-10-13T13:31:13+02:00","ttfb_ms":178,"uri":"/test-git/test/uploads","user_agent":"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0","written_bytes":24}
(these is the complete papertrail of the same correlation-id)
So following this, the exiftool command beeing executed here is:
exiftool -all= --IPTC:all --XMP-iptcExt:all -tagsFromFile @ -ResolutionUnit -XResolution -YResolution -YCbCrSubSampling -YCbCrPositioning -BitsPerSample -ImageHeight -ImageWidth -ImageSize -Copyright -CopyrightNotice -Orientation -
Obviously the bundled exiftool is used. In Ubuntu this is at /opt/gitlab/embedded/bin/exiftool
. When the exiftool from the distribution (libimage-exiftool-perl
) is NOT installed, your trace using the bundled exiftool loks like this:
root@[redacted]:~# strace -ff -efile /opt/gitlab/embedded/bin/exiftool /tmp/test.jpg 2>&1|grep -v ENOENT|grep pm|grep openat
openat(AT_FDCWD, "/usr/share/perl/5.30/strict.pm", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/usr/share/perl/5.30/warnings.pm", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/opt/gitlab/embedded/lib/exiftool-perl/Image/ExifTool.pm", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/opt/gitlab/embedded/lib/exiftool-perl/File/RandomAccess.pm", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/usr/share/perl/5.30/vars.pm", O_RDONLY|O_CLOEXEC) = 6
openat(AT_FDCWD, "/usr/share/perl/5.30/warnings/register.pm", O_RDONLY|O_CLOEXEC) = 7
openat(AT_FDCWD, "/usr/share/perl/5.30/Exporter.pm", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/usr/share/perl/5.30/overload.pm", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/usr/share/perl/5.30/overloading.pm", O_RDONLY|O_CLOEXEC) = 6
openat(AT_FDCWD, "/usr/share/perl/5.30/Exporter/Heavy.pm", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/perl/5.30/File/Glob.pm", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/usr/share/perl/5.30/XSLoader.pm", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/opt/gitlab/embedded/lib/exiftool-perl/Image/ExifTool/Exif.pm", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/opt/gitlab/embedded/lib/exiftool-perl/Image/ExifTool/MakerNotes.pm", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/usr/share/perl/5.30/File/Basename.pm", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/perl/5.30/Scalar/Util.pm", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/perl/5.30/List/Util.pm", O_RDONLY|O_CLOEXEC) = 4
root@[redacted]:~#
When ubuntu's exiftool is installed, the same trace looks like this:
root@[redacted]:~# strace -ff -efile /opt/gitlab/embedded/bin/exiftool /tmp/test.jpg 2>&1|grep -v ENOENT|grep pm|grep openat
openat(AT_FDCWD, "/usr/share/perl/5.30/strict.pm", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/usr/share/perl/5.30/warnings.pm", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/usr/share/perl5/Image/ExifTool.pm", O_RDONLY|O_CLOEXEC) = 4 # <-- difference here
openat(AT_FDCWD, "/usr/share/perl5/File/RandomAccess.pm", O_RDONLY|O_CLOEXEC) = 5 # <-- and here
openat(AT_FDCWD, "/usr/share/perl/5.30/vars.pm", O_RDONLY|O_CLOEXEC) = 6
openat(AT_FDCWD, "/usr/share/perl/5.30/warnings/register.pm", O_RDONLY|O_CLOEXEC) = 7
openat(AT_FDCWD, "/usr/share/perl/5.30/Exporter.pm", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/usr/share/perl/5.30/overload.pm", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/usr/share/perl/5.30/overloading.pm", O_RDONLY|O_CLOEXEC) = 6
openat(AT_FDCWD, "/usr/share/perl/5.30/Exporter/Heavy.pm", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/perl/5.30/File/Glob.pm", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/usr/share/perl/5.30/XSLoader.pm", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/usr/share/perl5/Image/ExifTool/Exif.pm", O_RDONLY|O_CLOEXEC) = 4 # <-- and here
openat(AT_FDCWD, "/usr/share/perl5/Image/ExifTool/MakerNotes.pm", O_RDONLY|O_CLOEXEC) = 5 # <-- and here
openat(AT_FDCWD, "/usr/share/perl5/Image/ExifTool/TagLookup.pm", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/usr/share/perl5/Image/ExifTool/Fixup.pm", O_RDONLY|O_CLOEXEC) = 5
root@[redacted]:~#
As long as the versions are closely adjacent to each other, this might not even be an issue, but GitLab currently uses exiftool 12.65, while ubuntu 20.04 is at 11.88, causing the embedded exiftool to crash instantly (before even attempting to read the jpg) when it uses the ubtuntu-libs.
The solution would obviously be to force the embedded exiftool to use it's own libs to avoid this Problem (because having exiftool in the OS is a totally valid requirement for other stuff on the same instance). I haven't tested this behaviour for other gitlab-versions, but I'd assume this will affect basically all cases, where an OS-Provided exiftool is installed, and the major-versions differ. If you managed to find a lazy-managed gitlab-instance in the wild, that suffers from this issue (which can be easily tested by trying to write a comment with images), you may also be able to exploit this behaviour, and therefore this might also pose a security-risk if left unpatched.
-zeus