Threat Vectors and Software Security: Securing the Environment
In part 2 of this series on software security, we explored how DevOps plays a key role in securing your software. While they take some time to set up, automated processes provide significant ROI. By pulling repeated processes out of the hands of your employees you can ensure consistent, secure and reliable outcomes. Next, we’ll have a look at what goes into securing the environment in which your application runs.
Simply put, the environment is where you run your software applications. You may physically host software in your office or, more likely, in the cloud. Whichever the case, it’s important that underlying infrastructure and network are configured with security in mind.
In this article we’ll have a look at the overall picture and then narrow into the specifics. First, we’ll look at the overall network and how you separate out your environments. From there, we’ll get into what you should be doing on a VM-level basis. A recurring theme in this series is the importance for security to be in place from start to finish. Even one mistake can compromise the rest of your efforts.
Firewalls and Security Policies
Your first line of defense in a secure network is a firewall. A firewall enables you to control and monitor data entering and leaving your network. You’ll want your firewall configured with a set of security policies. These policies can be simple, like only allowing traffic over HTTP/HTTPS ports into your network. This prevents someone from accessing the network over a different port, and their requests will be rejected. Simple policies can be incrementally expanded to do more, like rejecting requests with no UserAgent string – a common signature of bots trying to access the network. On the flip side, a misconfigured firewall can lead to data being stolen which Capital One found out the hard way.
More sophisticated firewalls can look for malicious attacks, like many requests from a single source, and block it out before it hits your internal network. They may even utilize AI to monitor traffic patterns and dynamically update rules based on that data. For instance, if there is a noticeable change in the source location of heavy request traffic, that could be an indicator for an attack that you can preemptively avoid.
Keep Your Network Secure and Closed
Your application runs in a network, and you need to decide where exactly in that network your application runs. Will it be in a space that is publicly accessible? Why? If your application doesn’t need to reach out to the Internet, why give it Internet access? For example, the machine your database lives in should almost never be available publicly. It should reside in a private subnet and application servers needing access to it should be given access to that subnet.
Along those same lines, applications should only be able to communicate with other applications on a “by need” basis. By reducing the amount of exposure points of your network, you help insulate parts of your environment in the event something does become compromised. In other words, the number of ways an attacker can get in becomes extremely limited.
Isolate Production and Test Environments
It should go without saying but your production environment and your test environment should in no way, shape or form have access to each other. Your production environment should be locked down as much as possible. Pointing a test environment to production data is never a good idea, even if it makes debugging easier. If you need to access production data in a lower environment, you should always pull down a copy of the production data, sanitize it (to remove any sensitive content) and then put it into the test environment.
The test environment is just that. It’s filled with unverified code and data that that hasn’t passed whatever security audits you have in place. By cross-pollinating that environment with production data, you create additional risk and exposure. In fact, if you’re running in AWS cloud, a good practice is to create entirely separate accounts for these environments. This creates some additional administrative complexity, but it helps to illustrate how cross-pollination should be avoided.
Least Privileged Access
Access to each environment, especially production, should strictly adhere to an as-needed basis. Your front-end developers who don’t know (or need to know) how the application runs on the server should not have server access. The same guidance applies to other developers or operations individuals who set up and run the environment – they should not have access unless they need it. And even then, access should be explicitly granted for a timed interval to perform a specific task after which their access is revoked. There are tools out there that can help with this. For instance, if you are in AWS, you can use STS to create temporary credentials that will expire after a set period, removing the need of remembering to revoke credentials once the task is complete. This also provides a series of checks and balances, where no one individual can perform risky operations without another individual signing off.
Rotate Keys
Keys should constantly rotate. When access keys are constantly swapped in and out, if one becomes compromised, it won’t be an ongoing liability. Even for internal applications that aren’t exposed to the Internet, you should have rotating keys that allow those applications to communicate. The hardest key to crack is the one that’s constantly changing. And if people don’t generate the keys, then they can’t leak the keys.
Ensure OS/Software is Updated Regularly
What operating system (OS) version is your software running on? Were there security patches put out recently for it? Has the OS reached its end of life? These are all questions you should be asking regularly. New vulnerabilities are found all the time for the OS your application is on, and security patches are put out to correct those. According to CVE, the number of vulnerabilities has been steadily increasing over the past 5 years. By not patching your OS you leave yourself open to attacks such as remote execution, elevation of privileges or information disclosure.
The same goes for the languages and frameworks your application is built on. Are you still running Java 8 when Java 11 is out? Why? Each framework in your application should be monitored for security updates and have them regularly applied.
Looking Ahead
So now we’ve secured everything around your application. Your business processes are in place, your code and deployment pipeline are automated, and your environment is secure. There’s one thing left to do – secure the application itself. In the final part of this series, we’ll review the ins and outs of making sure your application is as strong as it can be.