In this article I first try to understand what security is and what are best security practices for web applications.
In my previous article "The challenge for 2019 has just got real" I had set a challenge for myself in 2019: to learn more about securing web applications in general and PHP web applications in specific.
In this article we're going to explore what security means and what basic steps should be considered in providing security. After all we want to incorporate security in our design and development process instead of trying to bold it on at the end.
What is security?
Security is freedom from, or resilience against, potential harm (or other unwanted coercive change) caused by others.This quote is taken from WikiPedia where in my opinion the goal of security is very well described.
- Security should provide freedom for the related party
- Security should create a resilience against harm or unwanted change caused by others
Looking at the goal of my exploration, building secure web applications, I need to understand the basics of good security practices. I found DarkReading: Back To Basics: 10 Security Best Practices where the author lists ten things you need to consider in regards to security:
My interpretation of security best practicesI believe these are good first basics to get started, but I would like to have them ordered differently. In terms of securing a typical web application, I need to look these steps a bit differently.
1. DocumentI should document the design of my application. This means I should detail the platform (a part of) the application will run on, what sort of tools or services should be present and what ports are required. And this should be done for each aspect of the application. If we split up responsibilities of the application, we might want to include which pieces of the application should connect with each other and in which direction.
2. AlignI always tell people that good agreements make better friends. This is why documentation is so important in any endeavour you're embarking on. The documentation should also specify what is expected by anyone on the team so everyone knows who's responsible for what and what will be the result of their work. A good distribution of skills and experience should create an awesome team.
Of course, the people that are part of the team you're working with should feel comfortable in the role they were given and they should feel a valued member of this team.
3. AutomateIf we automate the setup of our platform and application from the beginning, we already have a playbook to get started with those things we should optimise over time like software updates and automated deployments. This automation should set up the infrastructure, remove the pre-installed bulk of services, tools and libraries (clean slate), update the platform to the latest version and install only required components we need on it.
4. SegmentBecause a web application consists of different purpose areas we want to segment these areas as much as possible and apply the concept of single-responsibility. All this is handled by our automation step.
5. LimitSince this segmentation flows naturally into limitation, we can ensure that we define rules how segmented components should interact with each other, what connections we allow inbound and outbound, and which users (if any) should have access to these resources. Again, automation should make this a trivial process.
6. PatchWe need to ensure we're always running the latest version of the OS, library, tool or service we're using and when patches are available, this update should be easy to apply. Considering it's a repetitive process, we should automate this.
7. MonitorAlongside the installation of required OS, tools, services and libraries, special attention need to be put in monitoring of these systems. Upfront you should define metrics that you will measure, how you can distinguish normal telemetry from abnormalities and how you're going to alert on these abnormalities.
Given that you can not secure a system 100%, you need to be able to discover intrusions and have a remediation plan ready.
8. VisualiseYour whole infrastructure should be visible from every layer:
- your network
- your platforms
- your monitoring
- your application
9. CheckIn the article the author used this part to enforce policies, but I would disagree. Checking things should be a process where expectations should be verified.
At one point you have a working environment with a variety of platforms, networks, services and applications. If you want to know for sure they are meeting your requirements, testing for these requirements is your only option.
With my background in testing I would suggest that you apply a few testing approaches to ensure the running architecture meets your expectations, preferably in an automated way.
Some of the tools I can think of:
- Provisioner Linting: For each of the provisioners (Ansible, Puppet, Chef, …) there exists a linting tool to validate your automated provisioning scripts
OS Checker: To verify the OS we like to use
nmapbecause we can fingerprint the OS without even accessing the system
Port Scan: A common skipped phase is to ensure that only ports are open required for the application to operate. We also use
nmaphere to ensure that we have the right ports open while others are closed. As a bonus, you can even verify if the segmented elements in your architecture are unreachable
- Performance benchmarking: To ensure we can keep improving our solutions, we introduce performance benchmarking at the beginning of every assignment so we can see when a change we introduce is reducing performance.
- Resilience testing: It's no secret that I'm a fan of the Netflix Chaos Monkey, so I include it to build in resilience from the start.
Common tests: With common tests I group the table-stakes of testing applications. These are:
- Unit testing
- Behaviour testing
- Acceptance testing
- End-to-end testing
- Functional testing
- Security testing: Since this is a new field I need to explore further, I will come back to this aspect in future posts.