
The most dangerous code in the world - gmcabrita
https://crypto.stanford.edu/~dabo/pubs/abstracts/ssl-client-bugs.html
======
tptacek
The worst example from this paper is Curl's API.

Curl has an option, CURL_SSL_VERIFYHOST. When VERIFYHOST=0, Curl does what
you'd expect: it effectively doesn't validate SSL certificates.

When VERIFYHOST=2, Curl does what you'd expect: it verifies SSL certificates,
ensuring that one of the hosts attested by the certificate matches the host
presenting it.

When VERIFYHOST=1, or, in some popular languages, when VERIFYHOST=TRUE, Curl
does something very strange. It checks to see if the certificate attests to
any hostnames, and then accepts the certificate _no matter who presents it_.

Developers reasonably assume parameters like "VERIFYHOST" are boolean; either
we're verifying or we're not. So they routinely set VERIFYHOST to 1 or "true"
(which can promote to 1). Because Curl has this weird in-between setting,
which does not express any security policy I can figure out, they're
effectively not verifying certificates.

~~~
kyberias
While you're attacking curl you (intentionally?) forget to mention that the
default value is 2 that is perfectly safe. I don't think it's "reasonable to
assume" that the parameter is a boolean value while it's well documented. If
programmers are lazy, they make many kind of mistakes.

~~~
tptacek
Yes, yes, I know, stupid Paypal, stupid Amazon, we get it. VERIFYHOST=1 doing
nothing makes perfect sense, you just have to read the documentation. Of
course.

~~~
kyberias
Yes, Amazon et.al. made some mistakes due being lazy and PHP being the nice
language that it is. They have fixed it. Let's go ahead and find another non-
default, documented parameter value in a library and call it a vulnerability.

~~~
tptacek
Ok. Your turn. Go!

