CVE-2015-3406 (published 2019-11-29T21:15Z)

The PGP signature parsing in Module::Signature before 0.74 allows remote attackers to cause the unsigned portion of a SIGNATURE file to be treated as the signed portion via unspecified vectors.

Severity: MEDIUM
CVSS v2 base score: 6.4 (AV:N/AC:L/Au:N/C:N/I:P/A:P)
CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N)

Weakness information:
cwe_id: CWE-681
cwe_name: Incorrect Conversion between Numeric Types
description: When converting from one data type to another, such as long to integer, data can be omitted or translated in a way that produces unexpected values. If the resulting values are used in a sensitive context, then dangerous behaviors may occur.
extended_description: 
            
            
            
         
         

Fix information:
repo_url: https://github.com/audreyt/module-signature
commit_details: repo_url: https://github.com/audreyt/module-signature
author: Audrey Tang
author_date: 2015-04-05 16:05:20+08:00
msg: * Fix issues reported by John Lightsey
repository: repo_url: https://github.com/audreyt/module-signature
repo_name: audreyt/module-signature
description: Module signature file manipulation
repo_language: Perl
owner: audreyt
file_changes: filename: Makefile.PL
change_type: ModificationType.MODIFY
diff: @@ -10,6 +10,7 @@ readme_from     'lib/Module/Signature.pm';
 repository      'http://github.com/audreyt/module-signature';
 install_script  'script/cpansign';
 build_requires  'Test::More', 0, 'IPC::Run', 0;
+requires        'File::Temp';
 
 # On Win32 (excluding cygwin) we know that IO::Socket::INET,
 # which is needed for keyserver stuff, doesn't work. In fact

programming_language: Perl
filename: README
change_type: ModificationType.MODIFY
diff: @@ -248,7 +248,7 @@ SEE ALSO
     Dist::Zilla::Plugin::Signature
 
 AUTHORS
-    唐鳳 <cpan@audreyt.org>
+    Audrey Tang <cpan@audreyt.org>
 
 CC0 1.0 Universal
     To the extent possible under law, 唐鳳 has waived all copyright and

programming_language: Perl
filename: Signature.pm
change_type: ModificationType.MODIFY
diff: @@ -1,5 +1,5 @@
 package Module::Signature;
-$Module::Signature::VERSION = '0.73_01';
+$Module::Signature::VERSION = '0.74';
 
 use 5.005;
 use strict;
