Let’s talk for a brief moment about some very basic things you can do to help make your web application more secure. If I were to pick three of the most common issues I still see while browsing the web, they would be:

  1. Error messages enabled
  2. Cross-Site Scripting (unescaped input)
  3. And yes, SQL Injection of some sort

The (un)fortunate thing is that most of these issues are easily solvable. A generic error page, as opposed to a stack trace or verbose error message, can usually be implemented with a couple configuration changes. Yet, I still see large websites that spit out stack traces and code when an error occurs.

Cross-Site Scripting is another issue that still plagues us. Testing for it is simple – just enter something like test"> into an input field and if the resulting page displays that in raw HTML, chances are you have a problem. Every language has some form of HTML-escaping function and, if possible, it’s good to turn this on by default. This will be the case in Rails 3.0, thankfully.

Finally, I still see traces of SQL Injection on an all-too regular basis. Identified by the oh-so-dangerous single tick mark – ‘ – and typically resulting in an error page that shouldn’t be showing up anyway if the first issue were address. That said, even if the error is obscured, it’s still possible to retrieve data using a technique called Blind SQL Injection. Any data getting sent to an SQL server should also be properly escaped or sent through stored procedures depending on the backend technology. Think SQL Injection isn’t a problem? Talk to RockYou, whose database of 32 million usernames and passwords was compromised because of it.

Address those three things and (sadly) you’ll be ahead of the game.

Bringing Security Back

Just a quick note that I’m going to begin posting content on this blog again. I continually come across common issues in web applications and feel there should be a place where startup developers can come for good reading on basic info about web application vulnerabilities and how to prevent them.

That said, I will have upcoming posts about Cross-Site Scripting/Request Forgery, SQL Injection, and possibly some recorded demos I’ve given on the past showing just how easy it is to use such vulnerabilities to take advantage of a web site.

Let’s all take a breath for a moment, shall we?



There. Now let’s take a look at the recent activity we saw on Twitter over the weekend into Monday. There were two distinct, very likely related events.


The Phish

On Saturday, Twitter was hit with a phishing attack. While the events surrounding that have been widely documented, there was an undercurrent of discussion from developers of third-party Twitter applications claiming that this was exactly why Twitter needed to implement OAuth. With the sale of a Twitter application that had been around for one day and accumulated approximately 1,000 accounts, speculation was high that this phishing attack was a direct result of developers being “forced” to request user credentials to build their Twitter apps.

There are a couple things to address here. First is that OAuth is most definitely not a web application silver bullet and would not have prevented the phishing attack that occurred.


Plain and simple.


OAuth provides a secure manner for interacting with an application’s API. Phishing is an attempt to retrieve valid user credentials by spoofing or forging the target site. While Twitter users are admittedly lackadaisical with their account credentials (as seen with a test I performed earlier this year on a site called TwitterAwesomeness), the fact is that this attack occurred because somebody created a legitimate looking Twitter login page and some users fell susceptible to the spoof.

For those looking for more details, there was some good discussion on the Twitter Development mailing list if you can wade through the various misconceptions. Chris Messina actually has a fantastic blog post on password usage and Twitter. Unfortunately, there is still the misconception that OAuth would have fixed this and prevented the worm from propagating. To address that – any application can spoof the Twitter home page. Once those credentials have been obtained, the attackers can automate the Twitter website in a variety of ways.

While I agree that the pattern of password usage needs to change on Twitter, restricting application access is a different battle from educating users on preventing themselves from being victims of phishing attacks. Not to mention that chances are high that a web application vulnerability such as SQL Injection exists within the numerous third-party web applications that accept Twitter usernames and passwords. Ultimately, however, OAuth will be beneficial in locking down Twitter from an API and third-party application perspective.


The Hack

On Monday morning, there was a post indicating Twitter had been “hacked” and several high-profile accounts had been compromised and used to post fake updates. This is more of an operational issue, but may have been indirectly related to the ongoing phishing attacks if a staff member had been phished. Based on the Twitter blog post, it would appear as if the admin tools utilized by Twitter support staff are available externally and may even share Twitter account information. From a security operations point of view, this is a recipe for disaster. If possible, administrative functions should be logically separated from user activity. Twitter is rather fortunate this happened at the same time and that the attackers didn’t have more malicious or damaging ideas in mind.

This prank is simply the tip of the iceberg. While Twitter may be able to secure the admin tools, the site will continue to grow and the phishing attacks will continue to advance to take advantage of how Twitter is used. How so? Well many Twitter-folk utilize automatic-follow techniques so they don’t have to manage it. This means immediate acceptance into a larger network, even more so if you have somebody reply to you. Further, “re-tweeting” is a popular concept on Twitter to share links. Finally, any URL over 30 characters is automatically shortened by Twitter and many users do so manually or utilize client applications further obfuscating the destination site.


