From ec7069250b324c08a102e1a07e3d969144d3b476 Mon Sep 17 00:00:00 2001 From: Jacob Bachmeyer Date: Thu, 3 Nov 2022 17:37:07 -0500 Subject: [PATCH] Add structured exception for known Automake vulnerabilities --- gatekeeper.pl | 88 +++++++++++++++++++++++------------- testsuite/lib/gatekeeper.exp | 2 +- 2 files changed, 58 insertions(+), 32 deletions(-) diff --git a/gatekeeper.pl b/gatekeeper.pl index 84ccd60..d6676f6 100755 --- a/gatekeeper.pl +++ b/gatekeeper.pl @@ -581,6 +581,34 @@ END { return join("\n", map join(': ', @$_), @{(shift)->{trace}})."\n" } } +{ + package Local::Exception::known_vulnerability; + {our @ISA = qw(Local::Exception)} + + sub summary { return 'upload found vulnerable to ' + .join(', ', sort keys %{(shift)->{issues}}) } + + sub message { + my $self = shift; + + my $text = "file rejected because:\n"; + + # Because CVE-2012-3386 was not fixed until 1.11.6 / 1.12.2, we point + # people to that version instead of 1.11.1, which fixes + # CVE-2009-4029. Ward, 2012-07-20 + $text .= <<"END" if $self->{issues}{'CVE-2009-4029'}; +$self->{file} contains a vulnerable Makefile.in (CVE-2009-4029). + Regenerate it with automake 1.11.6 / 1.12.2 or newer. +END + $text .= <<"END" if $self->{issues}{'CVE-2012-3386'}; +$self->{file} contains a vulnerable Makefile.in (CVE-2012-3386). + Regenerate it with automake 1.11.6 / 1.12.2 or newer. +END + + return $text + } +} + { package Local::Exception::signature_from_future; {our @ISA = qw(Local::Exception)} @@ -2134,15 +2162,21 @@ sub check_replay { } } +=item automake_tests ( $upload_file ) + +Examine UPLOAD_FILE for known vulnerabilities that certain (now ancient) +versions of GNU Automake can introduce. Returns nothing, but throws an +exception if UPLOAD_FILE is found to be exploitable. + +=cut + sub automake_tests { my $upload_file = shift; - my $error_string = ''; - - return "Error: $upload_file not found\n\n" + die "file not found: $upload_file" unless -e $upload_file; - return "Error: $upload_file is unreadable\n\n" + die "file not readable: $upload_file" unless -r $upload_file; # Reject an upload tarball if it contains a Makefile.in vulnerable @@ -2157,58 +2191,52 @@ sub automake_tests { if DEBUG; my @tar_cmd = (qw(/bin/tar -tf), $upload_file); open TAR, '-|', @tar_cmd - or return 'Error: failed to run command: '.join(' ',@tar_cmd)."\n\n"; + or die 'failed to run command: '.join(' ',@tar_cmd).": $!"; my $found_makefile = 0; while () { $found_makefile++, last if m/Makefile.in/i } close TAR; # We don't care about errors here; the pipe can cause # non-zero exit codes when tar is unhappy that it's asked # to stop - return '' unless $found_makefile; + return unless $found_makefile; # If it does, check inside them - my $found_cve_2009_4029 = 0; - my $found_cve_2012_3386 = 0; + my %issues = (); ftp_syslog('debug',"DEBUG: found Makefile.in, " ."testing for CVE-2009-4029 and CVE-2012-3386") if DEBUG; @tar_cmd = (qw(/bin/tar --to-stdout -x -f), $upload_file, qw(Makefile.in --wildcards */Makefile.in)); open TAR, '-|', @tar_cmd - or return 'Error: failed to run command: '.join(' ',@tar_cmd)."\n\n"; + or die 'failed to run command: '.join(' ',@tar_cmd).": $!"; while () { - $found_cve_2009_4029 = 1 + $issues{'CVE-2009-4029'} = 1 if m/perm -777 -exec chmod a\+rwx|chmod 777 \$\(distdir\)/; - $found_cve_2012_3386 = 1 + $issues{'CVE-2012-3386'} = 1 if m/chmod a\+w \$\(distdir\)/; } close TAR; # We don't care about errors here; the pipe can cause # non-zero exit codes when tar is unhappy that it's asked # to stop - # Because CVE-2012-3386 was not fixed until 1.11.6 / 1.12.2, we point - # people to that version instead of 1.11.1, which fixes - # CVE-2009-4029. Ward, 2012-07-20 - $error_string .= "file rejected: $upload_file contains a vulnerable " - . "Makefile.in (CVE-2009-4029);\n" - . "Regenerate it with automake 1.11.6 / 1.12.2 or newer.\n\n" - if $found_cve_2009_4029; + throw known_vulnerability => file => $upload_file, issues => \%issues + if %issues; + } +} - $error_string .= "file rejected: $upload_file contains a vulnerable " - . "Makefile.in (CVE-2012-3386);\n" - . "Regenerate it with automake 1.11.6 / 1.12.2 or newer.\n\n" - if $found_cve_2012_3386; +=item check_vulnerabilities ( $upload_file ) - } +Examine UPLOAD_FILE for known vulnerabilities. This is only used for +issues related to packaging; notably an old issue in GNU Automake. - return $error_string; -} +Returns nothing on success and throws an exception if a known vulnerability +is found in UPLOAD_FILE. + +=cut sub check_vulnerabilities { my $upload_file = shift; - my $error_string = automake_tests($upload_file); - - return $error_string; + automake_tests($upload_file); } @@ -2263,9 +2291,7 @@ sub check_files { fatal("gpg verify of upload file ($header->{filename}) failed",1) unless $valid; - my $error_string = check_vulnerabilities($upload_file); - - fatal($error_string,1,'',3) if ($error_string ne ''); + check_vulnerabilities($upload_file); ftp_syslog('debug', "DEBUG: " ."tested negative for CVE-2009-4029 and CVE-2012-3386") if DEBUG; diff --git a/testsuite/lib/gatekeeper.exp b/testsuite/lib/gatekeeper.exp index ed8c955..7eefcac 100644 --- a/testsuite/lib/gatekeeper.exp +++ b/testsuite/lib/gatekeeper.exp @@ -822,7 +822,7 @@ proc analyze_log { base_dir name assess } { exp_continue } -re {^gatekeeper\[[0-9]+\]: \(Test\) \[EX\]\ - file rejected: [^()]+\((CVE-[0-9-]+)\)[^\r\n]+} { + upload found vulnerable to (CVE-[0-9-]+)[^\r\n]*} { # from check_vulnerabilities via check_files set A(exploit-check-fail,$expect_out(1,string)) 1 exp_continue -- 2.25.1