Security

Nothing will scare away your users like an insecure application. Regardless of how many cool bells and whistles you have, when users fear for the safety and privacy of their information they are likely to head towards the hills. In fact, they may even like your application so much they decide to develop a competing product, without the security holes. We’ve discussed a lot of really great information up to this point and we’ve seen how easy it is to integrate popular services into our own web applications through APIs. It’s important we not lose sight of the fact we are acting on behalf of the user and often handling some very important, sensitive, and private information for these users.

We’ve discussed at great length how dangerous passing user credentials through HTTP requests can be and how OAuth helps mitigate the risks involved. While using OAuth does eliminate some obvious security concerns, it is still important to keep security in mind when developing your API driven web application. This chapter will look at common security concerns when providing and consuming APIs and how we can take proper measures to protect our users.

Application Security

Integrating services into our web application allows us to create rich applications that open many doors for our users. Since we’re acting on behalf of our users, there are certain things we need to make sure we do to avoid compromising security.

Token Security

One of the most convenient aspects of OAuth is the ability to allow the users to authenticate with the service they are hoping to use. They also have the ability to revoke access to your application at any point in time. When a user chooses to allow access to your application, you become responsible for handling the token associated to their account. In most cases, the user doesn’t even know you are exchanging their authentication for a token. If a user has an account on an external services compromised, they’ll often have to to through a process of selectively revoking the access other applications have to the compromised service.

There is some diversity in how you handle OAuth tokens, a good part of that depends on which version of OAuth you are using. It might make more sense with the longer lived tokens in OAuth 1.0 to persist these values in a database, while OAuth 2.0 tokens might make more sense to store in a session. Regardless of how you store them, it’s important they stay within your application.

Stolen access tokens and client tokens can lead to a situation where another user can access the API on behalf of the authenticated user. To put it in different terms, an attacker would be able to “login” as another user on the service and access their account for reading, writing, updating, and deleting information. It’s vitally important to store all credentials and tokens securely.

SQL Injection

SQL Injection is one of the more well known types of attacks and can be used access data that is persisted in a database. To be clear, the SQL Injection attack in this scenario would be against your application and not the service being used. A SQL Injection attack happens when data is inserted directly into an SQL query without being sanitized beforehand. The results can be disastrous and can vary based on the motives of the attacker.

When an SQL Injection attack is successfully executed, data can be deleted and additional data can be gathered from databases that should never be exposed to the outside world. Obviously, if you are persisting access tokens in the database, this can result in exposing all the stored access tokens to the attackers.

To mitigate these types of attacks, a best practice is to always use prepared statements. In PHP, extensions like PDO and MySQLi offer this functionality and it goes a long way in protecting your application and database. Another way to mitigate these attacks is to validate all input values every single time before querying the database. Validating can be as simple as understanding types of values you are expecting to get and abandoning the query if something different from what you expected is provided. Validation is a strong step in preventing attack data from even making it to your query. PHP’s built-in filter_var and related functions can help here.

Lastly, it’s very important you handle errors correctly. SQL errors that output to the browser provide a lot of information attackers can use to gain more information about your database and table structure. It’s important to understand what happens when a query fails and ensure you aren’t giving the attackers the ammunition they need to successfully attack you. The less an attacker knows and can discover about your stack and the software you are using, the more difficult it is for them to attack you and the more likely they move on to attacking easier targets.

File System Vulnerabilities

The one predictable thing about web applications is they run on a server and the server can access everything your application needs to run. It’s important to understand how we structure our application on the file system. One of the major concerns is storing configurations in publicly accessible location or in the web root. When configurations and other information is accessible to the public, it can lead to database configurations and API Client Credentials being compromised.

The Web Root or Document Root is the directory from which your web server is configured to serve to requests.

File system vulnerabilities can take different forms, and everything from configurations to session information can be stolen if your file system is improperly secured. When you are setting up a server for production use, it’s important to understand the best way to secure your file system from attackers. This includes everything from what you put in the web root to where you store PHP sessions. If you are unsure of the best ways to do this securely, I would implore you to hire a security expert to assist you in getting your file system set up correctly. It might cost you up front, but it is money you can easily justify spending since recovering from a security breach can be more costly.

