Puppet: System Administration Automated

Support

Ticket #896 (closed defect: fixed)

Opened 1 year ago

Last modified 1 year ago

Need subjectAltName in Server Cert; newer Ruby SSL check barfs if hostname on SSL connection != CN on cert

Reported by: whaymand Assigned to: community
Priority: high Milestone: misspiggy
Component: library Version:
Severity: normal Keywords:
Cc: Triage Stage: Accepted
Attached Patches: Code Complexity: Unknown

Description

See thread http://mail.madstop.com/pipermail/puppet-users/2007-October/004692.html

Ruby 1.8.6.110-3.fc7 has the new "fix", 1.8.6.36-3.fc7 didn't. This is sure to hit RHEL and other distros soon.

David Lutterkort wrote: It seems to all boil down to bz 313691 [1], which in turn addresses CVE 2007-5162 [2], which makes me think that this problem will hit users of other distros sooner or later.

The bug there is that ruby didn't verify that the common name on the cert matched the host name to which the SSL connection was established. In other words, you only have trouble if the CN on the cert is not the name of the host the client connects to - often the case when your clients connect to host 'puppet' and that is a CNAME to another host.

If my reading of post_connection_check in /usr/lib/ruby/1.8/openssl/ssl.rb is correct, it should be possible to fix this by adding 'subjectAltName' extensions to the server cert. Changes are definitely needed in the way that the puppetmaster generates the server cert.

---

Since I use CNAMEs extensively, I'm sure to hit this soon. In fact, I'd rather be able to subsequently add these alt names at a later date, but I suspect SSL won't allow me to do this.

Attachments

puppet-fqdn-cname-server.patch (0.5 kB) - added by zothar on 11/13/07 21:51:13.
Make the default server name be puppet.<"domain" from Facter>
ca.patch (365 bytes) - added by whaymand_home on 11/14/07 21:59:41.
defaults.patch (0.6 kB) - added by whaymand_home on 11/14/07 21:59:54.
sslcertificates.patch (1.4 kB) - added by whaymand_home on 11/14/07 22:00:12.
fix-896-ssl_verify_fix.patch (1.2 kB) - added by mccune on 11/20/07 21:41:34.
FOR 0.23.2 - Small patch to disable the post connection check in recent ruby versions.
defaults.udiff (0.9 kB) - added by whaymand_home on 11/20/07 23:07:22.
Additional patch for more wildcards in certdnsnames
sslcertificates.rb.udiff (0.6 kB) - added by whaymand_home on 12/03/07 12:02:58.
Additional cumulative patch to correct bug - see #942

Change History

11/13/07 21:51:13 changed by zothar

  • attachment puppet-fqdn-cname-server.patch added.

Make the default server name be puppet.<"domain" from Facter>

11/13/07 21:53:28 changed by zothar

  • patch changed from None to Code.

I've attached a patch that is my workaround for the problem. It works if the installation was previously using the default "puppet" server name and it's CNAME friendly.

11/14/07 08:41:09 changed by whaymand_home

