As far as I understand it this has very little impact on the security of OpenSSL and can only be abused by someone with access to a signing system (and then you have more problems anyway).
What happens is that during the signing phase the certificate up the chain is read and checked, then during the generation this root certificate can be swapped out form underneath the process, and the generation proceeds as if nothing happened.
This means that the newly inserted root certificate is inserted into the chain of trust, while it was not explicitly added.
First off, at some point I became the person that would dig into a PoC for Ruby/OpenSSL/X509 bugs for hours. I've become a monster.
Secondly, I think that this is entirely wrong.
Standard disclaimer: I'm not a professional cryptographer. I have had to beat my head against ruby and the OpenSSL x509 bindings, so I know enough to probably make some very wrong statements.
That being said, the PoC is full of glaring errors. The ctx and cipher objects are created but never used. the Extension Factory is created and then entirely ignored because it's only used for the #issuer_certificate method. In addition, x509v3 extensions aren't used in any way during this PoC, so it has no reason to be there. And that's just the beginning.
I went through and picked apart the code in small bits to remove obfuscation and unnecessary actions while preserving the displayed output. Here's the massively cleaned up version:
#!/usr/bin/env ruby
require 'openssl'
key = OpenSSL::PKey::RSA.new(2048)
puts "Spoof must be in PEM format and saved as ca.pem"
raw = File.read "ca.pem"
ca_cert = OpenSSL::X509::Certificate.new raw
puts "before we sign the cert: #{ca_cert.verify(key)}"
ca_cert.sign(key, OpenSSL::Digest::SHA1.new)
puts "after we sign the cert: #{ca_cert.verify(key)}"
puts "Hijacked Certificate with chainloaded key saved @ #{ca_cert.serial}.pem"
printf "Verifying Keys Intergity: "
puts ca_cert.verify(key)
This removes all the variable duplications, doesn't write files because they have absolutely no impact on the behavior, and still displays the same output as the given PoC.
With a few final modifications it looks like this:
#!/usr/bin/env ruby
require 'openssl'
key = OpenSSL::PKey::RSA.new(2048)
ca_cert = OpenSSL::X509::Certificate.new(File.read("ca.pem"))
puts "before we sign the cert: #{ca_cert.verify(key)}"
ca_cert.sign(key, OpenSSL::Digest::SHA1.new)
puts "after we sign the cert: #{ca_cert.verify(key)}"
So what we've managed to demonstrate is that you can as a matter of fact sign SSL certificates with a private key.
Once again I may have _entirely_ missed the point on this and deleted a subtle line that had a major effect on the code. However with the sheer number of lines that were purely cargo culted for SSL implementations, I really think that this isn't an issue. I have an entire history of how I started with the original PoC and how I converted it to the above examples at https://github.com/adrienthebo/cve-2014-2734 ; please check it out if you think I made a mistake in my work.