@@ -58,6 +58,8 @@ sub _cipher_map {
     my @lines = split /\015?\012/, $sigtext;
     my %map;
     for my $line (@lines) {
+        last if $line eq '-----BEGIN PGP SIGNATURE-----';
+        next if $line =~ /^---/ .. $line eq '';
         my($cipher,$digest,$file) = split " ", $line, 3;
         return unless defined $file;
         $map{$file} = [$cipher, $digest];
@@ -66,7 +68,7 @@ sub _cipher_map {
 }
 
 sub verify {
-    my %args = ( skip => 1, @_ );
+    my %args = ( @_ );
     my $rv;
 
     (-r $SIGNATURE) or do {
@@ -179,6 +181,11 @@ sub _fullcheck {
         ($mani, $file) = ExtUtils::Manifest::fullcheck();
     }
     else {
+        my $_maniskip = &ExtUtils::Manifest::maniskip;
+        local *ExtUtils::Manifest::maniskip = sub { sub {
+            return unless $skip;
+            return $_maniskip->(@_);
+        } };
         ($mani, $file) = ExtUtils::Manifest::fullcheck();
     }
 
@@ -238,6 +245,11 @@ sub _verify_gpg {
 
     my $keyserver = _keyserver($version);
 
+    require File::Temp;
+    my $fh = File::Temp->new();
+    print $fh $sigtext;
+    close $fh;
+
     my $gpg = _which_gpg();
     my @quiet = $Verbose ? () : qw(-q --logger-fd=1);
     my @cmd = (
@@ -246,7 +258,7 @@ sub _verify_gpg {
             ($AutoKeyRetrieve and $version ge '1.0.7')
                 ? '--keyserver-options=auto-key-retrieve'
                 : ()
-        ) : ()), $SIGNATURE
+        ) : ()), $fh->filename
     );
 
     my $output = '';
@@ -258,6 +270,7 @@ sub _verify_gpg {
         my $cmd = join ' ', @cmd;
         $output = `$cmd`;
     }
+    unlink $fh->filename;
 
     if( $? ) {
         print STDERR $output;
@@ -286,7 +299,7 @@ sub _verify_crypt_openpgp {
     my $pgp = Crypt::OpenPGP->new(
         ($KeyServer) ? ( KeyServer => $KeyServer, AutoKeyRetrieve => $AutoKeyRetrieve ) : (),
     );
-    my $rv = $pgp->handle( Filename => $SIGNATURE )
+    my $rv = $pgp->handle( Data => $sigtext )
         or die $pgp->errstr;
 
     return SIGNATURE_BAD if (!$rv->{Validity} and $AutoKeyRetrieve);
@@ -309,32 +322,35 @@ sub _read_sigfile {
     my $well_formed;
 
     local *D;
-    open D, $sigfile or die "Could not open $sigfile: $!";
+    open D, "< $sigfile" or die "Could not open $sigfile: $!";
 
     if ($] >= 5.006 and <D> =~ /\r/) {
         close D;
-        open D, $sigfile or die "Could not open $sigfile: $!";
+        open D, '<', $sigfile or die "Could not open $sigfile: $!";
         binmode D, ':crlf';
     } else {
         close D;
-        open D, $sigfile or die "Could not open $sigfile: $!";
+        open D, "< $sigfile" or die "Could not open $sigfile: $!";
     }
 
+    my $begin = "-----BEGIN PGP SIGNED MESSAGE-----\n";
+    my $end = "-----END PGP SIGNATURE-----\n";
     while (<D>) {
-        next if (1 .. /^-----BEGIN PGP SIGNED MESSAGE-----/);
-        last if /^-----BEGIN PGP SIGNATURE/;
-
+        next if (1 .. ($_ eq $begin));
         $signature .= $_;
+        return "$begin$signature" if $_ eq $end;
     }
 
-    return ((split(/\n+/, $signature, 2))[1]);
+    return;
 }
 
 sub _compare {
     my ($str1, $str2, $ok) = @_;
 
     # normalize all linebreaks
+    $str1 =~ s/^-----BEGIN PGP SIGNED MESSAGE-----\n(?:.+\n)*\n//;
     $str1 =~ s/[^\S ]+/\n/g; $str2 =~ s/[^\S ]+/\n/g;
+    $str1 =~ s/-----BEGIN PGP SIGNATURE-----\n(?:.+\n)*$//;
 
     return $ok if $str1 eq $str2;
 
@@ -345,7 +361,7 @@ sub _compare {
     }
     else {
         local (*D, *S);
-        open S, $SIGNATURE or die "Could not open $SIGNATURE: $!";
+        open S, "< $SIGNATURE" or die "Could not open $SIGNATURE: $!";
         open D, "| diff -u $SIGNATURE -" or (warn "Could not call diff: $!", return SIGNATURE_MISMATCH);
         while (<S>) {
             print D $_ if (1 .. /^-----BEGIN PGP SIGNED MESSAGE-----/);
@@ -412,9 +428,9 @@ sub _sign_gpg {
         die "Cannot find $sigfile.tmp, signing aborted.\n";
     };
 
-    open D, "$sigfile.tmp" or die "Cannot open $sigfile.tmp: $!";
+    open D, "< $sigfile.tmp" or die "Cannot open $sigfile.tmp: $!";
 
-    open S, ">$sigfile" or do {
+    open S, "> $sigfile" or do {
         unlink "$sigfile.tmp";
         die "Could not write to $sigfile: $!";
     };
@@ -597,7 +613,7 @@ sub _mkdigest_files {
         }
         else {
             local *F;
-            open F, $file or die "Cannot open $file for reading: $!";
+            open F, "< $file" or die "Cannot open $file for reading: $!";
             if (-B $file) {
                 binmode(F);
                 $obj->addfile(*F);
@@ -949,7 +965,7 @@ L<Dist::Zilla::Plugin::Signature>
 
 =head1 AUTHORS
 
-唐鳳 E<lt>cpan@audreyt.orgE<gt>
+Audrey Tang E<lt>cpan@audreyt.orgE<gt>
 
 =head1 CC0 1.0 Universal
 

programming_language: Perl