Archive for the ‘Security’ Category.

SSL at Dreamhost

I have been wanting to secure my websites with SSL/TLS since the day I signed up with Dreamhost, but gave up after realizing I would have had to pay quite a bit extra on top of hosting and domains. Back then I would have needed to buy both static IPs, and the certificates. A few years back we started getting free certificates that were recognized by most browsers, but Dreamhost was still requiring the purchase of a static IP. Next Dreamhost stopped requiring a static IP, and I actually started the process of obtaining a free certificate, but eventually gave up due to the whole process requiring more time than I had available.

When Let’s Encrypt entered the field I got quite excited. I was even prepared to do the work this time around to write the certificate renewal automation myself. But when I finally got the time to do the work, I realized that Dreamhost had actually done all the work for me, and provided really easy setup through their management panel.

The hardest part turned out to be to find and fix all the non-https links. Dreamhost has good wiki pages about secure hosting in general, how Let’s Encrypt works at Dreamhost, how to force SSL everywhere, and how to configure WordPress for SSL. The instructions worked for the most part. Even after going through all the steps for WordPress I found non-https links when viewing the blog, and had to look for them in the templates and so on.

Next I went through my external links and converted many to https links. Of all the domains that I link to and can support SSL, Amazon seems to be the only one that redirects from https to plain http in some cases, or provides mixed environment if you follow an https link. The astore that used to work in an iframe no longer worked like that, and had to become a regular link. Hopefully Amazon fixes their end sooner rather than later.

M2Crypto Has New Maintainer

I am excited to announce that M2Crypto has a new maintainer and homepage! As of last summer, Martin Paljak agreed to take over the project since I had not been able to dedicate enough time to keep things going.

Martin is a long time M2Crypto contributor and was a security expert even before his contributions to M2Crypto. He has probably forgotten more about software security than I ever knew, so I know the project will be in safe hands.

There is also a new version of M2Crypto available on PyPI so go check it out!

M2Crypto Supports OpenSSL 1.0.x

I was supposed to release new M2Crypto version in the summer of 2010 but “real life” got in the way, and this extended all the way until this week. I finally decided that I’d better push out a new release even though there was just one significant change: OpenSSL 1.0.x support. However, I felt this was really important since OpenSSL 1.0.x has been out for almost a year now, and it is starting to get difficult to deal with software that does not work with pre-1.0.x.

Unfortunately I made a mistake in my first release to PyPI: I used the setup.py commands to build, sign and upload a source distribution, but I did this from a tree I had svn exported. Due to the way the M2Crypto setup.py was constructed this meant that the tarball was lacking vital files. Yesterday I did a new 0.21.1 release from the Subversion checkout, so the tarball now includes everything.

EV Guidelines Holding Up

About a month ago I was reading a post how one can use a browser while disabling all certificates that it ships with. While this can work, it is definitely not for the lazy or someone not very familiar with the issues. The author’s comment that it was trivial to get an EV certificate with nothing but email verification got me worried, since this should not have been possible per the EV guidelines (PDF).

I tried to comment, but comments had already been closed. I tried to find the author’s email address, but could not (in a couple of minutes of searching that I had available), so I filed a bug to Mozilla to track this down. Luckily it turns out the comment is misleading, and EV guidelines were followed. Thanks to Kathleen Wilson for tracking down the post author and clarifying things!

SSL in Python 2.7

It has been almost two years since I wrote about the state of SSL in Python 2.6. If you haven’t read that yet, I suggest you read that first and then continue here, since I will mostly just be talking about things that have changed since then, or things that I have discovered since then.

The good news is that things have improved in the stdlib ssl module. The bad news is that it is still missing some critical pieces to make SSL secure.

Python 2.7 enables you to specify ciphers to use explicitly, rather than just relying on what comes default with the SSL version selection. Additionally, if you compile the ssl module with OpenSSL 1.0 and later, using ssl.PROTOCOL_SSLv23 is safe (as in, it will not pick the insecure SSLv2 protocol) as long as you don’t enable SSLv2 specific ciphers (see the ssl module documentation for details).