------
moxie
I agree that these APIs are fundamentally difficult to use correctly
(sometimes it almost seems as if they've been designed to trick you), and that
developers commonly get them wrong, but this paper is perhaps a little more
inflammatory than it should be.

They cast a really wide net, looking for as many examples as possible where
non-browser applications fail to do SSL validation correctly, but then
conclude that this will result in a security compromise without fully
examining the implications.

For instance, they point out that many SDKs for Amazon FPS don't validate
certificates correctly. But I didn't see them mention that the FPS protocol
does its own signature-based authentication and that credentials are never
transmitted in the clear: it was essentially designed to operate over an
insecure transport to begin with.

Likewise, they point out an "unsafe" construction that an Android application
that I wrote (TextSecure) uses. But they don't mention that this is for
communication with an MMSC, that this is how it has to be (many don't present
CA-signed certificates), and that the point of TextSecure is that an OTR-like
secure protocol is layered on top of base transport layer (be it SMS or MMS).

So I think the paper would be a lot stronger if they weren't overstating their
position so much.

~~~
austinpilot
One of the authors here... The paper is accompanied by a FAQ, which among
other things explains the impact on specific software:

[https://docs.google.com/document/pub?id=1roBIeSJsYq3Ntpf6N0P...](https://docs.google.com/document/pub?id=1roBIeSJsYq3Ntpf6N0PIeeAAvu4ddn7mGo6Qb7aL7ew)

For example, broken SSL in Amazon FPS allows a MITM attacker to forge instant
payment notifications and defraud merchants who use vulnerable SDKs. This is a
real vulnerability, acknowledged by Amazon.

~~~
scott_s
Can you address his specific point about TextSecure?

~~~
zx2c4
please would ya?

------
3pt14159
The title should be renamed to:

Many security flaws found in commonly used SSL libraries.

Other than that, it is a great find.

~~~
Wingman4l7
Thanks for de-FUDing the title, I scanned the comments hoping someone had done
that =)

------
mrb
How ironic. Even these guys hosting a paper about SSL can't host their stuff
securely on an HTTPS server.

<base
href="[http://crypto.stanford.edu/~dabo/pubs/pubs.html>](http://crypto.stanford.edu/~dabo/pubs/pubs.html>);

This causes the page to throw an HTTPS warning: "this page loads insecure
content" due to the css loaded over HTTP.

~~~
tptacek
Yes, yes, stupid Dan Boneh, extracts SSL keys from servers over the Internet
using timing measurements, but can't properly write an HTML page, we get it.
Credibility -> toilet.

~~~
nicholassmith
Because being talented at one thing means you're talented at _everything_.

~~~
tptacek
The two things here being "finding critical vulnerabilities in the TLS
protocol and its implementations, and generally being one of the most highly-
regarded academic practical cryptographers" and "writing HTML". Trenchant
point.

~~~
nicholassmith
Exactly (I think people might assume I was disagreeing), the skill sets are
wildly different in many ways.

------
rolux
From the PDF linked in the article:

"Not the most interesting technically, but perhaps the most devastating
(because of the ease of exploitation) bug is the broken certificate validation
in the Chase mobile banking app on Android. Even a primitive network
attacker—for example, someone in control of a malicious Wi-Fi access point—can
exploit this vulnerability to harvest the login credentials of Chase mobile
banking customers."

~~~
rolux
Further down in the PDF, the authors present the decompiled source of the
Chase app:

    
    
      public final void checkServerTrusted(X509Certificate[]
          paramArrayOfX509Certificate, String paramString)
      {
        if ((paramArrayOfX509Certificate != null) && (
            paramArrayOfX509Certificate.length == 1))
          paramArrayOfX509Certificate[0].checkValidity();
        while (true)
        {
          return;
          this.a.checkServerTrusted(
              paramArrayOfX509Certificate, paramString);
        }
      }
    

Good to know this isn't used for anything critical, just for, um, mobile
banking.

~~~
sukuriant
Okay. Please tell me I'm reading that wrong.

    
    
       void foo(X509Certificate[] a, String unused) {
         if( a != null && a.length == 1) a[0].checkValidity();
         while(true){
            return;
            /* never executed stuff */
            foo(a, unused);
         }
       }
    

X509Certificate.checkValidity()'s javadoc:
[http://docs.oracle.com/javase/1.5.0/docs/api/javax/security/...](http://docs.oracle.com/javase/1.5.0/docs/api/javax/security/cert/X509Certificate.html#checkValidity%28%29)

Selections from above link:

Checks that the certificate is currently valid. It is if the current date and
time are within the validity period given in the certificate.

    
    
      Throws:
      CertificateExpiredException - if the certificate has expired.
      CertificateNotYetValidException - if the certificate is not yet valid.
    

There has got to be more to their code than this. It does nothing useful
except make sure a random certificate is not expired. If there is no
certificate, it doesn't fail or return false or anything. What is this!?

Could this be a profiler-optimized set of code that really had a LOT more code
to it? But then why would the bit of random junk after the return statement
exist? Did no one do a proper code-review of this???

[edit: I used JavaSE 1.5 above; but I just checked Android's version and it
looks to be the same, just less verbage in the docs.]

~~~
rolux
The issue with the code above is the return statement, most likely inserted
during development, with the good intention to remove it later, since the "bit
of random junk" that follows would have validated the server's certificate.

~~~
sukuriant
But it doesn't. It's calling the exact same function. As your sibling comment
remarked, it looked like someone really frustrated with why they were getting
a stack-overflow error and gave up.

------
pjscott
Sounds like it might be easier to list the options that actually do the Right
Thing. If you're using Python, for example, the correct way to make HTTP
requests is to ignore the standard library's urllib and (shudder) urllib2, and
use Requests instead:

<http://docs.python-requests.org/en/latest/>

It validates SSL certificates correctly by default. How about other languages?

~~~
gingerlime
Good to know. I always wondered how come none those libraries fully validate
SSL certificates. On one of my projects, we were hooking into the Windows
Winhttp Libraries to be able to do this (and a couple of other things), but
when porting to Mac we kinda had to accept the standard libs just didn't care
enough about this. It's been a while ago, so perhaps things have changed.
Requests is a great example of this I guess.

------
kzahel
I notice that whenever I use "wget <https://github.com/>[...]" I always end up
typing wget --no-check-certificate because the first try never works.

I suppose my web browser has an extended list of CA that my OSX lion does not
know about.

~~~
jackowayed
My HTC Droid Incredible's browser also always complained about their
certificate and popped up a dialog box I had to click through. But now that
I've installed Cyanogen Mod, it hasn't been a problem, so I guess it's one of
several things HTC broke.

------
mindstab
So of all the possible futures we could have, ones where we use computers to
give us crypto, good security and privacy etc, instead we end up with Masamune
Shirow's admitted guess of Ghost in the Shell where people can't properly use
their arms due to 5 different version of the driver installed and people
having 10 different viruses IN THEIR BRAINS and are constantly getting hacked
and having their bodies taken over.

------
andrewcooke
they make this point in the paper, but still it surprises me - the level of
testing for payment frameworks seems surprisingly minimal. it's pretty easy
with openssl to roll your own certificates to test a bunch of different
issues. you'd think that the people involved would have quite an incentive to
test well.

i'm not saying that this would solve all the problems, or that you should
develop critical financial software by having people that don't understand
much writing tests. but tests are pretty much common culture now; you'd think
people would have considered this. and the argument the paper makes is not
that the programmers are clueless, but that they are confused by the API, so
they should be able to think up some useful tests...

of course, integration testing with sockets is a bit more complicated than
unit tests (perhaps something toolkit apis should support is a way to allow
testing without sockets?), but it's not super-hard. [edit: hmm. although
testing for unreliable dns is going to be more tricky.]

------
zippie
The title is a bit sensationalist - there was incorrect code and it made the
copy/paste rounds. Presumably all incorrect code is dangerous to some degree
but I'm certain there's a more fitting title for this story.

At any rate, here is a pull request for PHP which attempts to address the
issue:

<https://github.com/php/php-src/pull/221>

------
scott_s
I have only read the first two sections, but the prose in this paper is a
breath of fresh air. It is clear and strong.

------
davyjones
Slightly related, link to Peereboom's rant on the OpenSSL library (a bit
dated): <http://www.peereboom.us/assl/assl/html/openssl.html>

