Image-Magick-Safer
view release on metacpan or search on metacpan
"requires" : {
"File::LibMagic" : "1.15"
}
}
},
"release_status" : "stable",
"resources" : {
"bugtracker" : {
"web" : "https://github.com/Humanstate/image-magick-safer/issues"
},
"homepage" : "https://metacpan.org/module/Image::Magick::Safer",
"license" : [
"http://dev.perl.org/licenses/"
],
"repository" : {
"url" : "https://github.com/Humanstate/image-magick-safer"
}
},
"version" : "0.08",
"x_serialization_backend" : "JSON::PP version 4.16"
}
version: '1.4'
name: Image-Magick-Safer
no_index:
directory:
- t
- inc
requires:
File::LibMagic: '1.15'
resources:
bugtracker: https://github.com/Humanstate/image-magick-safer/issues
homepage: https://metacpan.org/module/Image::Magick::Safer
license: http://dev.perl.org/licenses/
repository: https://github.com/Humanstate/image-magick-safer
version: '0.08'
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
Makefile.PL view on Meta::CPAN
#!perl
use strict;
use warnings;
use ExtUtils::MakeMaker;
WriteMakefile(
NAME => 'Image::Magick::Safer',
VERSION_FROM => 'lib/Image/Magick/Safer.pm',
AUTHOR => 'Lee Johnson <leejo@cpan.org>',
LICENSE => 'perl',
PREREQ_PM => {
'File::LibMagic' => 1.15,
},
BUILD_REQUIRES => {
},
META_MERGE => {
resources => {
license => 'http://dev.perl.org/licenses/',
homepage => 'https://metacpan.org/module/Image::Magick::Safer',
bugtracker => 'https://github.com/Humanstate/image-magick-safer/issues',
repository => 'https://github.com/Humanstate/image-magick-safer'
},
},
test => {
RECURSIVE_TEST_FILES => 1,
},
);
# vim: ts=4:sw=4:et
# NAME
Image::Magick::Safer - Wrap Image::Magick Read method to check magic bytes
<div>
<a href='https://travis-ci.org/Humanstate/image-magick-safer?branch=master'><img src='https://travis-ci.org/Humanstate/image-magick-safer.svg?branch=master' alt='Build Status' /></a>
<a href='https://coveralls.io/r/Humanstate/image-magick-safer?branch=master'><img src='https://coveralls.io/repos/Humanstate/image-magick-safer/badge.png?branch=master' alt='Coverage Status' /></a>
</div>
# VERSION
0.07
# SYNOPSIS
use Image::Magick::Safer;
# functions just like Image::Magick but wraps the Read method
# to check the magic bytes of any images using File::LibMagic
my $magick = Image::Magick::Safer->new;
# if any @files have a MIME type that looks questionable then
# $e will be populated
if ( my $e = $magick->Read( @files ) ) {
# bail out, unsafe to continue
....
}
# DESCRIPTION
Image::Magick::Safer is a drop in wrapper around Image::Magick, it adds a
magic byte check to the `Read` method to check the file MIME type using
[File::LibMagic](https://metacpan.org/pod/File::LibMagic). If a file looks questionable then it will prevent the file
being passed to the real Image::Magick::Read method and return an error.
If a file cannot be opened, because it does not exist or it is prefixed
with a pipe, an error will also be returned.
You can replace any calls to `Image::Magick` with `Image::Magick::Safer`
and the functionality will be retained with the added Read protection. The
aliases for `Read` will also be made safe.
If you need to override the default MIME types then you can set the modules
`$Image::Magick::Safer::Unsafe` hash to something else or add extra types:
# add SVG check to the defaults
$Image::Magick::Safer::Unsafe->{'image/svg+xml'} = 1;
The default MIME types considered unsafe are as follows:
text/plain
application/x-compress
application/x-compressed
application/gzip
application/bzip2
application/x-bzip2
application/x-gzip
that cannot be found.
Note that i make **NO GUARANTEE** that this will fix and/or protect you from
exploits, it's just another safety check. You should update to the latest
version of ImageMagick to protect yourself against potential exploits.
Also note that to install the [File::LibMagic](https://metacpan.org/pod/File::LibMagic) module you will need to have
both the library (libmagic.so) and the header file (magic.h). See the perldoc
for [File::LibMagic](https://metacpan.org/pod/File::LibMagic) for more information.
# WHY ISN'T THIS A PATCH IN Image::Magick?
Image::Magick moves at a glacial pace, and involves a 14,000 line XS file. No
thanks. This will probably get patched in the next version, so for the time
being this module exists.
# KNOWN BUGS
DOES NOT WORK with BSD 10.1 and 7.0.1 and i can't figure out why. If you can
figure out why then please submit a pull request. This is possibly some libmagic
weirdness going on.
# SEE ALSO
[Image::Magick](https://metacpan.org/pod/Image::Magick) - the library this module wraps
[https://www.imagemagick.org](https://www.imagemagick.org) - ImageMagick
[https://imagetragick.com/](https://imagetragick.com/) - ImageMagick exploits
[http://permalink.gmane.org/gmane.comp.security.oss.general/19669](http://permalink.gmane.org/gmane.comp.security.oss.general/19669) -
GraphicsMagick and ImageMagick popen() shell vulnerability via filename
# AUTHOR
lib/Image/Magick/Safer.pm view on Meta::CPAN
package Image::Magick::Safer;
=head1 NAME
Image::Magick::Safer - Wrap Image::Magick Read method to check magic bytes
=for html
<a href='https://travis-ci.org/Humanstate/image-magick-safer?branch=master'><img src='https://travis-ci.org/Humanstate/image-magick-safer.svg?branch=master' alt='Build Status' /></a>
<a href='https://coveralls.io/r/Humanstate/image-magick-safer?branch=master'><img src='https://coveralls.io/repos/Humanstate/image-magick-safer/badge.png?branch=master' alt='Coverage Status' /></a>
=head1 VERSION
0.08
=head1 SYNOPSIS
use Image::Magick::Safer;
# functions just like Image::Magick but wraps the Read method
# to check the magic bytes of any images using File::LibMagic
my $magick = Image::Magick::Safer->new;
# if any @files have a MIME type that looks questionable then
# $e will be populated
if ( my $e = $magick->Read( @files ) ) {
# bail out, unsafe to continue
....
}
=head1 DESCRIPTION
Image::Magick::Safer is a drop in wrapper around Image::Magick, it adds a
magic byte check to the C<Read> method to check the file MIME type using
L<File::LibMagic>. If a file looks questionable then it will prevent the file
being passed to the real Image::Magick::Read method and return an error.
If a file cannot be opened, because it does not exist or it is prefixed
with a pipe, an error will also be returned.
You can replace any calls to C<Image::Magick> with C<Image::Magick::Safer>
and the functionality will be retained with the added Read protection. The
aliases for C<Read> will also be made safe.
If you need to override the default MIME types then you can set the modules
C<$Image::Magick::Safer::Unsafe> hash to something else or add extra types:
# add SVG check to the defaults
$Image::Magick::Safer::Unsafe->{'image/svg+xml'} = 1;
The default MIME types considered unsafe are as follows:
text/plain
application/x-compress
application/x-compressed
application/gzip
application/bzip2
application/x-bzip2
application/x-gzip
lib/Image/Magick/Safer.pm view on Meta::CPAN
that cannot be found.
Note that i make B<NO GUARANTEE> that this will fix and/or protect you from
exploits, it's just another safety check. You should update to the latest
version of ImageMagick to protect yourself against potential exploits.
Also note that to install the L<File::LibMagic> module you will need to have
both the library (libmagic.so) and the header file (magic.h). See the perldoc
for L<File::LibMagic> for more information.
=head1 WHY ISN'T THIS A PATCH IN Image::Magick?
Image::Magick moves at a glacial pace, and involves a 14,000 line XS file. No
thanks. This will probably get patched in the next version, so for the time
being this module exists.
=cut
use strict;
use warnings;
use parent 'Image::Magick';
use File::LibMagic;
our $VERSION = '0.08';
# imagemagick can automatically uncompress archive files so there's another
# attack vector in having an exploit image zipped up, so just checking for
# text/plain isn't enough
$Image::Magick::Safer::Unsafe = {
map { $_ => 1 }
'text/plain',
'application/x-compress',
'application/x-compressed',
'application/gzip',
'application/bzip2',
'application/x-bzip2',
'application/x-gzip',
'application/x-rar',
'application/x-z',
lib/Image/Magick/Safer.pm view on Meta::CPAN
# mime_type
if ( my $info = $magic->info_from_filename( $image ) ) {
$info->{mime_type} = ''
if ! defined $info->{mime_type};
if ( $info->{mime_type} =~ /No such file or directory/i ) {
return $info->{mime_type};
}
# if the mime_type is within the $Image::Magick::Safer::Unsafe
# hash or we can't figure it out then we assume it's not a real
# image and therefore could have an exploit within the file
if (
! $info->{mime_type}
|| $Image::Magick::Safer::Unsafe->{ $info->{mime_type} }
) {
return "$image is of type @{[ $info->{mime_type} ]}, potentially unsafe";
}
} else {
return "unable to establish mime_type for $image";
}
}
# all images *seem* ok, delegate to the real Image::Magick
return $self->SUPER::Read( @images );
}
# Image::Magick has a few aliases for the Read method
*Image::Magick::Safer::ReadImage = *Image::Magick::Safer::Read;
*Image::Magick::Safer::read = *Image::Magick::Safer::Read;
*Image::Magick::Safer::readimage = *Image::Magick::Safer::Read;
=head1 KNOWN BUGS
DOES NOT WORK with BSD 10.1 and 7.0.1 and i can't figure out why. If you can
figure out why then please submit a pull request. This is possibly some libmagic
weirdness going on.
=head1 SEE ALSO
L<Image::Magick> - the library this module wraps
L<https://www.imagemagick.org> - ImageMagick
L<https://imagetragick.com/> - ImageMagick exploits
L<http://permalink.gmane.org/gmane.comp.security.oss.general/19669> -
GraphicsMagick and ImageMagick popen() shell vulnerability via filename
=head1 AUTHOR
t/005_safer.t view on Meta::CPAN
#!perl
# mocking Image::Magick dependency here for testing as it may not be installed
# and it's an absolute swine to install so that's not going to work on
# cpantesters et al
BEGIN {
$INC{'Image/Magick.pm'} ||= "mocked";
};
package Image::Magick;
sub new { bless( {},shift ); };
1;
use strict;
use warnings;
use Test::More;
use FindBin qw/ $Bin /;
use File::Spec::Functions qw/ catdir /;
use File::Basename;
use Config;
use Image::Magick::Safer;
if (
$^O =~ /BSD/i
&& $Config{osvers} =~ /(10\.1|7\.0\.1)/
) {
plan skip_all => "Issues with BSD $1, see GH #2";
}
my $magick = Image::Magick::Safer->new;
# Image::Magick::Read could fail for other reasons, so we monkey patch it here
# to make sure it returns "success" (which in Image::Magick terms is void)
no warnings 'redefine';
no warnings 'once';
*Image::Magick::Read = sub ($;@) {};
# add SVG check to the defaults
$Image::Magick::Safer::Unsafe->{'image/svg+xml'} = 1;
note( "magic byte check" );
foreach my $file ( glob catdir( $Bin,"exploit","*" ) ) {
foreach my $method ( qw/ Read ReadImage read readimage / ) {
my $e = $magick->$method( $file );
like(
$e,
qr/potentially unsafe|unable to establish/,
( run in 1.834 second using v1.01-cache-2.11-cpan-beeb90c9504 )