Access Control and Scopes

As the creator of an application it’s important your access control is set up properly. Obviously, allowing authenticated users to see the private information of other users is not a situation you want to find yourself in. In addition to leaking presumably private user content, this can lead to an account being hijacked. It can also lead to the leaking of OAuth credentials.

Scopes are another important aspect of security related specifically to OAuth. It is important to only grant access to the set of scopes necessary for your application to function properly. Granting access to scopes your application isn’t actively using is a very poor design choice. If OAuth credentials are hijacked, an attacker can gain access to parts of a third-party service they shouldn’t have.

For example, if your integration with a service only requires you read data from the service, make sure you don’t have scopes set allowing a user to write or delete data. Early in the application development cycle, you may be unsure of what scopes your user should be authorized to use. In this case, it is important to selectively add and remove scopes throughout the process. It’s a topic that should be revisited often and have adjustments made as necessary. Every scope you include should be justifiable in the context of your application. If you find your scope needs to change after you have authenticated users, generating new access tokens is a relatively trivial task, you should do this when necessary.

Social Engineering

There are certainly a lot of responsibilities that fall to application developers when it comes to securing user data. There are also some very important things to be aware of if you are using an application. While the movies might portray computer hacking as a highly technical endeavor, a lot of information is given away for free in social engineering attacks. Some of these attacks can be highly technical, such as phishing or spoofing, while others are as simple as a phone call or email.

To this point, a vast majority of the information provided is centered around application developers securing data; it is vitally important we know how to protect ourselves as well as users. This section is going to focus solely on ways we can protect our information and should hopefully raise our sense of awareness on how other people may try to get information from us.

Phishing

Fraud and stealing user data can be very lucrative; it’s one of the reasons so many attackers will go to great lengths to trick us into giving up sensitive information. A phishing attack happens when an attacker poses as a credible business, or perhaps even the service we are using in order to make us feel comfortable about giving them information.

Often times phishing websites spend a great deal of time and care in making their application look very similar to another service in order to fool users. They trick visitors into thinking they are providing their credentials or API information for completely legitimate purposes such as updating account information or verifying an account is still active. In some cases, they may even tell us they need our information because our account suffered a security breach and users need to re-verify their identities. This works, with alarming frequency, because it sounds legitimate and users will do anything to protect themselves and their data. Little do users know, the attack is actually being carried out as he or she types their username and password into the provided fields.

A lot of services have gone out of their way to include phrases like “We’ll never ask you for your credentials” in their emails. This is helpful when users are deciding whether to fill out that form or not. While the majority of these attacks are looking for usernames and passwords, don’t rule out the possibility of one of these attacks targeting Access Keys and/or access secrets. Right now, it’s not the main attack vector, but over time you may find attackers looking for that very information.

Spotting a phishing attack can be tricky at first, especially when they’ve done a good job replicating the look and feel of the application. You may actually be familiar with the graphics, layout, and wording on the spoofed website. To mitigate this attack, it’s always important to check the URL shown in the browser location bar. If the URL doesn’t contain the hostname of the service you are using, it’s probably fake. If you have any doubt in your mind about whether the site is legitimate, you’re better off closing it and not providing the requested information. You should also be able to email the support staff at the service, as they will likely be aware of the company’s policy of asking you to provide your credentials.

Phone Calls and Emails

When done badly this type of attack is really obvious to detect. The problem is the successful attackers aren’t bad at it. Attackers are keen at getting whatever little information they can, and they know how to use it to their full advantage. If someone were to call you and ask for your username, password, access token, etc. you would hopefully have enough sense to not share it information with them.

What if someone called as a representative of MySQL and asked you to take a quick phone survey regarding your satisfaction with the product? If you are willing to offer up the information, you might reveal you are in fact using the product, what version of the product you are using, and maybe even some details about how you are using the product. All this information could be extremely valuable to attackers and it may give them the information they need to successfully execute an attack on your application or probe further. A good piece of advice when dealing with “vendor” calls is to avoid giving out any information on the phone and letting your superiors know the call was made. Never give out information to people that have called you seeking it. A survey may seem like a legitimate reason for a call, but keep in mind, that is what makes the attack so successful.

User IDs