Servers

With that out of the way, there isn’t really much difference to how you would write a simple SSL server with Python 2.7 compared to what I wrote in 2008. If you know your ssl module was compiled with OpenSSL 1.0 you can pick ssl.PROTOCOL_SSLv23 for maximum compatibility. Otherwise you should stick with an explicit version other than v2.

The documentation for the ssl module in 2.7 has improved a lot, and includes good sample code for servers here.

The M2Crypto code hasn’t changed. The next M2Crypto release will add support for 0penSSL 1.0.

Clients

Checking the peer certificate’s hostname is still the weak point of the ssl module. The SSL version selection situation has improved slightly like I explained above. Othewise follow the example I wrote in 2008.

Again, the M2Crypto API hasn’t changed.

Lately I have been working with pycurl at Egnyte, so I decided to give a client example using that module.

import pycurl
 
c = pycurl.Curl()
c.setopt(pycurl.URL, 'https://www.google.com')
c.setopt(pycurl.HTTPGET, 1)
c.setopt(pycurl.SSL_VERIFYPEER, 1)
c.setopt(pycurl.CAINFO, 'ca.pem')
c.setopt(pycurl.SSL_VERIFYHOST, 2)
 
try:
    c.perform()
finally:
    c.close()

I am not a big fan of pycurl due to difficulties getting it compiled and the non-Pythonic API. But it is based on the very powerful curl library, so it comes full featured out of the box.

Other Resources

Besides the Python crypto libraries capable of doing SSL that I mentioned in my SSL in Python 2.6 article, I have found pycurl. Another find in the Python crypto front is cryptlib.

Mike Ivanov wrote a great series about crypto in Python: part 2, part 3 (link to part 1 seems to have rotted). Mike also produced a comparison of different Python crypto libraries (PDF).

The future is also looking bright for the ssl module. Already the upcoming Python 3.2 ssl module will include support for SSLContexts so that you can set options for multiple SSL connections at once, allows you to selectively disable SSL versions, and it allows you to check the OpenSSL version as well.

Secure Password Scheme for Turbogears2 Application with repoze.who and bcrypt

I am working on a little Turbogears2 application, and wanted to use the repoze.who and repoze.what packages that integrate nicely with Turbogears2 and have gathered fair amount of positive feedback. It seems usage is simple, but I was quite disappointed in how password hashes are done by default, especially after I had read Thomas Ptacek’s educational rant about secure password schemes.

It turns out by default the authentication code that gets generated for you if you tell paster quickstart you want authentication is the weak kind of way Thomas warns about. Luckily the correct way he advices is easy to put in by using the py-bcrypt module. If you want pointers, see repoze.who Issue 85, or the py-bcrypt homepage.

Unfortunately py-crypt is kind of annoying to put in dependencies. The pypi entry is named bcrypt, but the download page links to py-bcrypt, so setuptools machinery can not find the right package. This can be worked around relatively easily by adding the py-bcrypt download link to setup.cfg:

[easy_install]
find_links = http://www.pylonshq.com/download/
             http://www.mindrot.org/projects/py-bcrypt/
# ...

and then in setup.py you do something like this:

#...
 
install_requires=[
    "TurboGears2 >= 2.0.3",
    "Catwalk >= 2.0.2",
    "Babel >=0.9.4",
    #can be removed iif use_toscawidgets = False
    "toscawidgets >= 0.9.7.1",
    "zope.sqlalchemy >= 0.4 ",
    "repoze.tm2 >= 1.0a4",
    "repoze.what-quickstart >= 1.0",
]
 
try:
    import bcrypt
except ImportError:
    install_requires.append("py-bcrypt >= 0.1")
 
