I'm very excited to announce that my proposal was accepted and I'll be presenting at the Los Angeles Ruby Conference on February 23, 2012.
I'll be giving a talk, "Python for Ruby Programmers," to familiarize Rubyists with Python and give them a better sense of Python's relative strengths and weaknesses. We'll talk syntax, maintainability, and practical applications.
More information coming soon!
This is a blog about software engineering and programming languages.
Subscribe or learn more about my work at mikeleone.com.
Showing posts with label python. Show all posts
Showing posts with label python. Show all posts
Thursday, January 3, 2013
Sunday, April 29, 2012
Integration Testing in Python
Hey folks! Here's a presentation I did for the Providence Royal Python Society meetup this winter. It covers some of the currently-available integration testing tools for Python, as well as my own project, easy-integration.
Thursday, October 20, 2011
Web App Security: Django and the OWASP Top 10
Security threat: Neutralized. |
At my company, Panoptic Development, we've built several applications for the healthcare industry. Since we often deal with sensitive patient medical data, web application security is a huge concern. Enter the OWASP Top 10, a collection of best practices for web application security.
From Wikipedia:
The Open Web Application Security Project (OWASP) is an open-source application security project. The OWASP community includes corporations, educational organizations, and individuals from around the world. This community works to create freely-available articles, methodologies, documentation, tools, and technologies.What's the Top 10?
From the OWASP Wiki:
The OWASP Top Ten provides a powerful awareness document for web application security. The OWASP Top Ten represents a broad consensus about what the most critical web application security flaws are. Project members include a variety of security experts from around the world who have shared their expertise to produce this list. Versions of the 2007 were translated into English, French, Spanish, Japanese, Korean and Turkish and other languages. Translation efforts for the 2010 version are underway and they will be posted as they become available....As you help us spread the word, please emphasize:
- OWASP is reaching out to developers, not just the application security community
- The Top 10 is about managing risk, not just avoiding vulnerabilities
- To manage these risks, organizations need an application risk management program, not just awareness training, app testing, and remediation
No Easy Answer
Make no mistake - robust security is the result of consistent, ongoing code review, infrastructure expertise, and a broad knowledge of web programming, not a one-time checklist. Still, when you're dealing with sensitive data, and especially when several organizations work on the same codebase, it's important to have mutually-accepted security standards.
Django: Frameworks to the Rescue
Full-stack web development frameworks like Django are great for helping a team manage security concerns. Let's investigate how Django's security features relate to the 2010 OWASP Top 10. If you need background information on the vulnerability types themselves, I included wikipedia links.
I should also stress that this isn't an exhaustive look into every possible security vulnerability; this just explores some of the most important ways that Django mitigates (or doesn't mitigate) major security concerns.
- Code Injection: For most Django applications, the primary code injection risk is SQL injection. Django protects against SQL injection through its ORM abstraction layer, which automatically escapes input. Note that it's possible to perform raw sql queries with Django, any any such code should be manually audited for if it interacts with direct user input. Though raw SQL is needed occasionally, especially for optimization, it's generally a code smell in a Django application.
If your application interacts with any other backends, like LDAP, you'll want to investigate those third-party libraries separately. Client-side javascript is also mitigated through its templating system; see #2 below.
- Cross-site scripting: Generally, the most important way to mitigate XSS is to prevent unescaped user input from making it into your application's rendered HTML. Django’s templating system facilitates this by automatically excaping all variable values. If you don't want to escape something on the front end, you have to explicitly tell Django not to escape it. In your code reviews, you can concentrate more on the few areas of your app where you don't escape user input.
- Session hijacking: With the default Django SessionMiddleware, the framework doesn't allow any session data in the url. Session IDs are also stored as hashes, mitigating brute force attacks.
While you'll still want to ensure your code doesn't expose direct session data to the user in any way, Django makes it difficult to expose that information.
- Insecure direct object references: Django has several mechanisms in place to mitigate IDORs. It provides a special "slug" field if you don't want to pass object IDs around as parameters. Django 1.2 also lets you explicitly name read-only fields in the admin, so you can prevent users from hacking together forms that alter protected data.
Note that you'll still want to manually audit your code to expose areas where users can access arbitrary object data, especially outside of the admin.
- Cross-site request forgery: Django has built-in CSRF protection middleware, so it would be extraordinarily difficult for an attacker to maliciously submit a form to your site using an authenticated user's credentials.
- Security misconfiguration: This is one item that is largely outside the domain of the web framework itself; it's more about the application's deployment environment. You need to keep up with Python security updates, Django security updates, and keep track of any third-party libraries you use for security updates. You need to disable ports/services you don't use, and more. With complex apps, this can be a huge job.
Fortunately, there are great, frequently-updated blogs for both the Python and Django core teams where you can keep track of security updates. It's also easy to follow security announcement lists for your web server (e.g. apache, nginx) or operating system to keep track of security updates.
- Insecure cryptographic storage: If the only secure information you're encrypting is user password data, you're all set if you use Django's built-in user authentication. Django encrypts password data using SHA1 by default, but also supports MD5 and crypt out-of-the-box.
If your application directly stores or manipulates any sensitive user data, you'll need to audit that code manually. Fortunately, OWASP maintains a great cryptographic storage cheat sheet to help you along the way.
- Failure to restrict URL access: Django has great built-in support for restricting access to specific content. Access is always controlled at the view level, before anything is rendered. You're able to restrict access for specific actions or for entire views. Note that you'll still want to audit each url/action in your app to ensure that you're restricting access the way you intended. It's easy to miss a @login_required decorator or forget to lock down an AJAX action.
- Insufficient transport layer protection: In many cases, strong transport layer protection means using SSL. Though this falls outside the domain of Django itself, the framework does provide some help: Django supports the secure cookie protocol (PDF link to research paper), and also allows developers to force the use of secure cookies over HTTPS.
- Unvalidated redirects and forwards: Because of Django's robust, built-in URL access restriction (see #7), it would be very hard for an attacker to take advantage of unvalidated redirects. Again, since access is handled at the view level, you can't [easily] redirect users to a different url on your site without access control.
Additionally, Django's built-in user authentication system doesn't allow off-site redirect links as url parameters. Note that you'll still want to audit your code for any manual use of redirect links in URL parameters.
Labels:
csrf,
django,
owasp,
python,
security,
sql injection,
ten,
top 10,
web application security,
xss
Wednesday, August 18, 2010
Tutorial: My Fabric Presentation from RIRUG
Slides are up from my presentation during the June meeting of the RI Ruby Users Group!
Labels:
capistrano,
deployment,
django python,
fabric,
git,
python,
rails,
ruby,
tutorial
Saturday, February 27, 2010
Custom Date Formats in the Django Admin
For better or for worse, subclassing Django components to add custom functionality is a common technique. The workflow usually goes something like this:
First, let's add a new module to our app, fields.py:
In fields.py, subclass the Datefield form, adding the MM-DD-YYY format to the tuple of default formats:
Then, subclass the django model DateField to use the new USADateFieldForm:
When you're done, your new module will look like this:
Finally, import fields in your models.py module and use it! Your model might look something like this:
I like approaches like this, which push logic back into the models. The functionality would be tougher to test and maintain if we wrote custom front-end code for the field.
- Subclass a django component
- Override a specific method
- Set some custom configuration options in the method
- Call super()
First, let's add a new module to our app, fields.py:
In fields.py, subclass the Datefield form, adding the MM-DD-YYY format to the tuple of default formats:
class USADateFormField(forms.DateField): def __init__(self, *args, **kwargs): kwargs.update({'input_formats': ("%m-%d-%Y",)+DEFAULT_DATE_INPUT_FORMATS}) super(USADateFormField, self).__init__(*args, **kwargs)
Then, subclass the django model DateField to use the new USADateFieldForm:
class USADateField(models.DateField): def formfield(self, **kwargs): kwargs.update({'form_class': USADateFormField}) return super(USADateField, self).formfield(**kwargs)
Finally, import fields in your models.py module and use it! Your model might look something like this:
class Appointment(models.Model):
scheduled_date = USADateField(blank=True)
I like approaches like this, which push logic back into the models. The functionality would be tougher to test and maintain if we wrote custom front-end code for the field.
Labels:
admin,
code,
django python,
forms,
programming,
python
Friday, February 12, 2010
Fabric - A Deployment Tool for Rubyists and Pythonists Alike
If you're coming from the Ruby/Rails world, the industry standard tool for deployment is clearly Capistrano.
In some cases, though, using Fabric might make more sense. If you've got a simple web app and want to try something different for deployment, have a look at Fabric. It's a terse, lightweight Python deployment tool and a good alternative to Capistrano. Most importantly, it's SUPER EASY to learn and you don't need ANY Python experience.
I like how Fabric's tutorial shows a version-control-agnostic deployment pattern. The fabfile is part of the project we want to deploy, and whatever is in our project directory will be deployed. With this pattern, Fabric doesn't need any information about our version control system or repository.
For example, I use git for most of my projects.
If I'm running the master branch on my development machine and want to deploy master, I just run
Super easy. We can manage the code we're deploying with the tools already built in to our version control system; we don't have to implement those controls again with our deployment tool.
Installing Fabric on Ubuntu 9.10
Wow, that was easy.
In some cases, though, using Fabric might make more sense. If you've got a simple web app and want to try something different for deployment, have a look at Fabric. It's a terse, lightweight Python deployment tool and a good alternative to Capistrano. Most importantly, it's SUPER EASY to learn and you don't need ANY Python experience.
I like how Fabric's tutorial shows a version-control-agnostic deployment pattern. The fabfile is part of the project we want to deploy, and whatever is in our project directory will be deployed. With this pattern, Fabric doesn't need any information about our version control system or repository.
For example, I use git for most of my projects.
If I'm running the master branch on my development machine and want to deploy master, I just run
$ fab deployWhat if I want to deploy my release branch instead of the master branch? I just do the following:
$ git checkout my-release-branch $ fab deploy
Super easy. We can manage the code we're deploying with the tools already built in to our version control system; we don't have to implement those controls again with our deployment tool.
Installing Fabric on Ubuntu 9.10
$ sudo apt-get install python-setuptools $ sudo easy_install fabric
Wow, that was easy.
Labels:
capistrano,
deployment,
django python,
fabric,
git,
python,
rails,
ruby
Subscribe to:
Posts (Atom)