These five security checks are easy to automate
The web is a scary place, if you are running a server or developing a web application. Fortunately some checks to make sure your application and server is safe are very easy to automate and even execute regularly as part of your CI/CD Pipeline or post-deployment process.
Although these checks will not find every possible security flaw in your application, automating these you can free up time for you or your security team, that you can spend on more thorough checks that are not so easy to automate.
Check your dependencies for vulnerabilities
Chances are your Software uses open source or even closed source libraries to get stuff done. These dependencies often deal with the nitty-gritty details for HTTP, SSL and other internet protocols for you. And that’s why it’s especially important to keep these up-to-date and patched, otherwise you will be using components with widely known vulnerabilities. It’s a well-known vulnerability like this that got Equifax and caused one of the biggest data breaches in history.
What’s sad about this is that these vulnerabilities are usually easy to fix, by simply updating libraries to a newer version. And it’s also easy to automate the detection of vulnerable dependencies. There’s plenty of tools out there, that scan through the files you use to manage your dependencies anyway to find out what libraries and versions are vulnerable to known attacks. One such tools is the the OWASP Dependency Check another is Synk. Run these tools regularly and keep an eye on emerging vulnerabilities.
Now I said it’s easy to fix but sometimes your application is on a platform that is no longer supported. In that case it’s high time to start migrating it to a newer platform or if that’s not an option to isolate it from the web and make it inaccessible or replace it completely.
Check your web servers for accidentally exposed ports
It’s also too easy to expose some internal service to the public by accident. Even though your firewall configurations may look fine Software like Docker may surprise you by opening ports that don’t show up in UFW. These misconfigurations may lead to exposure of supporting services such as Memcached or Redis to the public internet. While this may not actually leak sensitive data, it’s still a vector for bad guys to do bad stuff like finding your exposed Memchaced server on Shodan, a search enginge for exposed services and using it to execute amplified and anonymous DDoS attacks on other servers.
The most common tool used to check for this kind of exposure in the Unix world is
nmap. There’s also tools like Gauntlt and Serverspec that specialise in automating these tests for vulnerable server settings. It’s easy to integrate these into a CD Pipeline or as post-deployment smoke test in order to make sure only the ports that absolutely need to be exposed to the web are accessible to the public.
Check for weak SSL/TLS connections
TLS (formerly known as SSL) is evolving at a rapid pace these days. Driven by the Snowden revelations and the availability of free server certificates, encrypted HTTP will soon be the standard protocol for Internet connections. I am not aware of any reason not to use TLS any more but many reasons to do so.
In recent years attacks such as POODLE and BEAST and others have been mitigated by a newer protocol version of TLS. Bigger key sizes are getting less and less of a burden on modern hardware and the ephemeral Diffie-Hellman key exchange protocol brought us Forward Secrecy, that is the property that exposure of the server private key will not expose any captured traffic encrypted under that key.
At the same time test services as offered by SSL Labs and tools like SSLyze make it very easy to scan your server and get a feeling for the security of your encrypted connections. There’s also a very nice collection of secure setting for common server software such as Apache, Nginx and others at ciphlerli.st, but please be careful with these, as they might break existing clients. Don’t blindly copy-paste the settings unless you made sure, your clients will still be able to connect.
Check for secrets in your source control system
The security of your application rests on the use of secret keys and passwords. And yet the exposure of passwords and secrets is a common way for intruders to gain unauthorised access to systems. These secrets should therefore not be kept as plain text in your source code repository, especially when you open source that same repository at some point. If you want to keep keys or passwords in version control, they should be encrypted with a password that is only known to team members.
For production passwords/tokens most provisioning tools such as Ansible and Chef have features that encrypt sensitive values at rest and decrypt them just for the deployment procedure. For values that need to be available to the whole team, such as AWS tokens, tools like git-secret ensure that these are stored encrypted in source control.
If you are not sure if your repository did contain sensitive values at some point you can also use tools like truffle hog to automatically scan through the SCM history for anything that looks like a secret key or password. If you find something and need to rewrite your SCM history to purge keys, take a look at this handy guide by Github.
Check for injection vulnerabilities at compile time
At the German OWASP Day 2015 Christoph Kern explained how Google approached the systematic eradication of SQL Injection vulnerabilities throughout their code base. The approach they take is limited to Java, but should also work for any other statically typed language. The idea is that, if you can guarantee that all SQL strings are compile time constants and all non-constant String values will be escaped by your SQL library no user provided value will ever be unsanitised. Formalising these rules, you can essentially check for SQL injection vulnerabilities at compile time by using static analysis tools such as Google’s error-prone.
Here’s Christoph’s example to illustrate how Google does this. The following vulnerable SQL statement would be caught as a compile time error, because the
getAlbumsQuery statement is not a compile time constant.
String getAlbumsQuery = "SELECT ... WHERE " + " album_owner = " + session.getUserId() + " AND album_id = " + servletReq.getParameter("album_id");
Whereas the following query is safe and will compile, since the SQL statement is built only from compile time constants and the User ID is set and SQL escaped by the
QueryBuilder qb = new QueryBuilder( "SELECT ... FROM ..."); qb.append("WHERE A.sharee = :user_id"); qb.setParameter("user_id", ...);
This change is probably the hardest of all five, because it might require you to migrate your code to a more secure SQL API, but the assurance of zero SQL injection vulnerabilities as long as everyone uses the API sounds like a worthwhile effort to me. If you fear this may be too much of an effort for your team to undertake, check out my previous post on how you can break down huge changes like this into smaller steps you can do over a longer period of time. Also check out the slides from Christoph Kern for more details on error-prone.
Closing words: better, but still not good enough
While these checks can mitigate or even eradicate some security issues in your application or infrastructure, they can’t fully replace manual security inspection and penetration testing. Your team will still need to stay up-to-date with secure coding standards and learn about building security into the product. The book “Agile Application Security” by Laura Bell, et. al. is a good place to start if you want to establish better security practices with your team and start automating more and more of your security checks.