For a while using auto-incrementing integers was all the rage when it came to identifying users internally. As we’ve learned, this provides a lot of information to would-be attackers and gives them a much better understanding how our data is structured. As we’ve seen, we should not be giving attackers any sort of information. For example, if you somehow expose user IDs in a URL, an attacker can discern how many users you have by simply incrementing the user ID until they receive a 404 Not Found status. This can be used by attackers to scout whether your application is worth the time and effort it takes to attack. While this might not seem like a huge deal if you run a pretty a small application, I’m going to assume most applications are developed with an intent on being popular and well-used.

The other danger in this regard is it allows attackers to collect data on every user in your database by incrementing the ID number. We certainly strive to make our applications as user and developer friendly as possible, but we stand to reveal a lot of information in this model. A better application security practice is to generate random hashes for each user and to use them in place of auto-incrementing integers as external identifiers. These random hashes are just that–random. They are not hashes of the auto-incrementing integers and they are not hashes of a combination of easily retrieved data; they are randomly generated.

$id = md5(openssl_random_pseudo_bytes(128));

By using hashes, we gain more control over our application and keep very important information close to the vest. Auto-incrementing ID’s are often used because they are much easier to generate, required by the database, and essentially do the work for us. I would encourage you to take the steps necessary to move away from integer IDs to using hashes or to plan on using hashes in a new application. Security isn’t always the most time-efficient practice, but any attempt at keeping our data away from attackers is time well spent. Any information the users need to know should be made known to the users appropriately. If you can’t answer “Why would a user need this information?”, they very well may not need it at all.

Token Expiration

Throughout the book we’ve learned how access credentials are generated. With a little practice this becomes quite trivial. There’s always a concern that by requesting new tokens we are bothering the user or degrading the user experience of our application. There’s a very fine line we walk between security and user experience, and it’s important to err on the side of security as much as humanly possible.

Tokens, as we know, can be stolen and obtained through nefarious means. It’s imperative we have a way to revoke those tokens when they are stolen. It’s also important we not let them sit around forever. A design feature which makes OAuth far more secure than passing our credentials across the Web is the fact they are only valid with the client credentials we’re using. This means the lifted tokens do not provide carte blanche access to all of our information in any context. While this is good, our credentials are handed over to us for a very specific reason. access secret was given that name for a very particular reason–it’s supposed to be a secret. It’s quite possible our tokens have been stolen and we’ve not been able to see the full effects of this thievery yet, but what is important is that we have some way to invalidate them.

The most practical way to invalidate tokens is to expire them. Once they’ve existed beyond the predetermined amount of time, they become utterly useless. This is one of the scenarios which might cause us somewhat of a usability concern, but rest assured, an access token can be obtained or refreshed in a way that’s not intrusive. When a token expires, any request sent using that token should be unsuccessful. An expired token could lead to an Unauthorized status from the server and serve as notice to make a request for a new access token.

The OAuth 2.0 specification makes several mentions of access token expiration, which indicates that while an attack vector may be hard to visualize, generating new tokens on a regular basis is a good practice. In the long run, it’s a situation where we should focus on the service and security we’re providing to the user instead of focusing on the the time we’re spending to implement the solution. Security is never easy, but invalidating tokens regularly you gain some peace of mind, and decrease the likelihood stolen tokens will lead to the compromise of your user’s data.

Conclusion

This chapter explored many different ways our data can be compromised. While not all of them relate directly to OAuth as a protocol, some of these attacks can be used in tandem to cause us problems. It’s important to point out we should be writing software with security as a primary concern in our mind. This chapter about security is by no means exhaustive when you consider all the ways attackers try to manipulate and steal our data. I highly suggest investigating the topic thoroughly before you start working on your next application. You should also have a security audit performed on any existing codebase to identify vulnerabilities, and so you can take the necessary steps to protect your users.

Whether we’re writing or integrating web services, it’s important to remember we as developers are in charge of security. It’s not up to anyone else. If we aren’t looking out for our users and our data, I guarantee no one else is either. Security is not a bolted-on feature. Rather, it is a mindset we must always be in so we can provide secure, useful software. If nothing else, this chapter should open your eyes to the vital task that lies in front of you as you build your applications.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.6.75