setup(
    install_requires = install_requires,
 
# ...

Now when you go deploy your TG2 app with easy_install or similar tools, it will download the py-bcrypt package the first time, and won’t bother you if it already exists.

Using M2Crypto with boto – Secure Access to Amazon Web Services

Many companies run services in the Amazon cloud infrastructure, so it makes an attractive target for criminals as well. You need to make sure that you really are talking to the right Amazon servers when you use the cloud services.

boto seems to have emerged as the winner in the scramble to develop Python libraries to deal with Amazon Web Services (AWS). By default, boto will use the stdlib httplib.HTTPSConnection. This is a problem, because the stdlib does not provide secure SSL out of the box. However, boto designers have made it easy to plug in alternative SSL implementations that conform to the httplib.HTTPSConnection interface. M2Crypto provides this in httpslib.HTTPSConnection.

The first step is to get CA certificates that we can use to verify that the Amazon servers we will be talking to have valid certificates issued by trusted certificate authorities.

Amazon offers various services that boto provides access to, so the exact details vary a little bit (namely what connection class to instantiate). I’ll use the SimpleDB as an example, because the first 25 machine hours per month are free so it makes a great test system (you still need to sign up for AWS and provide credit card information).

#!/usr/bin/env python
 
import sys
 
from M2Crypto import httpslib, SSL
from boto.sdb.connection import SDBConnection
 
def https_connection_factory(host, port=None, strict=0, **ssl):
    """HTTPS connection factory that creates secure connections
    using M2Crypto."""
    ctx = SSL.Context('tlsv1')
    ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, depth=9)
    if ctx.load_verify_locations('cacert.pem') != 1:
        raise Exception('No CA certs')
    return httpslib.HTTPSConnection(host, port=port, strict=strict,
                                    ssl_context=ctx)
 
def create_connection(aws_access_key_id, aws_secret_access_key):
    """Create SimpleDB connection."""
    conn = SDBConnection(aws_access_key_id=aws_access_key_id,
                         aws_secret_access_key=aws_secret_access_key,
                         https_connection_factory=(https_connection_factory, ()))
    return conn
 
if __name__ == '__main__':
    # Sample usage
    if len(sys.argv) != 3:
        sys.exit('Usage: %s aws_access_key_id aws_secret_access_key' % sys.argv[0])
 
    conn = create_connection(*sys.argv[1:])
    domain = conn.create_domain('mytest')
    try:
        item, key, value = 'item1', 'key1', 'value1'    
        domain.put_attributes(item, {key: value})
        assert value == domain.get_attributes(item)[key]
    finally:
        conn.delete_domain(domain)
 
    print 'Usage:', conn.get_usage()

The sample application takes your AWS access key and secret access key as parameters, and it assumes cacert.pem file containing the CA certificates is in the same directory. Typically running that application shows that it uses less than 0.006 secondshours of Amazon computing facilities so you could run this application over 15 million4500 times a month without charge.

Update:I mixed up units, which Mocky pointed out; fixed above.

M2Crypto 0.20.2 for Ancient OpenSSL

M2Crypto has been claiming support for OpenSSL 0.9.7 but it actually turned out I wasn’t testing with quite that old OpenSSL version. Recently M2Crypto got support for RSA PSS stuff, but it turns out this was added in OpenSSL 0.9.7h, and you could not build/run M2Crypto against an older OpenSSL version. Arguably you should not use those old OpenSSL versions, but apparently there are people who can’t help it. And since M2Crypto claims support all the way back to 0.9.7 it made sense to make it so.

The M2Crypto trunk and 0.20.2 now omit the RSA PSS stuff if you have too old OpenSSL. Additionally, to prevent this kind of error from happening in the future, I added “minreq” (for Minimum Requirements) Tinderbox client that builds and tests M2Crypto trunk using Python 2.3, OpenSSL 0.9.7 and SWIG 1.3.28 (the current minimum requirements) on Ubuntu 8.04.