“If you can’t stand the heat, stay out of the kitchen.”
Harry S. Truman
Over the last few years there’s been a huge fuss over vulnerabilities in web applications. However, even though almost every internet user knows about the Heartbleed vulnerability discovered in 2014, their knowledge of web security concepts is limited to things like, “I know my password should be long and complicated.” Greater concerns are left to the antivirus software professionals.
Unfortunately, the “ignorance is bliss” approach isn’t good enough to prevent a user’s data security from being compromised. And while you might not care on a personal level — after all, it’s only your data you’re worried (or not) about — taking a negligent attitude towards web security on a business level can be extremely harmful for web‑based businesses, especially when you’re responsible for your customers’ safety.
A malefactor who breaches a certain access level can send spam on your behalf or host illegal content on your server, leaving you to deal with abuse reports. Or, by learning the payment system’s binding, said malefactor can refund all of your orders and erase one month’s profits. And these are only two examples of the havoc that can ensue when security is compromised.
To realistically see the possible outcomes and learn how to avoid them, we need to start from square one and understand what “web security” really means.
This term has various interpretations — but omitting the details, we can say that web security is a combination of three aspects of the so‑called “CIA triad”: confidentiality, integrity, and availability. In other words, web security is about ensuring that data is kept in the hands of authorized users, and that it’s accurate, complete, and available whenever needed.
Let’s start with the triad’s first component — confidentiality.
Confidentiality
How can an unauthorized person gain access to your information? The most obvious way was mentioned earlier: weak passwords. Honestly, the number of websites hacked due to having the same administrator login and password is so huge that it’s funny — in sad way.
The other big problem is the lack of proper access control — in other words, improper interpretation of the roles within a chain of command, resulting in a user who gets access to information that should be restricted from him.
Often times this happens if the protection of sensitive functionality components (i.e. the admin panel) isn’t based on employee access level but rather is just hidden in the application code without any visible access. In other words, instead of properly verifying that the user trying to access the admin panel actually has admin rights, the web application assumes that the fact he knows the admin panel’s URL is enough for him to gain entry.
This is an amateur mistake, one that happens because the application’s business logic wasn’t clear during development. In the presence of ambiguity, developers have no choice but to write filters for the roles (i.e. which users have access to which application areas) at development’s end, creating the possibility that some vulnerabilities were overlooked because the filters implemented late; possibly by two different developers. Therefore, it never hurts to confirm that the authorization module used throughout the application is easy to analyze, and that access is denied by default and restricted to whitelisted names only.
Availability
Once you’ve confirmed that users can only access the areas they’re authorized to, the next step is to ensure your service is available to the user whenever he needs it. Which means you’ll need to start thinking about the types of malcontents that can limit access.
Availability’s arch‑enemy is the nefarious DDoS (Distributed Denial of Service) attack. This attack’s aim is to overload the website with automated queries, thus denying real users’ access to the service. From June 11–13, 2014, hackers froze Evernote in this fashion, leaving users to question whether they should continue using a service that was susceptible to such a debilitating hack.
And here’s something really scary: every web resource is vulnerable to DDoS attacks. However, how many resources it would take to initiate an attack is another story.
Integrity
If confidentiality issues arise because of user error or developmental negligence, then integrity, as well as availability, becomes another hackers’ milieu.
By integrity we primarily mean the malicious substitution of data. For example, a hacker replacing a customer’s bank account number with his own.
Integrity‑related vulnerabilities are extremely tricky because it can be hard to tell whether your website was hacked. For example, an e‑store owner might still receive her customers’ credit card payments, but the related info is also automatically forwarded to the malefactor. This is common in cases of industrial espionage and data theft.
While some systems such as WordPress provide tools for tracking changes by comparing current files with the files in the online directory, this still won’t guarantee your safety.
Some conclusions
You (as a user or as an owner of an internet‑based business) must come to terms with the fact that every web service can be hacked. And even if your code is extremely secure, there’s still the possibility of men in black masks breaking in and stealing your actual server.
Ah, but all is not lost. If the data’s value is less than the cost required for a hacker to obtain it, you can consider your service adequately protected. After all, no one will pay thousands of dollars to hack your personal webpage.
Taking a methodical development approach and paying attention throughout, and using proven, secure anti‑hacking technologies will provide you with a web application that’s secure from most common attacks.
There will always be aspects you can’t control — for example, your host’s vulnerability. The best thing you can do to ensure your own security via your host is to turn your code into something unreadable by obfuscating the libraries and encoding web configurations. This will protect you from standard hacking tools, i.e. reflectors.
If you’re struggling to decide which technology to choose, here’s some advice: choose a recent (but not the newest!) technology; and if possible, choose an open‑source one. The first suggestion will provide you with secure, out&‑of‑the‑box methods, and the second allows you to see the changes made to the technology. Two big negatives of closed systems are: 1) you have no information regarding the system’s encryption and storage, and 2) no knowledge of whether your information will be passed to a third‑party.
Before we dive into more details, let’s summarize our current web security checklist:
- Project requirement analysis is an important development step in terms of application security. Hence your provider must have a complete understanding of your security requirements prior to development.
- Dedicate enough time for security development in accordance with your project’s requirements. This may increase the final cost, but in the end you’ll get a better, safer product. Of course, it’s possible to rework the code later, but no one can promise that it will be cheaper or as effective.— If possible, avoid storing sensitive user data (SSN, credit card numbers, etc.) on your side. Shifting this responsibility to a third‑party and using the APIs of payment providers is preferable. If it’s absolutely necessary that you store this data yourself, then invest significant time in encryption algorithm development and allow this data to be decrypted only for specific back‑end procedures.
- For projects that don’t require a particularly custom approach, pursue out‑of‑the‑box solutions that are available inside frameworks, and CMS supported by large communities. This will reduce development costs — and besides, there’s no need to reinvent the wheel.— Use only time‑tested, community‑backed third‑party components when developing your web application(s) most important parts. Researching these components will increase development time, but you’ll be spared any unpleasant surprises down the road. If third‑party components are lacking, write the most important parts from scratch.— Most recent solutions (MVC, in particular) contain tools for defeating some of the most common vulnerabilities.
- Ensure that your configurations are secure. Many vulnerabilities can be avoided with proper website configuration.
Still unclear how all of this works? Let’s consider some common maladies:
DDoS attacks
DDoS attacks are based on your web servers’ structure. If we omit the hardware details, web servers can be represented as a set of processes sleeping in the background. When a query reaches the servers, one of the processes wakes up, starts working on the request, and goes back to sleep when the client receives the query’s result. The problem is that the number of processes is limited by server configuration, i.e. a server can only handle a limited number of queries simultaneously.
In a perfect world, this wouldn’t matter. But in the real world, some queries can linger for a long time; sometimes forever. This usually happens when the query is fairly complex or has links to internal objects, which leads the process into infinite recursion.
Let’s return to our earlier statement: every web resource is vulnerable to DDoS attacks. The only differentiator is the number of resources a malefactor needs for an attack.
Unfortunately, serious bottlenecks, advanced searches, or a noticeable amount of calculations make it easier for DDoS attacks to freeze a website. This is how hackers typically stage a DDoS attack. They create bots which overwhelm servers with a huge amount of requests. And the more complex these requests are, the less resources are needed for attack.
This is where the struggle between a hacker’s and a server setup’s resources begins. To effectively resist attacks, we either have to increase capacity (i.e. the number of processes in our web server), or optimize performance. The first option is usually cheaper. However, at a certain point maintenance of the server becomes more expensive than reworking the code. A cluster of 30–50 servers is already difficult and costly to maintain.
SQL injections
Even though the SQL injection attack has been around for over a decade, it’s still one of the most common attacks.
Here’s how it works: a malefactor locates an input area on your website — for example, the login and password form. Instead of the expected text, the hacker enters an SQL command containing special symbols. If your application doesn’t filter input characters, your web server will run the input as a command and the malefactor will be able to perform direct queries to the server’s database and bypass network security features. The hacker will be able to execute arbitrary commands on the target server: reading the contents of tables, deleting, editing, or adding data… the possibilities are limited only by the malefactor’s imagination.
In late January 2014, this is exactly how more than 20,000 Bell Canada customer records were stolen, including usernames, plaintext passwords, and credit card data.
Once in possession of logins, email addresses, and passwords, the aggressor is likely to hack a large number of your clients on other websites, because let’s be honest: it’s most likely that the same password will match the same email on other sites. Moreover, possessing email access opens a ton of possibilities for the hacker. For example, he could be possibly hack the user’s PayPal account. Sound crazy? Check out this story: https://goo.gl/V4Ph9i
Unfortunately, even if you don’t store passwords but hash them (i.e. you perform some irreversible calculations on the password to obtain a unique string) and store the hashes, it’s of little help. Although theoretically it would be almost impossible to guess the plaintext password even with the hash, it could still be done by brute force, i.e. by a using dictionary attack, even if you add salt to the hashes (i.e. you combine your hash string with another arbitrary string, making deciphering more difficult). This is another reason to rethink your passwords. The longer and more random, the better.
The fact that a malefactor possesses a strong desire and the resources to decipher and steal data doesn’t mean we should make it easier for him.
What’s the best protection?
Each technology has its own methods for SQL injection prevention. However, they’re all based on the same principles: input constraint and validation, and usage of functions that treat input as a literal value so the SQL server doesn’t see it as executable code.
Also, you should avoid displaying detailed error information in the user database. Don’t let an attacker learn the database structure, the field names, essences, stored procedures, etc.
Error messages allow attackers to better understand the database structure and suggest which commands and scripts are best to implement. For example, the error message may tell the malefactor that his SQL query has the correct database name, but the wrong number of fields.
In the case of SQL injections, there are technologies which protect against such vulnerabilities by default — for example the ADO.NET Entity Framework, in which creating SQL queries is handled by a built‑in library.
XSS‑forgery
Cross‑site scripting, or XSS, is a strong second in the “hacker’s preference” rankings. XSS is actually one of the specific code injection types. However, unlike SQL injection, whose attacks are aimed directly at the database, XSS’ purpose is to ensure that a malicious script embedded in a web page activates itself on the user’s computer. And once it activates, an attacker can access various websites through the user’s authentication or authorization and set about stealing data.
At first glance it seems that to implement a malicious script in a web page, a hacker would first have to bypass the web server’s security. Unfortunately, it can be done much easier than this, which explains XSS’ popularity amongst hackers.
Today’s web resources are filled with constantly changing content that’s often “pulled” from external sources (for example, a Skype plug‑in which highlights the number in the text and turns it into the button that the user can click to start a call. To do this, the plug‑in inserts a piece of html code which does not actually interfere with the site but still might steal the user’s cookie). Thus, in comments to any article on a popular web page there may be hidden a script that, if not pre‑filtered by the server, will run in the browser of each page visitor.
What’s the best protection?
The best protection is to follow this advice: don’t trust any input data from unreliable sources.
During development, pay special attention to input data validation. Although it won’t provide airtight protection against XSS, it will at least help eliminate the most obvious security holes. A simple check of whether the input contains special HTML characters allows you to protect against blatant attacks. Also, it can help in case the input contains some syntax constructions, i.e. URL. Here, as a validation, developers can check the input’s beginning: submitted URLs should begin with http or https. JavaScript is a bad idea.
After validation, you should focus on input escape. This is an important step for allowing users to enter text that includes special characters. Escaping replaces special characters with their entities, which prevents attackers from leveraging the input field to create potentially dangerous HTML tags like script, frame, etc.
But what if it’s still necessary to enable the input to contain java scripts, images, CSS, etc. — in other words, the very information that could potentially allow an XSS attack? In this case you can use Content‑Security Policy (CSP), which provides an HTML header that declares trusted and approved content sources. When using CSP, a user’s browser will load only page content that comes from trusted sources.
Another recommendation (which of course, can’t fully protect against cookie theft but at least makes it more difficult) is to install an additional flag, “HTTPOnly”, which allows you to restrict access to cookie scripts from the client side.
Also, some technologies (for example, ASP.NET) offer built‑in protections against XSS. You should research these.
CSRF — Cross‑Site Request Forgery
CSRF tricks the authenticated user of the web application into running a malicious script that performs actions on behalf of a legitimate user. For example, a CSRF script sends the web application a password change request, and after a successful user authentication the web application fulfills the request.
Another scenario: the malefactor emulates a login form from the user’s bank and leaves a link to it somewhere. Usually the link looks similar to the URL of the bank’s website page: mybank.comlogin vs. mybank1.comlogin, attempting to confuse the user into entering her username and password because she thinks she’s authorizing something legitimate. The entered data is transmitted to the original website, allowing the user to log in there, but in the process the malefactor steals the data. The user, now logged into her normal website, has no idea her data was stolen.
What’s the best protection?
To protect against CSRF, developers can use a variety of techniques including a random token for each session validation request, or random field names in the various web application forms.
Tokens work like this: on our page we place a hidden field where a random ID is created. If our application doesn’t’ receive this ID because someone’s trying to log in from the outside, the application issues an alert.
In some technologies there are built‑in mechanisms for implementing anti‑forgery tokens (MVC). In other cases, this mechanism must be implemented manually or via third‑party solutions.
ASP.NET MVC includes its own set of built‑in helper methods whose unique markers, transmitted with each request, protect against CSRF attacks. These helper methods not only use a mandatory hidden field in the form, but also the cookies’ value, which makes request forgery very difficult.
If you predict CSRF attacks on your application, you should also make sure that the site is not allowed to be put into the frame.
Errors in business logic versioning
Careful consideration of business logic is important in order to preserve your data’s confidentiality and integrity.
Errors when dealing with complex objects, unaccounted competitiveness — these are typical problems associated with business logic.
For example, two managers simultaneously try to modify the same user. One finished editing and saved the result, while the second overwrites the changes and erases the first manager’s work. The same thing applies when an e‑store user adds goods to his basket from two different computers: home and work, for example. Eventually he might discover that his checkout page is a mess: some goods are not visible, the total sum is wrong, etc.
An identical scenario could occur if two managers simultaneously make two invoices with different serial numbers. Even though both will be sent, only one will be visible in their history.
What’s the best protection?
Just manage your application flow from beginning to end. That’s it.
Sensitive data leakage
This vulnerability appears after the website has been hacked, i.e. the attacker already has critical access (for instance, the database or administrator password). To prevent sensitive data leakage, the web application should properly deal with the data and provide it with optimum protection at every level.
If private user data is stored in plaintext or is transmitted through unsecure communication channels, your application is definitely vulnerable; and also if the application uses obsolete cryptographic algorithms or persistent cryptographic keys.
What’s the best protection?
First of all, use SSL to protect sensitive data transmissions.
Secondly, use a strong encryption algorithm. For password storage, use specially‑developed algorithms like bcrypt, PBKDF2, or scrypt.
If there is no direct need for storing sensitive data, avoid it. For credit card payments, you should redirect the user to the payment system or bank page. If it’s impossible to avoid storage, encrypt the data and allow access for specific back‑end procedures only.
Similar to SQL injections, you should avoid providing error information and the causes, and instead redirect the user to a specially created error page.
In sum…
Whether in the real world or the online one, you can never be 100% safe. However, real life‑threats (falling space debris, an escaped tiger, etc.) don’t stop us from going outside. Instead, if we just act responsibly, we can usually protect ourselves from danger. The same thinking applies to our online life.
During web application development, we recommend making a habit of consistently asking yourself whether you are:
- Being vigilant during development
- Not overlooking the business logic layer
- Using secure passwords
- Providing access to the right people
Forewarned is forearmed, and awareness is critical to safe passage online. As long as you strive for optimum security and consciously steer clear of potentially dangerous situations, everything will be a‑ok!