CVE-2010-2761: Improper Control of Generation of Code ('Code Injection') (CWE-94)
value: The multipart_init function in (1) CGI.pm before 3.50 and (2) Simple.pm in CGI::Simple 1.112 and earlier uses a hardcoded value of the MIME boundary string in multipart/x-mixed-replace content, which allows remote attackers to inject arbitrary HTTP headers and conduct HTTP response splitting attacks via crafted input that contains this value, a different vulnerability than CVE-2010-3172.
CWE description: The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.
Published: 2010-12-06T20:12Z
Repository: https://github.com/AndyA/CGI--Simple
Language: Other
Files changed: lib/CGI/Simple.pm, t/050.simple.t, t/070.standard.t
Commit date: 2010-11-13 13:56:37 +0000
Commit message: Randomise multipart boundary. Thanks to Yamada Masahiro.

Diff: diff --git a/lib/CGI/Simple.pm b/lib/CGI/Simple.pm
index 0d562cb..e274189 100644
--- a/lib/CGI/Simple.pm
+++ b/lib/CGI/Simple.pm
@@ -1123,11 +1123,18 @@ sub redirect {
 
 sub multipart_init {
   my ( $self, @p ) = @_;
   use CGI::Simple::Util qw(rearrange);
   my ( $boundary, @other ) = rearrange( ['BOUNDARY'], @p );
-  $boundary = $boundary || '------- =_aaaaaaaaaa0';
+  if ( !$boundary ) {
+    $boundary = '------- =_';
+    my @chrs = ( '0' .. '9', 'A' .. 'Z', 'a' .. 'z' );
+    for ( 1 .. 17 ) {
+      $boundary .= $chrs[ rand( scalar @chrs ) ];
+    }
+  }
+
   my $CRLF = $self->crlf;    # get CRLF sequence
   my $warning
    = "WARNING: YOUR BROWSER DOESN'T SUPPORT THIS SERVER-PUSH TECHNOLOGY.";
   $self->{'.separator'}       = "$CRLF--$boundary$CRLF";
   $self->{'.final_separator'} = "$CRLF--$boundary--$CRLF$warning$CRLF";
diff --git a/t/050.simple.t b/t/050.simple.t
index 29ef191..6b517e8 100755
--- a/t/050.simple.t
+++ b/t/050.simple.t
@@ -943,14 +943,15 @@ is( $sv, $header, 'redirect() - nph, 1' );
 $q = new CGI::Simple;
 
 $sv = $q->multipart_init();
 like(
   $sv,
-  qr|Content-Type: multipart/x-mixed-replace;boundary="------- =_aaaaaaaaaa0"|,
+  qr|Content-Type: multipart/x-mixed-replace;boundary="------- =_[a-zA-Z0-9]{17}"|,
   'multipart_init(), 1'
 );
-like( $sv, qr/--------- =_aaaaaaaaaa0$CRLF/, 'multipart_init(), 2' );
+like( $sv, qr/--------- =_[a-zA-Z0-9]{17}$CRLF/,
+  'multipart_init(), 2' );
 $sv = $q->multipart_init( 'this_is_the_boundary' );
 like( $sv, qr/boundary="this_is_the_boundary"/, 'multipart_init(), 3' );
 $sv = $q->multipart_init( -boundary => 'this_is_another_boundary' );
 like(
   $sv,
diff --git a/t/070.standard.t b/t/070.standard.t
index 0a8579a..d3c018b 100755
--- a/t/070.standard.t
+++ b/t/070.standard.t
@@ -951,14 +951,16 @@ is( $sv, $header, 'redirect() - nph, 1' );
 restore_parameters();
 
 $sv = multipart_init();
 like(
   $sv,
-  qr|Content-Type: multipart/x-mixed-replace;boundary="------- =_aaaaaaaaaa0"|,
+  qr|Content-Type: multipart/x-mixed-replace;boundary="------- =_[a-zA-Z0-9]{17}"|,
   'multipart_init(), 1'
 );
-like( $sv, qr/--------- =_aaaaaaaaaa0$CRLF/, 'multipart_init(), 2' );
+
+like( $sv, qr/--------- =_[a-zA-Z0-9]{17}$CRLF/,
+  'multipart_init(), 2' );
 $sv = multipart_init( 'this_is_the_boundary' );
 like( $sv, qr/boundary="this_is_the_boundary"/, 'multipart_init(), 3' );
 $sv = multipart_init( -boundary => 'this_is_another_boundary' );
 like(
   $sv,

Vulnerable code:   $boundary = $boundary || '------- =_aaaaaaaaaa0';
  qr|Content-Type: multipart/x-mixed-replace;boundary="------- =_aaaaaaaaaa0"|,
like( $sv, qr/--------- =_aaaaaaaaaa0$CRLF/, 'multipart_init(), 2' );
  qr|Content-Type: multipart/x-mixed-replace;boundary="------- =_aaaaaaaaaa0"|,
like( $sv, qr/--------- =_aaaaaaaaaa0$CRLF/, 'multipart_init(), 2' );
Fixed code:   if ( !$boundary ) {
    $boundary = '------- =_';
    my @chrs = ( '0' .. '9', 'A' .. 'Z', 'a' .. 'z' );
    for ( 1 .. 17 ) {
      $boundary .= $chrs[ rand( scalar @chrs ) ];
    }
  }

  qr|Content-Type: multipart/x-mixed-replace;boundary="------- =_[a-zA-Z0-9]{17}"|,
like( $sv, qr/--------- =_[a-zA-Z0-9]{17}$CRLF/,
  'multipart_init(), 2' );
  qr|Content-Type: multipart/x-mixed-replace;boundary="------- =_[a-zA-Z0-9]{17}"|,

like( $sv, qr/--------- =_[a-zA-Z0-9]{17}$CRLF/,
  'multipart_init(), 2' );