Introduction

It’s highly likely that your account details and possibly your personal information have been stolen. In 2014 Yahoo had 3 Billion user accounts compromised. Last year Marriot reported 500 Million, including passport information.

Imagine being a developer who worked on those systems.

You can never fully protect a system because ultimately it may not be a hardware, firmware or software issue – it may be a wetware issue. Humans. We’re fallible, forgetful, busy and in some cases downright clever and nasty. You can, however, seal off every hole you can find and put in place practices that mean even if a one of those clever and vindictive (or bored-with-too-much-time) humans gets in, they still leave empty handed.

If you work on a system that holds precious data you need to equip yourself with some basic skills. If you want to be considered for roles that may involve the processing of sensitive data you need to demonstrate you already have these skills. The following is a quick checklist of security issues, tips, potential holes and gotchas that you should know cold.

Common attack vectors

  1. SQL Injection. The family favourite.
    The old classic

    string query = "SELECT * FROM Users WHERE Name=’" 
                 + user_input("Name") + "'";
    DataSet results = command.Execute(query);

    You take input from your users and pass it directly in to a Database query. Let’s suppose the user inputs ” Fred'; Delete FROM Users; -- “. Your query now becomes:

    SELECT * FROM Users WHERE Name='Fred'; Delete FROM Users; --'

    No more users in your User table. Or they request all your users. Or they update Information. Or… You get the picture.

  2. OS Command injection.
    Conceptually similar to a SQL Injection

    string command = "compress " + user_input("filename")
    execute(command)

    And of course the wiley user enters ” fakefile.txt || rm -fr * ” so the command you’re about to execute looks like

    compress fakefile.txt || rm -rf *

    Which will, assuming there’s no such file called fakefile.txt, delete everything in the current folder including subfolders. Oops.

  3. Application command injection aka Uncontrolled Format String
    Another variation on a theme. You allow user input to be passed to an application that is then executed dynamically:

    var command = "print('" + user_input["name"] + "');";
    exec(command);

    What if the user inputs name as ” gotcha'); nefarious_command_of_doom(); // “? The resultant commands executed would be

    print('gotcha'); nefarious_command_of_doom(); // ');

    …and goodbye goes that Christmas bonus.

  4. Buffer and integer overflows. Your cup runneth over
    A buffer overflow occurs when you try and fill a space with more data than it’s expected to hold. You have a character array of size 20 and you try and write in 30 characters. Those last 10 characters will overwrite whatever goes after that array.

    Normally this will simply result in bad data, an execution error and/or a program crash. However if you’re patient and get it right then you can overwrite the stack return address – the address of the next instruction to be called after a method returns – to have the program continue execution from anywhere you want.

    As an example your nefarious user might overfill an array with garbage up until it reaches the point in memory containing the next instruction to be called. At that point the user ensures the data they are filling the array with contains a value that, when interpreted as the “next instruction”, will point to a set of subroutines within the data. They now run the show and pillage your application’s data or execute system commands using the privileges of the current application.

    Integer overflow occurs when you perform operations on an integer whose result exceeds the limits of what that integer can store. For example if your integers are 32 bit then they can represent unsigned values between 0 and 4,294,967,295. If you add 1 to 4,294,967,295 you don’t get 4,294,967,296. You get an overflow and the integer value will wrap back around to 0.How is this a problem? Suppose you let your users tell your program how many rows of data they will enter with each row being, say, 256 bytes in length. You allocate the memory required and then store the data provided by the user. If your user enters 16777216 ( = 232 / 256) then the total size will be 4294967296 (= 232) which wraps around to 0 in an unsigned 32bit integer. Any data now written to the 0-sized area that’s been allocated will result in a buffer overflow.

  5. Cross-site script injection (XSS)
    Another injection attack caused by not properly sanitising a user’s input.Suppose you have a web application which allows a user to enter their name, and then that name is displayed on the page

    <input type="text" id="NameInput" onchange="displayName(this);" />
    <span id="NameDisplay" ></span>
    
    <script>
    function displayName(element) {
        var name = $(‘#NameInput’).val();
        $(‘#NameDisplay’).html(name);
    }
    </script>
    

    Each time the user types a character in the NameDisplay input box the displayName method is called. This method grabs the value entered by the user and outputs it directly as raw HTML.

    If the name the user entered happens to be a valid piece of JavaScript that reads the users cookies, or makes calls to webservices on behalf of that user using the users credentials then we have a problem.

    A relative of this is CSS injection whereby CSS is injected by the user using the same method as XSS. In this case it’s not JavaScript that will run: it’s CSS commands. That might seem benign except that IE’s expression()function is an open door. Another possibility is CSRF tokens (a special value used to protected against Cross site script forgery attacks – see below) could also be extracted using CSS selectors.

  6. Cross site script forgery (CSRF)
    A simpler attack whereby an attacker tricks a user (or the user’s browser) into executing a command without the users knowledge.For example, if a user is logged onto a web site and that site uses cookies to remember the login status of users (so they don’t have to keep entering their username / password each visit) then an attacker could send an email with a button “Claim your Prize!!!”. The address the button directs the user to is actually the website that the attacker knows (or guesses) the user is logged on to.

    If the link is “https://www.awesome-site.com” then no damage has been done. However, if the link was crafted to be something like https://www.awesome-site.com/delete-my-data (assuming delete-my-data was a valid command a user may wish to invoke in certain cases) then the attacker has tricked the user into wiping out their own data.

  7. Missing authentication and/or authorization for critical functions
    This isn’t an attack as much as it’s the equivalent of leaving the front door unlocked when you go on holidays. If you have pages that may expose sensitive data, or methods in applications that affect or expose sensitive data, you need to control access to those pages and methods.
  8. Allowing dangerous file types (eg scripts) to be uploaded to web apps
    Uploading files to a website is great: you can store images, music files, code samples, or even upload fully functioning scripts that when executed within the application domain of the website will allow the uploader full and unfettered access to everything on your site: your file system, your web servers, your database servers – everything.Yeah…no. Not a great idea.
  9. Use of broken, compromised or inappropriate algorithms or unpatched packages.
    This one comes down to ensuring the tools you use are safe and appropriate. Using a cryptographic algorithm to encrypt sensitive data is no good if the encryption is easily cracked. Using a fast or high collision hashing algorithm to store passwords is no good because it enables brute force attacks. Using packages in your applications that have fundamental security issues in themselves is going to end in tears.
  10. URL redirection to untrusted sites
    This is a phishing attack where a site exposes the ability to craft a URL that will redirect the user to any URL of their choice. For instance, suppose we have a site www.awesome-site.com that exposes a command “go” that redirects the user to any page requested. If an attacker tricks a user into clicking something like

    https://www.awesome-site.com/go?url=www.not-so-awesome.com

    Then the user will first visit awesome-site.com then be redirected to not-so-awesome.com. If not-so-awesome.com has been setup to look exactly like awesome-site.com, and pops up a login dialog when the user visits, then the user may think they are on awesome-site.com and enter their password. Not-so-awesome.com then stores that password, providing the attacker with the user’s credentials.

  11. Path traversalSuppose you have a page on a website that allows a user to view a file stored on the website:
    https://www.awesome-site.com/view?file=myfile.txt

    This may be safe if you have nothing sensitive in the website’s directory, but if the user happens to specify the filename as ../secretfile.data then the view command is being asked to load up a file outside the web application. In fact they could load up any file on the system if they knew the correct path. For instance the password file.

  12. Exposing too much information in error messages
    This is another house keeping item. You may have error handling like

    try
    {
        MyMethod();
    }
    catch (Exception e)
    {
        Response.Write("An exception occurred: " + e.Message);
    }
    

    If the exception’s message contained path information, information on database connection parameters, database table names, credentials or any number of things best not disclosed to users then you open your application up to exploitation.

What about the things you can’t control?

There will always be things that you, as a software developer, can’t control or stop. You may, however be able to mitigate the damage or at least curl up into a ball until the kicks and punches stop and you can dust yourself off.

  1. Network attacks such as DoS, DDoS, TCP SYN Flood attack and related
    This is a class of attack designed to pummel you into submission and prevent legitimate users from accessing your site. Methods to handle these attacks include correctly configured firewalls or by using DDoS mitigation services such as CloudFlare to handle and disperse the load.From a developer point of view never expose a page that, when called frequently, will bog down your server so much that your readers will be locked out. Add request throttling or simply take the page offline if traffic load exceeds a threshold.
  2. Users falling for phishing attacks
    There’s a lot you can do here: educate your users, remove phishing attack vectors, enforce 2-factor authentication and strong passwords. However, people are still people.
  3. Viruses and malware
    Follow good sanitation procedures such as not downloading anything from the internet directly onto a production server and restricting shares and access to production servers and you will be halfway there. Ensure you have a reputable anti-virus system and you’ll be even further along the road to safe practices. Just ensure those anti-virus and anti-malware systems don’t add such a load as to compromise your services.

On never needing to be secure

If you need to store sensitive data or if you are on a system that itself is vulnerable to issues such as path traversal, or if you use a database and can’t lose that data then you need to be prepared to be secure. You need to

  1. Encrypt or hash (with salt and pepper) your sensitive data.
  2. Learn how to identify places where you have security vulnerabilities and then learn how to plug those holes.
  3. Enforce security best-practices on your users. No bad passwords, multi-factor authentication, remove phishing vectors.
  4. Limit brute force and DoS attacks by request throttling
  5. Ensure your network itself is secure both internally and externally, and that all network communication is secure (including HTTPS for your readers)
  6. Educate and hold accountable your internal teams of developers and system administrators. Internal audits, logging of issues, proactive threat detection.
  7. Physically and logically limit access to your systems. Host your applications in a secure environment and ensure that physical and remote access is tightly controlled.

Or do none of this. Instead try something completely different

  1. Don’t store sensitive data. Do you really need your users to log on? What about using plugins such as Disqus for things like user comments and get them to deal with the hassle.
  2. Enable your system to be wiped and rebuilt automatically using containers. Someone gets in and wipes all your files or manages to sneak in a malicious file? Nuke the container, fix the vulnerability and the redeploy. Just make sure you have alerts and intrusion detection – you don’t want to notice an issue a week after it’s happened.
  3. Use data storage from your hosting provider (e.g. Azure Tables, AWS database services). This Database-as-a-Service means you don’t have to worry about securing the physical database: you just ensure your application is secure (and again that means SQL injection is still an issue).
  4. Do you really need to store all that data? What about archiving off data (especially user data) that’s old or identified as being no longer valid. And when I say archive I mean backup, offsite, the data and then completely delete the data from the production systems.
  5. Make your site read-only. If an attacker can’t write to your data store then SQL injection attacks are a moot point
  6. Compile your site into a series of static HTML pages. If there’s no script, no database calls, and no actual processing being done then a whole range of security issues are moot.

But back to the real world…

Not having to be secure would be nice but it’s not an option for most of us. Your absolute first step in having secure applications is to understand what you’re up against, and to then learn how to spot those attack vectors in the wild. Once you know about attack vectors, and you can find attack vectors, your next step is to learn how to completely remove, or at worse, mitigate the security issues.

None of it is especially hard to fix once a vulnerability has been identified but it is a learning process. There are plenty of courses, books and videos that will help get you start. I personally am too impatient to watch videos but need to get my hands on the code so I should give a shout-out to Secure Code Warrior who have gamified and self-paced online tutorials that will walk you through all of this step by step.

Not only is securing your user’s data important both morally and from a business point of view, it’s also the law in more and more jurisdictions. In a competitive job market it will be those who differentiate themselves by bringing with them the knowledge and tools to help secure their employees systems that will be the winners. Learn security, bake it in at the core of your applications and keep it top-of-mind at every step of your system’s development and you’ll be well on your way to peace of mind.