web interface: sort descriptions like the form fields in get_info, cert_search
[openxpki.git] / www.openxpki.org / trunk / htdocs / secadvs / CAN-2003-0960.txt
blob1bdf977f3dcc39fdeb7256dfe15de2c425423f2a
1 OpenCA Security Advisory [26 November 2003]
3 Vulnerabilities in signature validation
4 =======================================
6 Multiple flaws in OpenCA before version 0.9.1.4 could cause OpenCA to
7 use an incorrect certificate in the chain to determine the serial being
8 checked which could lead to certificates that are revoked or expired
9 being incorrectly accepted.
11 Chris Covell and Gottfried Scheckenbach performed tests with OpenCA and
12 CA hierarchies. They had problems to verify signatures with some
13 functions in OpenCA which test the signer's certificate.
15 Michael Bell of the OpenCA core team identified and fixed the problems
16 for OpenCA 0.9.1 and the CVS HEAD.
18 Vulnerabilities
19 -----------------
21 1. OpenCA has a library for common crypto operations - crypto-utils.lib.
22    This library includes a function to determine the serial of the
23    certificate which somebody used to create a PKCS#7 signature. The
24    function uses this serial to load and return the certificate. The
25    function used the interface of OpenCA::PKCS7 (the OpenCA PKCS#7
26    module) in a wrong way.
28 2. The crypto library crypto-utils.lib uses all certificates which were
29    included into the signature to create the X.509 object of the
30    signer's certificate. The result is a object which was created from
31    one of the certificates of the certificate chain. This means that
32    the result is haphazard.
34 3. OpenCA::PKCS7 includes a wrong regular expression to detect lines
35    which have nothing to do with the parsing of the certificate chain.
37 4. The serial in the certificate chain were parsed with a wrong regular
38    expression in OpenCA::PKCS7. Big letters like A, C, B, D, E and F
39    were ignored.
41 Who is affected?
42 ------------------
44 All version of OpenCA including 0.9.1.3. A security risk is present for
45 people who are using digital signatures to secure approved requests
46 or role based access control (RBAC).
48 Recommendations
49 -----------------
51 Upgrade to 0.9.1.4 and use newer snapshots than
52 openca-0.9-SNAP-20031125.tar.gz. You can fix the problem by yourself too
53 with the included patches. The original files which we used to create
54 the diffs are from OpenCA 0.9.1.3.
56 -----BEGIN PATCH-----
58 --- openca-0.9.1.3/src/modules/openca-pkcs7/PKCS7.pm    2002-09-10 16:42:02.000000000 +0200
59 +++ openca-0.9.1.4/src/modules/openca-pkcs7/PKCS7.pm    2003-11-26 15:54:08.000000000 +0100
60 @@ -69,7 +69,7 @@
62  our ($errno, $errval);
64 -($OpenCA::PKCS7::VERSION = '$Revision$' )=~ s/(?:^.*: (\d+))|(?:\s+\$$)/defined $1?"0\.9":""/eg;
65 +($OpenCA::PKCS7::VERSION = '$Revision$' )=~ s/(?:^.*: (\d+))|(?:\s+\$$)/defined $1?"0\.9":""/eg;
67  my %params = (
68          inFile => undef,
69 @@ -167,6 +167,8 @@
71         my ( $ret, $tmp );
73 +       return $self->{parsed} if ($self->{parsed});
75         $tmp = $self->{backend}->verify( SIGNATURE=>$self->{signature},
76                         DATA_FILE=>$self->{dataFile},
77                         CA_CERT=>$self->{caCert},
78 @@ -292,10 +294,10 @@
79                         ($self->{status}) = ( $line =~ /^\s*error:([^:]*):/ );
80                 }
82 -               next if( $line != /^depth/i );
83 +               next if( $line !~ /^depth/i );
85                 ( $currentDepth, $serial, $dn ) =
86 -                       ( $line =~ /depth:([\d]+) serial:([a-f\d]+) subject:(.*)/ );
87 +                       ( $line =~ /depth:([\d]+) serial:([a-fA-F\d]+) subject:(.*)/ );
88                 $ret->{$currentDepth}->{SERIAL} = hex ($serial) ;
89                 $ret->{$currentDepth}->{DN} = $dn;
91 --- openca-0.9.1.3/src/common/lib/functions/crypto-utils.lib    2002-12-22 13:08:19.000000000 +0100
92 +++ openca-0.9.1.4/src/common/lib/functions/crypto-utils.lib    2003-11-26 13:04:50.000000000 +0100
93 @@ -176,19 +176,36 @@
94                 return undef;
95         }
97 -       ## Get signer certificate from the pkcs7 structure
98 -       $sigCert = new OpenCA::X509 ( SHELL => $cryptoShell,
99 -                       DATA => $sig->getSigner()->{CERTIFICATE});
101 -       if( not $sigCert ) {
102 -               $errno  = 6103;
103 -               $errval = i18nGettext ("Signer's certificate is corrupt!\nOpenCA::X509 returns errorcode __ERRNO__ (__ERRVAL__).",
104 -                                      "__ERRNO__", $OpenCA::X509::errno,
105 -                                      "__ERRVAL__", $OpenCA::X509::errval);
106 -               return undef;
107 +       ## Get signer certificate chain from the pkcs7 structure
108 +       my @chain = split /-----END CERTIFICATE-----/,
109 +                   $sig->getSigner()->{CERTIFICATE};
110 +       for (my $i=0; $i < scalar @chain; $i++)
111 +       {
112 +               if (not $chain[$i])
113 +               {
114 +                       delete $chain[$i];
115 +                       next;
116 +               }
117 +               $chain[$i] .= "-----END CERTIFICATE-----";
118 +               $chain[$i] =~ s/^.*-----BEGIN CERTIFICATE-----/-----BEGIN CERTIFICATE-----/s;
119 +       }
120 +       $sigCert = undef;
121 +       for (my $i=0; $i < scalar @chain; $i++)
122 +       {
123 +               $sigCert = new OpenCA::X509 ( SHELL => $cryptoShell,
124 +                               DATA => $chain[$i]);
125 +               if( not $sigCert ) {
126 +                       $errno  = 6103;
127 +                       $errval = i18nGettext ("Signer's certificate is corrupt!\nOpenCA::X509 returns errorcode __ERRNO__ (__ERRVAL__).",
128 +                                              "__ERRNO__", $OpenCA::X509::errno,
129 +                                              "__ERRVAL__", $OpenCA::X509::errval);
130 +                       return undef;
131 +               }
132 +               last if ( $tmpCert->getSerial() eq $sigCert->getSerial() );
133 +               $sigCert = undef;
134         }
136 -       if( $tmpCert->getSerial() ne $sigCert->getSerial() ) {
137 +       if( not $sigCert ) {
138                 $errno  = 6104;
139                 $errval = gettext ("Signer's Certificate and DB's Certificate do not match");
140                 return undef;
141 @@ -281,19 +298,8 @@
142                 return undef;
143         }
145 -       my $sigCert = new OpenCA::X509 ( SHELL => $cryptoShell,
146 -                                  DATA => $sig->getSigner()->{CERTIFICATE});
148 -       if (not $sigCert) {
149 -               $errno  = 6302;
150 -               $errval = i18nGettext ("Cannot create X509-object from the certificate of the signer! OpenCA::X509 returns errorcode __ERRNO__ (__ERRVAL__).",
151 -                                      "__ERRNO__", $OpenCA::X509::errno,
152 -                                      "__ERRVAL__", $OpenCA::X509::errval);
153 -               return undef;
154 -       }
156         my $db_cert = $db->getItem( DATATYPE => 'CERTIFICATE',
157 -                               KEY => $sigCert->getSerial() );
158 +                               KEY => $sig->getSigner()->{SERIAL} );
160         if( not $db_cert ) {
161                 $errno  = 6303;
163 --- openca-0.9.1.3/src/common/lib/cmds/verifySignature  2003-03-31 15:45:19.000000000 +0200
164 +++ openca-0.9.1.4/src/common/lib/cmds/verifySignature  2003-11-26 13:04:34.000000000 +0100
165 @@ -11,7 +11,7 @@
166  ## Get the Configuration parameters ...
167  my ( $parsed, $lnk, $serLink, $sigInfo, $sigStatus, $signer, $signature);
168  my ( $baseDoc, $info, $sigCertStatus, $def, $dbStatus, $dbMessage);
169 -my ( $myCN, $myEmail, $mySerial, @sigCert, $tmpCert, $pCert );
170 +my ( $myCN, $myEmail, $mySerial, $tmpCert, $pCert );
172  ## Get Required Parameters from Configuration
173  my $baseDoc    = getRequired ('verifySignatureform');
174 @@ -53,10 +53,7 @@
175  $myDN = $signer->{DN};
176  $myDN =~ s/^\///; $myDN =~ s/\//<BR>/g;
178 -$sigCert = new OpenCA::X509 ( SHELL => $cryptoShell,
179 -                             DATA => $sign->getSigner()->{CERTIFICATE});
181 -$issuerDN = $sigCert->getParsed()->{ISSUER};
182 +$issuerDN = $sign->getParsed()->{CHAIN}->{1}->{DN};
183  $issuerDN =~ s/^\///; $issuerDN =~ s/[\/\,]/<BR>/g;
185  ## Check Signature Status
186 @@ -71,7 +68,7 @@
187                 $dbStatus = $errno;
188                 $sigStatus = "<FONT COLOR=\"Red\">".gettext("Unknown")."</FONT>";
190 -               $serLink = $sigCert->getSerial();
191 +               $serLink = $sign->getSigner()->{SERIAL};
192         } else {
193                 $sigMessage = gettext("Signature correctly verified");
194         }
195 @@ -96,11 +93,7 @@
196         $serLink    = $tmpCert->getSerial();
199 -if( $sigCert ) {
200 -       $pCert = $sigCert->getParsed();
201 -} elsif ( $tmpCert ) {
202 -       $pCert = $tmpCert->getParsed();
204 +$pCert = $tmpCert->getParsed();
206  ## View the Operator Used Certificate Data
207  $page = $query->subVar( $page, '@DN@',       ($myDN or "n/a" ) );
209 --- openca-0.9.1.3/src/common/lib/cmds/viewSignature    2002-12-10 16:18:15.000000000 +0100
210 +++ openca-0.9.1.4/src/common/lib/cmds/viewSignature    2003-11-26 13:04:34.000000000 +0100
211 @@ -11,7 +11,7 @@
212  ## Get the Configuration parameters ...
213  my ( $parsed, $lnk, $serLink, $sigInfo, $sigStatus, $signer, $signature);
214  my ( $baseDoc, $info, $sigCertStatus, $def, $dbStatus, $dbMessage);
215 -my ( $myCN, $myEmail, $mySerial, @sigCert, $tmpCert, $pCert );
216 +my ( $myCN, $myEmail, $mySerial, $tmpCert, $pCert );
218  my $dataType   = $query->param('dataType' );
219  my $key        = $query->param('key');
220 @@ -54,9 +54,6 @@
221                 name=>"EMAIL", value=>$signer->{DN_HASH}->{EMAILADDRESS}[0]} );
222  $myEmail = $lnk->a({-href=>$lnk->self_url()}, $signer->{DN_HASH}->{EMAILADDRESS}[0]);
224 -$sigCert = new OpenCA::X509 ( SHELL => $cryptoShell,
225 -                             DATA => $signature->getSigner()->{CERTIFICATE});
227  ## Check Signature Status
228  if( not libCheckSignature( SIGNATURE=>$signature ) ) {
229         $sigStatus = "<FONT COLOR=\"Red\">".gettext("Error")."</FONT>";
230 @@ -105,7 +102,7 @@
231         $serLink = $lnk->a({-href=>$lnk->self_url()},
232                         $tmpCert->getSerial() );
234 -       $decSerLink = "( " . hex( $sigCert->getSerial() ) . " )";
235 +       $decSerLink = "( " . hex( $tmpCert->getSerial() ) . " )";
237      $lnk = new CGI({cmd      => "search",
238                      dataType => "CERTIFICATE",
239 @@ -114,11 +111,7 @@
240      $myEmail = $lnk->a({-href=>$lnk->self_url()}, $tmpCert->getParsed()->{EMAILADDRESS});
243 -if( $sigCert ) {
244 -       $pCert = $sigCert->getParsed();
245 -} elsif ( $tmpCert ) {
246 -       $pCert = $tmpCert->getParsed();
248 +$pCert = $tmpCert->getParsed();
250  ## View the Operator Used Certificate Data
251  $page = $query->subVar( $page, '@CN@',       ($myCN or "n/a" ) );
252 -----END PATCH-----
254 References
255 ------------
257 The Common Vulnerabilities and Exposures project (cve.mitre.org) has
258 assigned the name CAN-2003-0960 to this issue.
260 http://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2003-0960
262 URL for this Security Advisory:
263 http://www.openca.org/news/CAN-2003-0960.txt