Archive for the ‘Security’ Category.

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.

M2Crypto 0.20.1 Fixes Regression in httpslib.ProxyHTTPSConnection

Miloslav Trmac noticed a regression in httpslib.ProxyHTTPSConnection and provided a fix for it, and I’ve just tagged and uploaded the new 0.20.1 version to PyPI. See the 0.20 release announcement for general information about the 0.20 release series.

I’ve also been getting a few requests for help on building M2Crypto on Fedora Core -based systems, so I’ve added some info to the FAQ. Basically there is a fedora_setup.sh wrapper script in the source tarball that you can use instead of the plain setup.py. There are more details about the fedora_setup.sh script, if you are interested.

M2Crypto 0.20

I am pleased to announce M2Crypto 0.20, which has been in development for over nine months. It fixes over 30 bugs, and fixes and new functionality was contributed by more than ten people. Hooah!

The CHANGES file lists the full list of changes, but personally I am most pleased by M2Crypto having reached the magical 80% unit test (code) coverage. Besides that technicality, there are Python 2.6 fixes, threading fixes, added support for RSASSA-PSS signing and verifying, certificates with large serial numbers, and more.

Download from pypi.

Or use easy_install (may not work on all systems): easy_install M2Crypto

M2Crypto is the most complete Python wrapper for OpenSSL featuring RSA, DSA, DH, HMACs, message digests, symmetric ciphers (including AES); SSL functionality to implement clients and servers; HTTPS extensions to Python’s httplib, urllib, and xmlrpclib; unforgeable HMAC’ing AuthCookies for web session management; FTP/TLS client and server; S/MIME; ZServerSSL: A HTTPS server for Zope and ZSmime: An S/MIME messenger for Zope. M2Crypto can also be used to provide SSL for Twisted. Smartcards supported through the Engine API.

M2Crypto 0.20 Beta Cycle Begins

Better late than never… I am announcing the first beta of M2Crypto 0.20 release. M2Crypto is the most complete Python wrapper for OpenSSL.

The 0.20 release has been in development for about nine months. About 30 bugs and new features have been implemented by more than ten people. Unit tests now cover 80% of the code base. Tinderbox is used to automatically test changes on various flavors of Ubuntu, Fedora Core, Redhat and Cygwin. We could use more Tinderbox clients, so please drop me a line if you have some spare machine cycles available.

The release include some fairly significant changes, including tricky ones in threading and so forth. See the CHANGES file for list of changes. Please test your applications, and go file bugs on any issues you notice. I’ll wait for feedback for a week, spin the next beta and so forth until there are no more release blockers found within a beta period.

There are a few issues I feel bad about that did not make the first beta. If you can help create fixes for these, I’d be willing to consider including the fixes in 0.20 if the changes don’t look too scary. Here is my wish list:

Download from pypi.

Or use easy_install (may not work on all systems): easy_install M2Crypto

Simple Website Change Detection System

I happened to read a post on how to detect if someone has changed files on your webserver to serve nebulous scripts and what not. The idea in the post was to compute hashes of the files on your server and then compare periodically that the hashes match. This works against some simple attacks where all the attacker does is modify some of your content files. It won’t work if the attacker has also gotten access to the script doing the checks, or the hashes, and so forth.

As I was reading the post I realized that if you use a version control system like Subversion to publish changes to your site (the live site is a checked out copy), you get this automatically. All you need to do additionally is to set up a cronjob to run svn status (or equivalent if using some other version control system) on the server. svn status does not print anything if there are no changes, but for any added, deleted or changed files or directories it will print one line of output. Of course, this only works for files, not for content coming from databases.

M2Crypto Build Wrapper for Fedora Core -based Distributions

Ever since M2Crypto got support for Elliptic Curves (EC) cryptography, it has been somewhat difficult to build M2Crypto on systems where OpenSSL has been built without EC support. Notably distributions based on Fedora Core, which besides Fedora Core include of course Redhat and CentOS.

Disabled EC support alone wouldn’t be an issue, since normally opensslconf.h defines OPENSSL_NO_EC, but those same systems have also changed OpenSSL build so that instead of opensslconf.h you need to include processor architecture dependent file. And if that wasn’t enough this isn’t actually what you are supposed to be doing, and you will hit a compiler error to notify you of that. The final step in the recipe is to tell SWIG to treat errors as warnings. The distributions make build changes in their own versions of M2Crypto, but unless you know the recipe, you are going to have a hard time building M2Crypto yourself. Miloslav Trmač showed me what kind of changes were needed, and I made a new setup wrapper fedora_setup.sh which should help you get off the ground with M2Crypto if you are having a hard time building it. Let me know if you run into any problems with the setup wrapper.

I am sure the distros did not make these changes just to make it harder to build systems based on OpenSSL, although it sure does feel like that at times. Maybe someone can shed light on why these changes were made in the first place.