------
justinhj
I came across this issue when using node.js to make secure requests as a
client and after setting up tests with bad certs found it silently worked
anyway. To get it working you need to be at a certain version of node.js and
make sure you set the options up carefully. Testing with a bad certificate is
essential for this stuff. [http://stackoverflow.com/questions/10142431/my-
node-js-https...](http://stackoverflow.com/questions/10142431/my-node-js-
https-client-always-works-regardless-of-certificate-validity)

------
jyrkesh
So how soon until we start seeing developers fix these gaping holes? And, more
importantly, how soon do we start seeing app-specific exploits that take
advantage of this problem?

~~~
Firehed
Probably as soon as certificate validation is more reliable.

I can see turning off validation for stuff where you're sending non-important
data to a third party which may or may not be encrypted (asyncronous API pings
where you say "something happened, ask us [securely] what it was") - but
that's only OK if you're just as willing to send the info over an http
connection as well.

If you turn off cert validation in your app to your own API, something is
seriously wrong. Unfortunately, it often comes down to simply buying a more
expensive certificate that's signed by a root CA with wider trust. Given
spending $50 or CURLOPT_SSL_VERIFYPEER=false, a scary number of people will
choose the latter.

These libraries should provide an easy way to specify an additional root CA
when validating the chain of trust - that way you could even use a self-signed
cert without disabling the chain of trust check, all you'd have to do is embed
your self-signing public key.

Probably more important, there should be clearer error messages when the SSL
chain verification. Cryptic "verify the CA cert is OK" messages don't help
much; they should say "SSL CA [name] is not in the installed trusted
certificates, add trust for it with CURLOPT_CAINFO, details at
example.com/ca.html" or something along those lines.