zothar: Sorry, this will only work in a subset of scenarious :-( We really do need the subjectAltName stuff added. I'll see what I can do. Derek.

11/14/07 21:59:41 changed by whaymand_home

  • attachment ca.patch added.

11/14/07 21:59:54 changed by whaymand_home

  • attachment defaults.patch added.

11/14/07 22:00:12 changed by whaymand_home

  • attachment sslcertificates.patch added.

11/14/07 22:05:02 changed by whaymand_home

Here are a trio of patches ({ca,defaults,sslcertificates}.patch) which add a new configuration parameter, "certdnsnames". This defaults to *

It is a colon-separated list of the DNS names to be recorded in the subjectAltName of the server certificate generated for the Puppet Master server. Once your latest 'n' greatest Ruby bothers to check this (:-) the client will only accept the server's cert when the DNS name it connects to matches one of the certdnsnames. Wildcards are permitted as per <nop>OpenSSL's usual fun and games.

I haven't added IP: or any of the other forms serverAltName supports.

Cheers, Derek

11/19/07 18:10:50 changed by whaymand

This has hit RHEL5.1 - ruby-1.8.5-5el5_1.1 has the stricter checking as per bz 313691 but RHEL5.0 - ruby-1.8.5-5el5 does not.

11/19/07 22:08:45 changed by luke

  • priority changed from normal to high.
  • milestone set to misspiggy.

11/19/07 22:48:40 changed by luke

  • status changed from new to closed.
  • resolution set to fixed.

Patches applied in [4bd7b6f69edfc984d153a23872a3ac6e123b5765]. Note that I had to fix all of your indentation to match our current coding practice.

11/20/07 13:18:31 changed by mccune

Just as an FYI, I think the best way to patch this problem is to check for, and then turn off the new, default behavior of Ruby's SSL checking.

For example, in ruby 1.8.5, according to http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=13502

the new checks may be overridden with:

Net::HTTP#enable_post_connection_check=(false)

We're already overriding some methods in Net::HTTP in client.rb in 0.23.2.

11/20/07 17:17:40 changed by mccune

More information about the security change is available at: http://www.isecpartners.com/advisories/2007-006-rubyssl.txt

Also, DerekW mentioned in IRC that this issue really only affects the puppetmaster server certificate, whose certificate must match the requrest string of the puppetd client connection.

11/20/07 19:31:09 changed by mccune

And just as another comment, requests to the mailing list or IRC should probably be pointed at RubySSL-2007-006

11/20/07 21:27:30 changed by luke

  • status changed from closed to reopened.
  • resolution deleted.

11/20/07 21:41:34 changed by mccune

  • attachment fix-896-ssl_verify_fix.patch added.

FOR 0.23.2 - Small patch to disable the post connection check in recent ruby versions.

11/20/07 21:53:19 changed by mccune

I've published a small, untested patch. I'll reply back once I've had a chance to actually test this patch, and write an additional test-case for the situation.

The branch is named 'pending/fix-896' and is located at: http://northstarlabs.net/git/puppet

11/20/07 23:07:22 changed by whaymand_home

  • attachment defaults.udiff added.

Additional patch for more wildcards in certdnsnames

11/20/07 23:09:26 changed by whaymand_home

New defaults.rb patch attached. This is against a git checkout of 20/11/07, i.e. it's cumulative and doesn't replace what's already submitted/checked in.

You now get *,*.*,*.*.*,*.*.*.*,*.*.*.*.*,*.*.*.*.*.* as your default certdnsnames, good enough to match most people domains.

(follow-up: ↓ 15 ) 11/23/07 22:49:54 changed by luke

I've applied Derek's patch but cannot reach Jeff's repo, apparently.

11/24/07 03:30:32 changed by luke

  • stage changed from Unreviewed to Accepted.

(in reply to: ↑ 13 ) 11/25/07 02:36:23 changed by mccune

Replying to luke:

I've applied Derek's patch but cannot reach Jeff's repo, apparently.

My patch to completely disable the new behavior is now published as [36c947ecae1b0082cf535dc691891b6cd7bf2c51] in the branch refs/heads/pending/fix-896r2

Hopefully that works.

I've also added a conditional to check if Net::HTTP#enable_post_connection_check needs to be defined or not. This should provide maximum compatibility with future and past versions of Ruby.

11/25/07 03:31:45 changed by mccune

For those being bitten by this bug currently, I've backported this patch to 0.23.2.

To apply the patch:

# Get the current code
git clone git://reductivelabs.com/puppet/ puppet.git
cd puppet.git

# Stage version 0.23.2
git checkout 0.23.2

# Create a new local branch for the backported patch.
git checkout -b 0.23.2p1

# Fetch, merge, and commit the patch fix.
git remote add mccune http://northstarlabs.net/git/puppet
git pull mccune backports/0.23.2/fix-896

To see the changes made:

git diff HEAD^

Hope this helps, as this seems to be impacting a lot of people.

This patched client will need to be installed on any machines with a "fixed" (recent) ruby.

(follow-up: ↓ 18 ) 11/26/07 02:32:08 changed by semantico

I've tested all these patches and none worked with dlutters rpm and the latest rhel4 ruby libs

the ruby lib ...

        if @socket.socket.context.verify_mode != OpenSSL::SSL::VERIFY_NONE
          @socket.socket.post_connection_check(@address)
        end

/network/xmlrpc/client.rb

@http.verify_mode = OpenSSL::SSL::VERIFY_NONE

(in reply to: ↑ 17 ; follow-up: ↓ 19 ) 11/26/07 03:38:14 changed by anarcat

Replying to semantico:

I've tested all these patches and none worked with dlutters rpm and the latest rhel4 ruby libs the ruby lib ... {{{ if @socket.socket.context.verify_mode != OpenSSL::SSL::VERIFY_NONE @socket.socket.post_connection_check(@address) end }}} /network/xmlrpc/client.rb {{{ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE }}}

Am I right in understanding that this basically disables OpenSSL's verification, thus reverting puppet to the behavior Ruby was having before the security patch?

(in reply to: ↑ 18 ) 11/26/07 03:46:29 changed by micah

Replying to anarcat:

Replying to semantico:

the ruby lib ... {{{ if @socket.socket.context.verify_mode != OpenSSL::SSL::VERIFY_NONE @socket.socket.post_connection_check(@address) end }}} /network/xmlrpc/client.rb {{{ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE }}}

Am I right in understanding that this basically disables OpenSSL's verification, thus reverting puppet to the behavior Ruby was having before the security patch?

Yes I believe so, but the reason that semantico is doing this is because semantico said:

I've tested all these patches and none worked with dlutters rpm and the latest rhel4 ruby libs

Which to me means that the patches didn't work for semantico, so a crude work-around is to disable things altogether.

11/26/07 20:48:40 changed by mccune

Argh, I'm almost certain my patch (just disabling the post_connection_check) is correct, but I'll triple test it right now.

I agree with micah, it seems semantico is just disabling SSL verification altogether, which will obviously "work".

semantico, could you please verify that you've tested *my* patch, and *only* my patch against 0.23.2 ? There's a back-ported version available, and I'll post a patch file if you don't have access to git.

Perhaps this should be two tickets to save confusion. I believe my patches may be mutually exclusive with whaymand_home and zothar's patches.

-mccune

11/27/07 00:12:05 changed by mccune

OK, so I just extensively tested this problem and my solution, and I believe I've wrapped my head around the issue completely and worked out a solution that works for everyone.

I believe we should disregard all patches except mine. (Sorry everyone else).

Here's my motivation:

First, the ruby maintainers did not actually change the behavior of ruby. They merely added the post_connection_check, which issues a warning if the certificate CN does not match the request string passed to Net::HTTP.

Second, it is the vendors who are taking the extra security step and setting @enable_post_connection_check = true in net/http.rb. Ruby maintainers default to false, which is the behavior puppet users have expected until now.

Third, all other submitted patches appear to drastically change how certificates are generated, which is not necessary if @enable_post_connection_check = false

Finally, the patch I've submitted simply "undoes" what vendors are doing. That is, the patch rolls back to the behavior of allowing the SSL connection to continue, with a warning, if the server certificate's subject field contains a CN string other than what is specified to the --server option of puppetd.

In addition, not all vendors are setting @enable_post_connection_check = true, which means any change in behavior to the way certificates are generated is not necessary when used with a ruby package not setting this condition true.

If anyone else would like to verify my efforts, the trick is to start with http://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.6-p111.tar.gz or http://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.5-p114.tar.gz and make sure to set @enable_post_connection_check = true instead of false in lib/ruby/1.8/net/http.rb, in order to mimic the behavior of the security conscience vendors.

Phew. So, in summary:

for HEAD see: http://northstarlabs.net/cgi-bin/gitweb.cgi?p=puppet;a=commitdiff;h=36c947ecae1b0082cf535dc691891b6cd7bf2c51

for 0.23.2 see: http://northstarlabs.net/cgi-bin/gitweb.cgi?p=puppet;a=commitdiff;h=c0e2ecb71d238740a4d831d83722c70ad498219a

Cheers, -Jeff

(follow-up: ↓ 23 ) 11/27/07 18:12:34 changed by whaymand

Jeff, your patch works perfectly (tested the backported 0.23 version from your website) with current RH Ruby from 5.0 and 5.1, and also 4.4 (which hey, doesn't even need it). The only downer is that is requires a new Puppet client package. With subjectAltName you only require a new server package (or a one-off hack to mint some certs). Less intrusive. Either way, we (Barcap) have to run with patches for the short term anyway so I have no personal or professional vested interest in my patch above Jeff's. It's more what the community wants or what the overall architectural plan is that matters.

What really does matters is that this is fixed, one way or another in 0.24 :-)

Regards, Derek

(in reply to: ↑ 22 ; follow-up: ↓ 24 ) 11/27/07 20:15:31 changed by mccune

Replying to whaymand:

Jeff, your patch works perfectly (tested the backported 0.23 version from your website) with current RH Ruby from 5.0 and 5.1, and also 4.4 (which hey, doesn't even need it).

Thanks for verifying this.

The only downer is that is requires a new Puppet client package.

Correct.

With subjectAltName you only require a new server package (or a one-off hack to mint some certs). Less intrusive.

Ah, to be a bit more clear, if you do the one-off hack to mint a new SSL certificate for the server, no patching is necessary whatsoever. This is actually the solution route I've taken at my site.

I'm perfectly happy to document a fairly straightforward way to mint a new certificate manually, using the Makefile and openssl.cnf from http://sial.org/ similar to what I did with Multiple Certificate Authorities. If anyone is interested in that HOWTO, just let me know.

What really does matters is that this is fixed, one way or another in 0.24 :-)

Agreed. It's looking like it will be, so I think we're in good shape.

(in reply to: ↑ 23 ) 11/27/07 20:26:19 changed by anarcat

Replying to mccune:

Ah, to be a bit more clear, if you do the one-off hack to mint a new SSL certificate for the server, no patching is necessary whatsoever. This is actually the solution route I've taken at my site. I'm perfectly happy to document a fairly straightforward way to mint a new certificate manually, using the Makefile and openssl.cnf from http://sial.org/ similar to what I did with Multiple Certificate Authorities. If anyone is interested in that HOWTO, just let me know.

I think this would be very important for people that are about to do their Ruby upgrade on puppet installations. As far as I know, the place for that is RubySSL-2007-006 right now, but from what micah said on IRC, the instructions there are not working.

I'm also worried about some patches here that disable SSL verifications, does your solution disable the verification too?

Shouldn't the proper solution be that the puppetmaster generate the right certificate in the first place?

Disclaimer: I'm having a hard time figuring out exactly what the problem is around this issue, so take my comments with a proverbial grain of salt.

(follow-up: ↓ 26 ) 11/28/07 00:33:15 changed by luke

  • status changed from reopened to closed.
  • resolution set to fixed.

mccune's patch has been applied and pushed.

Does anyone think this should be an option for the more anal security folks?

(in reply to: ↑ 25 ) 11/28/07 01:38:15 changed by mpalmer

Replying to luke:

Does anyone think this should be an option for the more anal security folks?

Possibly, but I'd leave it up to the anal security folks to implement it if they're worried about it. For me, hostname validation is only important when signatures from a CA are trivial for anyone to get; in Puppet's security model, it isn't important that the CN matches the hostname because the very presence of a signature from the CA says "yes, this is host is OK".

11/28/07 03:06:06 changed by luke

Cool; I'll leave it at that, then.

(follow-up: ↓ 30 ) 11/28/07 16:47:02 changed by lutter

I think the last patch (disabling hostname checking altogether) is a horrible idea - sorry for being so blunt. It means that (a) puppet changes the behavior of ruby's ssl connections in a subtle way that's almost impossible to find for the average user and (b) makes broken behavior that is serious enough to have a CVE filed for it the default with no way to turn it off.

I also don't understand why that change is needed; there are several perfectly good ways to make puppet work with the fixed ruby SSL implementation, at least one of which only requires server-side changes.

11/28/07 19:40:02 changed by lutter

  • status changed from closed to reopened.
  • resolution deleted.

On a more constructive note, and after talking to Luke, the security and usability issues should be addressed in the following way:

  1. make setting @enable_post_connection_check optional, and have the host name check enabled by default
  2. default the subjectAltName on server certificates to the server's canonical name and to 'puppet' (not to everything as is the case with the current patches)

Also, create a Wiki page that explains to users what they can do if SSL checks get in their way (but that's not part of the ticket, and I volunteered to do that)

(in reply to: ↑ 28 ) 11/29/07 13:51:47 changed by mccune

Replying to lutter:

I think the last patch (disabling hostname checking altogether) is a horrible idea - sorry for being so blunt.

No need to apologize, at least to me. I like blunt.

After considering it more, I think you're completely right. Were I not the one who disabled the SSL post connection check, I would be surprised to find out that it wasn't happening if I a new puppet user.

I'll augment the patch to make a configurable option, with the default behavior following that of Ruby's default behavior.

I hope to have this done by the end of the weekend, if not this afternoon.

11/29/07 15:45:03 changed by mccune

I've patched this to be configurable. Please see refs/heads/pending/fix-896r3 of http://northstarlabs.net/git/puppet

As a reference, here's the commitdiff:

http://northstarlabs.net/cgi-bin/gitweb.cgi?p=puppet;a=commitdiff;h=f94d6d3394dd0fa9ecf06b727cb7234fede7c960

Commit is [f94d6d3394dd0fa9ecf06b727cb7234fede7c960]

A second commit, [24cacdb] Fixes the test case for enable_post_connection_check to match the configuration.

11/29/07 17:11:47 changed by luke

This fix causes failures in spec/unit/network/xmlrpc/client.rb; I've added new tests to that file, since it's easier for me to think in rspec mode now.

(follow-up: ↓ 34 ) 11/29/07 19:05:33 changed by hyclak

Don't forget us EL4-ers!

Jeff's patch won't work, since redhat didn't backport the ability to turn off the SSL checks.

I attempted to follow the suggestion in RubySSL-2007-006 and re-created the certificate with server = puppet in my [puppetmasterd] config:

-----END CERTIFICATE-----
subject=/CN=puppet
issuer=/CN=netserv.math.ohiou.edu

But now, I get the following:

[hyclak@euclid puppet]$ sudo /usr/sbin/puppetd --test --server=puppet
notice: Ignoring cache
err: Could not retrieve configuration: Certificates were not trusted: data too large for modulus
warning: Not using cache on failed configuration

This has been seen before in #223, but I only have one puppetmaster running, and if I kill it, it really does die.

(in reply to: ↑ 33 ) 11/29/07 20:59:30 changed by hyclak

Replying to hyclak:

Don't forget us EL4-ers! Jeff's patch won't work, since redhat didn't backport the ability to turn off the SSL checks. I attempted to follow the suggestion in RubySSL-2007-006 and re-created the certificate with server = puppet in my [puppetmasterd] config: {{{ -----END CERTIFICATE----- subject=/CN=puppet issuer=/CN=netserv.math.ohiou.edu }}} But now, I get the following: {{{ [hyclak@euclid puppet]$ sudo /usr/sbin/puppetd --test --server=puppet notice: Ignoring cache err: Could not retrieve configuration: Certificates were not trusted: data too large for modulus warning: Not using cache on failed configuration }}} This has been seen before in #223, but I only have one puppetmaster running, and if I kill it, it really does die.

You can probably disregard this problem - I removed all traces of puppet from all clients and servers, reinstalled, and now things seem to be working fine.

11/29/07 23:21:32 changed by mccune

OK, I've updated the test cases. The problem is that I moved @http.enable_post_connection_check=true out of the cert_setup method and into the http_instance method. This broke the original test case.

I've removed the test, and agumented the spec tests, but I have no idea if I did this correctly. Could you glance at the latest commits to mccune/pending/fix-896r3 and see if they're reasonable?

The commitdiff is at: http://northstarlabs.net/cgi-bin/gitweb.cgi?p=puppet;a=commitdiff;h=a012849e9ca496ccf72cbaf307f220f3891b802e

12/03/07 11:46:53 changed by DavidS

JFYI: the current implementation of certdnsnames has a serious, but easy fixable problem. I posted it as a new bug at #942, so it isn't lost here.

12/03/07 12:02:58 changed by whaymand_home

  • attachment sslcertificates.rb.udiff added.

Additional cumulative patch to correct bug - see #942

12/06/07 22:57:20 changed by luke

Applied whaymond_home's patch for #942 in [5886d37af0429728db42faf7e950d971145a643b].

Also merged and pushed mccune's fix.

This fix works, but I'd still like to see a patch that added 'puppet' as a default alias for the server and didn't use the '.*.' aliases. At this point, Puppet makes all certs less secure -- we're essentially obviating the post-connection check because we've got these aliases set up.

I'm going to leave this ticket open until that happens, I think.

12/11/07 18:53:12 changed by luke

  • status changed from reopened to closed.
  • resolution set to fixed.

I added the last behaviour in [d9200a0], which should finally close this ticket.

The final behaviour is this:

By default, no DNS aliases are created.

If certdnsnames is set, then those plus the host's FQDN are added as aliases.

If the cert name is equal to the name of the signing server, then both 'puppet' and 'puppet.$domain' are added as aliases.