A Little Perspective

I urge those people pushing so hard for strong account controls on Twitter, to also direct their resources and energy towards more critical assets. With the estimated Internet population at nearly 1.5 billion people, Twitter’s population accounts for a minuscule fraction of that. Wells Fargo has 48 million customers. Bank of America employed 206,587 people in 2008. Based on my Twitter stats service that records analysis of every update on Twitter, there were 358,691 distinct users that posted tweets on January 5 of this year. I would love to see more critical assets such as banks implement more secure authentication methods as well, and those user populations are even larger and more critical than our favorite micro-blogging site.


Update: Seems it was an unrelated brute-force attempt that compromised Twitter’s Admin tools. Interestingly enough, I’ve seen this functionality other places and noticed when I had a support ticket that the username was the same. It seems my hope that the systems were somehow logically separated was not to be realized. Oh, Twitter.

There were two failings here, which is why layered security is beneficial.

  1. A weak password was being used for a highly-privileged account
  2. The administrative tools were exposed in such a way that an external attacker could continually attempt passwords and not be automatically locked out or noticed

Yes. It is just a micro-blogging site. But when the President-elect is relying on it to get his message out and people are staking their reputations and businesses on it…it suddenly becomes more.

I fully believe that Twitter does realize this and we know they are working to address some of the more pressing issues. Yes it’s taking a “long time” and we can criticize all we want, but who’s really at fault here – Twitter for not prioritizing the security of what was originally conceived to be an offline AIM status service, or the developers for propagating what they knew was an inherently insecure method of authentication with only the dollar signs of success in their eyes. In my opinion, why bother throwing blame. Let’s work together towards building a more secure web 3.0.


</soapbox>

I want to briefly touch again on PCI and payment applications, as I keep getting scared out of my security hat. There’s a fantastic tech startup group in Seattle and somebody recently asked about processing credit cards on the mailing list. One of the commenters pointed to the Rails ActiveMerchant plugin, which can be used to access payment gateways such as Authorize.NET, Paypal, and over 30 others. The following piece of code, found on the ActiveMerchant page, is what rang some bells in my head when I saw it.

# Create a new credit card object
credit_card = ActiveMerchant::Billing::CreditCard.new(
  :number     => '4111111111111111',
  :month      => '8',
  :year       => '2009',
  :first_name => 'Tobias',
  :last_name  => 'Luetke',
  :verification_value  => '123'
)

if credit_card.valid?

  # Create a gateway object to the TrustCommerce service
  gateway = ActiveMerchant::Billing::TrustCommerceGateway.new(
    :login    => 'TestMerchant',
    :password => 'password'
  )

  # Authorize for $10 dollars (1000 cents)
  response = gateway.authorize(1000, credit_card)

While ActiveMerchant itself is not a risk, I simply want to reiterate how you use the library is very important when it comes to handling credit cards. This code, if used in the manner above, puts your web server in scope for PCI compliance even if you are never writing the credit card number to disk. While you should be doing nearly everything in the PCI standard anyway in order to properly protect your assets, PCI can be a tricky field to navigate. I’ve said it before and I’ll say it again: if you want to avoid the complexity of introducing PCI compliance into your environment, do not store, process, or transmit a credit card number and use an offsite payment gateway instead.

If you have further questions about this, feel free to leave a comment, contact me (damon at startupsecurity.info), or visit PCI Answers for anything and everything related to PCI including contact information for one of the most knowledgeable PCI resources around, Mike Dahn.

Writing Good Code

What is good code?

One of the challenges for any developer, security notwithstanding, is writing good code. Although “good code” is a bit of a nebulous term, it can consist of proper documentation, a lack of duplication, clean code and code that does exactly what it is intended to do, and nothing else. Failing to achieve that last item is what tends to lead to so many security bugs.


What is bad code?

Writing good code is also essential when it comes to security. As a part-time coder myself, I know it’s difficult to stay in a security mindset when you’re solely focused on getting a certain piece of functionality to work. Often times you might hear yourself uttering things like “well I’ll just do this for now” or “this is such a hack, it will probably never work”. This is exactly the point at which the slippery slope to sloppy coding begins, and commonly ends with code that was not necessarily intended for production…but will probably make it there anyway.


What should I watch out for?

