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.
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
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).
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.
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
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;
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},
79 ($self->{status}) = ( $line =~ /^\s*error:([^:]*):/ );
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
97 - ## Get signer certificate from the pkcs7 structure
98 - $sigCert = new OpenCA::X509 ( SHELL => $cryptoShell,
99 - DATA => $sig->getSigner()->{CERTIFICATE});
101 - if( not $sigCert ) {
103 - $errval = i18nGettext ("Signer's certificate is corrupt!\nOpenCA::X509 returns errorcode __ERRNO__ (__ERRVAL__).",
104 - "__ERRNO__", $OpenCA::X509::errno,
105 - "__ERRVAL__", $OpenCA::X509::errval);
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++)
112 + if (not $chain[$i])
117 + $chain[$i] .= "-----END CERTIFICATE-----";
118 + $chain[$i] =~ s/^.*-----BEGIN CERTIFICATE-----/-----BEGIN CERTIFICATE-----/s;
121 + for (my $i=0; $i < scalar @chain; $i++)
123 + $sigCert = new OpenCA::X509 ( SHELL => $cryptoShell,
124 + DATA => $chain[$i]);
125 + if( not $sigCert ) {
127 + $errval = i18nGettext ("Signer's certificate is corrupt!\nOpenCA::X509 returns errorcode __ERRNO__ (__ERRVAL__).",
128 + "__ERRNO__", $OpenCA::X509::errno,
129 + "__ERRVAL__", $OpenCA::X509::errval);
132 + last if ( $tmpCert->getSerial() eq $sigCert->getSerial() );
136 - if( $tmpCert->getSerial() ne $sigCert->getSerial() ) {
137 + if( not $sigCert ) {
139 $errval = gettext ("Signer's Certificate and DB's Certificate do not match");
145 - my $sigCert = new OpenCA::X509 ( SHELL => $cryptoShell,
146 - DATA => $sig->getSigner()->{CERTIFICATE});
148 - if (not $sigCert) {
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);
156 my $db_cert = $db->getItem( DATATYPE => 'CERTIFICATE',
157 - KEY => $sigCert->getSerial() );
158 + KEY => $sig->getSigner()->{SERIAL} );
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
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');
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
188 $sigStatus = "<FONT COLOR=\"Red\">".gettext("Unknown")."</FONT>";
190 - $serLink = $sigCert->getSerial();
191 + $serLink = $sign->getSigner()->{SERIAL};
193 $sigMessage = gettext("Signature correctly verified");
196 $serLink = $tmpCert->getSerial();
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
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');
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>";
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",
240 $myEmail = $lnk->a({-href=>$lnk->self_url()}, $tmpCert->getParsed()->{EMAILADDRESS});
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" ) );
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