It may cause issues with root CA revocation (DigiNotar anyone?), but it's
still better than disabling the checks entirely.

~~~
spydum
If the SSL/TLS server is properly configured with all of the nodes in the
certificate chain, you don't need to buy more expensive certs.

Now I will say that, most common apps (Apache HTTPD + mod_ssl for example), do
not make this process as clear as it should be. Specifying cert order wrong in
the Intermediate Chain file will still break cert validation for some apps,
because it's sent out exactly as the server admin configures (and this fact is
often lost of folks who maybe touch their certs once a year when they expire).

~~~
Firehed
There's no standard as to which certificate issuers have their trusted root CA
cert installed. If your clients don't have it on their machines (desktops,
phones, servers, whatever) it doesn't matter what you paid.

My point was that the more widely-trusted issuers (meaning installed by
default on the most OSes) can get away with charging more because they're more
compatible.

There's nothing stopping you from setting up your own root CA and self-
signing, maintaining a full chain of trust if you build the certs right (I've
done it; once you have the process documented well it only takes a few
minutes) but unless the clients trust the lowest link in the chain (not the
case for self-signed, and some cheaper issuers) you'll still get validation
errors.

------
felanthropop
And odds are the guys that wrote this paper don't have any clue that even if
those writing the CLI tools/libraries/frameworks that use SSL had locked them
completely down, developers and sysadmins would write scripts to agree-to-all,
fake auth, etc. to get around security, because we have jobs that have to get
done and security is not what we are all paid to do. Security is only critical
when it fails. People claim to want security. They may even have an office of
security. But even if that office of security is scanning all the apps, taking
production apps down because they didn't throttle their probes, and maybe even
looking at code- they cannot do the job of the developer.

It is destined to be flawed as long as insecurity is allowed. Only when every
exploit is exploited continously will people be vigilant.

~~~
tptacek
Yes! Yes! Stupid researchers! Who has time for security? We've got mobile
banking transactions to process!

------
adamfisk
Anyone have an example of good cert verification in Java? The concept at
<https://github.com/iSECPartners/ssl-conservatory> is great, but it needs
examples in more languages. Our case is pretty weird (some self-signed certs
between peers, cert pinning of sorts in that we only accept equifax as a root
signer, no default signing authorities accepted), but anyone see holes in the
authenticate method of our trust manager at:

[https://github.com/getlantern/lantern/blob/master/src/main/j...](https://github.com/getlantern/lantern/blob/master/src/main/java/org/lantern/LanternTrustManager.java)

? This code is intended for deployment in potentially dangerous regions for
getting around government censors.

Thanks.

------
purephase
I noticed this the other day in Rails. ActiveResource::Connection in 3.2.8 is
affected in that the default OpenSSL verification mode is
"OpenSSL::SSL::VERIFY_NONE". A developer has to explicitly set it for SSL
validation.

You can see it here:
[https://github.com/rails/rails/blob/3-2-stable/activeresourc...](https://github.com/rails/rails/blob/3-2-stable/activeresource/lib/active_resource/connection.rb)

I'm pointing it out as it was not mentioned in the paper.

Edit: It looks like it has been that way since SSL was first implemented in
Connection.

------
khakimov
2010, Certificate verification is essential to TLS.

require 'always_verify_ssl_certificates' AlwaysVerifySSLCertificates.ca_file =
"/path/path/path/cacert.pem"

http= Net::HTTP.new('<https://some.ssl.site>, 443) http.use_ssl = true req =
Net::HTTP::Get.new('/') response = http.request(req)

[http://www.rubyinside.com/how-to-cure-nethttps-risky-
default...](http://www.rubyinside.com/how-to-cure-nethttps-risky-default-
https-behavior-4010.html)

------
drallison
Everyone who does any development should read this paper. It is not just for
SSL specialists!

------
citizenoftmrw
Are Rack-based middleware affected by these vulnerabilities (or did I lose the
plot)?

------
ritratt
"...bad implementations of SSL like OpenSSL..."

<falls off chair>

