Wednesday, September 5, 2012

Mobile devs -- what tools are in your bag of tricks?

Software developers are great at keeping their own set of tools around -- that class library, for example, that does the heavy lifting for various functions we repeatedly do. These are usually simple functional utilities that we collect over the years to save us time when we (inevitably) need to do [that same thing again].

Well, security should be no different. To build secure mobile apps, there are certain things that we're just going to have to do, and darn near every single time we write code.

So, what security goodies are in your bag of tricks? Here's some food for thought on some things you might find useful, in no particular order:


  • Protecting secrets at rest --
    Inevitably, we need to protect some data locally on the mobile device. Of course, the principles of sound design should guide us to minimize the data we store locally on the device. Some argue that we shouldn't really store anything of value locally, but our users don't always share that view. So we need to protect data locally: usernames (a la remember me button), passwords (best avoided, but for some consumer grade apps, it's acceptable), session tokens, customer names, and on and on.

    We need a reliable set of tools that help us protect things locally. Both iOS and Android give us some ability to do that, but for times when we cannot rely on the OS, we need more. SQLcipher is one such example. It's an open source extension of SQLite that does AES-256 using the venerable OpenSSL library, and it works on Android and iOS.
  • Protecting secrets in transit --
    Of course, any modern OS and app can do SSL encryption, but things aren't always that simple. Sometimes we want to more strongly verify the SSL certificates on both ends of the connection. Sometimes we want to encrypt data that doesn't play nicely with TCP connections, like Voice over IP data that is best suited for UDP.
  • Server connections --
    We often need to connect to different types of back-end services, and of course those connections need to be established securely. At a network layer, we can use SSL, like I've described above, but at a data layer, we also need to ensure our connection is strong. For example, if we're connecting to an SQL database of some sort, we need to ensure our SQL API is immutable, and not subject to SQL injection and such.
  • Authentication --
    We need strong mutual authentication among all of our application components, of course, but we also need to authenticate users and any other entities our app interacts with. We can use x.509 certificates in some cases. Other times we need to use simple username/password combinations. Either way, though, the authentication needs to be mutual and worthy of trust. We have to avoid mistakes like hard coding credentials into our code.
  • Authorization --
    Once a user or entity is identified and authenticated, we then need to ensure that it is able to get to all the data and resources it needs, of course. But we also need to ensure that it is not able to get to data and resources that it doesn't need -- that it's not authorized to access. That means we need to weave access control throughout our system, and it needs to be consistently applied across our architecture.
  • Input validation --
    All data entering our application, through whatever input source possible, needs to be validated. For example, if we're expecting a credit card number, then our code should validate that a credit card number has indeed been input, and nothing other than a credit card number. That's called input validation, and it's vital we get it right. Input validation problems lead to cross site scripting and a myriad of other security problems, after all. But there are many decisions to make, like where do we perform input validation? Our design time choices can have vast impacts on our application's ability to perform its given tasks securely.
  • Output escaping --
    Any and every time we need to output untrusted data, we need to "output escape" it in a contextually appropriate way. For example, if we're outputting data into an HTML context, we need to ensure that the data itself doesn't contain any HTML instructions (e.g., Javascript). When the data does contain HTML instructions, we need to use an encoding scheme that is relevant for that data context. In this case, HTML encoding.
These are all examples of security functions that pretty much every modern piece of software, including mobile apps, needs to do over and over. It makes sense to have an arsenal of tools available to help with these tasks, and that arsenal should be rigorously tested and reviewed.

If every app developer does this, the world will undoubtedly have more secure software. If every dev organization does it, all the better -- and there's a hidden benefit to doing this organizationally. When we do, code reviews become somewhat easier. Why? Because we're reviewing code for compliance to a set of code patterns. We're making sure our developers are using trustworthy code for these common security functions.

In our Mobile App Security Triathlon, Gunnar (@OneRaindrop) and I (@KRvW) will discuss all of these things, and provide code examples of how to implement them on Android and iOS. Consider how you'd approach each function, and join us in San Jose on 5-7 November, and let's discuss different ways of tackling these issues.

Cheers,

Ken van Wyk

No comments:

Post a Comment