As a developer with the paranoid security hat on, I have the following couple tips. If you find yourself going down this path, make a note to add a #TODO security task for yourself to go back and review the code that you’re writing. Further, don’t forget security when you’re wandering down the path of hacky code. While it may be the slickest thing you’ve written in the past week, hacks are exactly that – and breaks in logic may be a trade-off in security. These type of bugs fall into the “design flaw” category, which are becoming more and more common as issues like SQL Injection are becoming easier to deal with. And it’s not just SQL Injection and XSS to think about. There are other concerns such as authorization, session fixation, replay attacks and cross-site request forgery.

Second, if you do find yourself charting unknown territories and writing some wicked code…get somebody to look over your shoulder. Have a peer review your code both for logic flaws, as well as potential security issues. I’ve been in many situations myself where my mental effort has been focused on the functionality of a specific piece of code and security was the definition of an after-thought. Having somebody else take a look at the code is beneficial both from the “good code” as well as the security perspective.


Are there any tools I can use?

If you’re working on your own, there are a couple sites I know of that allow collaborative peer review. Use those at your own risk, of course and try not to paste intellectual property. ;)

For larger teams where the development environment may not have a built-in code review tool, I saw an impressive presentation at DjangoCon 2008 on an open-source code-review tool called Review Board. It’s built in Django with an MIT license and can be installed on an internal server.

I recently presented at StartPad, a local co-working space in Seattle, on web application security. It was a great talk, mostly due to the great discussion generated by the crowd. StartPad was nice enough to record the presentation and you can find that, as well as my slides, below. Topics covered include: web application security, including the basics of SQL Injection and Cross-Site Scripting, Data Breach laws and even some discussion on PCI compliance. I also did some demos including a SQL Injectable Ruby on Rails app. :) Enjoy!

At my presentation last night on web application security, I demo’ed a SQL Injectable Ruby on Rails application.

One of the questions that resulted from that, somewhat in shock, was how long this bug had existed in a public open-source project. Referring back to the original discoverer, it seems this bug has persisted through the lifetime of the Rails project (i.e. Rails 1.2 and 2.0 were vulnerable as well).

Looking back in time, we can actually see the March 2005 commit where the limit functionality was added to the MySQL adapter. If you have javascript enabled, I’ve pulled out the relevant bits below. The interesting thing to notice is that some sanitization is performed if both a limit and offset parameter exist, but if only the limit parameter exists…no sanitization is done.

There is some good discussion about how to exploit this :limit bug on the Ruby on Rails Security Project blog.

Finally, we can see where this SQL Injection was fixed earlier this year. And if you’re curious, here’s what sanitize_limit does.

That being said, I suppose we could enter into the old argument of whether closed or open-source is a more secure model. But realistically, bugs exist in any project – it’s the process and integration of security into that specific project’s development that determine it’s resulting security and risk profile.

I’ve giving a talk tomorrow at a Seattle co-working space, StartPad, about startups and security. You can find more information and register for the event on the StartPad website: Hacking and Compliance in a Web 2.0 World.

If you’re in Seattle and want to learn about web application security, stop on by!

What: StartPad Countdown 2 — Startup Security: Hacking and Compliance in a Web 2.0 World
Who: Damon Cortesi
When: 6:00 pm, Tuesday November 25th, 2008
Where: StartPad offices — 811 First Avenue, Suite 480, Seattle, WA 98104
Cost: Free!

Pizza and drinks will be served.

One of the things any organization should be prepared for is a potential “incident”. The definition of incident can vary widely, but it can be anything from an unauthorized internal data access to a “hacker” breaking in.

Monitoring is a big part of detecting incidents and perhaps a post for another day. If you do suspect somebody has unauthorized access to one of your systems, though, there are certain steps that should be taken. I recently came across a good cheat sheet for server administrators that should be kept handy in the event of an incident. There’s also a cheatsheet for those responding to potential incidents.

I came across these cheatsheets over on the SANS Internet Storm Center blog, a good feed to have in your reader to keep up-to-date on the latest security incidents around the net.

Enjoy, and hopefully you won’t need to reach for these in the near future. But they are good to have on hand!

ZoneAlarm Pro, Free Today

ZoneAlarm Pro, a personal firewall, is free today. Details at zonealarm.com.

Personally, I’m a Mac guy and both OS X and XP/Vista have a firewall built in, but ZoneAlarm does offer some better granularity and access control. When I was a Windows guy, though, my personal favorite was Sunbelt Personal Firewall (formerly Kerio, formerly Tiny). Yes, I am anal retentive enough to restrict my browsers outbound access to ports 80 and 443…

On the Mac, I do like Little Snitch for outbound access control and monitoring.