In the cloud-native ecosystem, decisions and changes are made on a rapid basis. Applications get adapted and deployed multiple times a week or even day. Microservices get developed decentralized with different peoples and teams involved. In such an environment, it is crucial to ensure that applications are developed and operated safely. This can be done by shifting security left into the developer lifecycle but also by using DevSecOps to empower operations with enhanced monitoring and protection for the application runtime.
In this article, I would like to show you how GitLab can help you streamline your application security from a code and operations point of view by providing you with real-world examples. Before we deep dive into the example, let me first introduce you to the GitLab Secure and GitLab Defend product portfolio which are the foundation for this. GitLab Secure helps developers to enable accurate, automated, and continuous assessment of their applications by proactively identifying vulnerabilities and weaknesses and therefore minimizing security risk. GitLab Defend, on the other hand, supports operations by proactively protecting environments and cloud-native applications by providing context-aware technologies to reduce overall security risk. Both are backed by leading open-source projects that have been fully integrated into developer and operation processes and the GitLab user interface (UI).
Let’s assume we have an application hosting a web interface that allows a user to provide some input. The application is written in Golang and executes the input as part of an external operating system command (os/exec). The application does not contain any validation or security features to validate the input, which allows us to inject additional commands that are also executed in the application environment.
The application is running as containerized microservices in a Kubernetes cluster. The Kubernetes Cluster is shared across multiple teams and projects, allowing us to inject and read data in another application running next to ours. In our example, we will connect an unsecured Redis instance in a different Namespace and read/write data.
Now let us take a closer look at how GitLab can help us detect the attack, permit its execution, and finally help us find and fix the root cause in our code.
Container Host Security helps us to detect an attack in real-time by monitoring the pod for any unusual activity. It can then alert operations with detailed information on the attack itself.
Container Host Security is powered by Falco, an open-source runtime security tool that listens to the Linux kernel using eBPF. Falco parses system calls and asserts the stream against a configurable rules engine in real-time. The Falco deployment used by Container Host Security can be deployed and fully managed using GitLab Managed Apps.
In our example, Falco detects the injected redis-cli command, which is used to read/write data into the unsecured Redis instance.
Falco can now alert operations who can use those valuable insights to define and execute further steps.
A first step to permit access to the unsecured Redis instance would be to permit traffic between the application in our Kubernetes cluster. This can be done by using Container Network Security. Container Network Security is again fully managed by GitLab Managed Apps and can also be configured within the GitLab project user interface.
Container Network Security is powered by Cilium, an open-source networking plugin for Kubernetes that can be used to implement support for NetworkPolicy resources. Network Policies can be used to detect and block unauthorized network traffic between pods and to/from the Internet.
Implementing Network Policies for our application will block the underlying network traffic generated by the attack. The policies can be enabled within the GitLab project UI:
With Container Network Security in place, our attack isn’t able to talk to the Redis instance anymore, but it is still possible to execute other network unrelated attacks using the command injection. Web Application Firewall (WAF) can now help us to increase the security and detect and block the attack at the Kubernetes Ingress level.
The Web Application firewall is also powered by open-source. It is based on the ModSecurity module, a toolkit for real-time web application monitoring, logging, and access control. It is preconfigured to use the OWASP’s Core Rule Set, which provides generic attack detection capabilities. Like the other integrations, Web Application Firewall is also fully managed by GitLab using GitLab Managed Apps.
In our example, the Web Application Firewall detects the attack and is also able to block it:
Blocking the attack at the Ingress level will help us to deny the traffic before it hits our application. To do so, we can enable the Web Application Firewall blocking mode directly from the GitLab UI:
In addition to Container Host Security, we could have used the Web Application Firewall to detect the attack using the Thread Monitoring dashboard within our GitLab project:
The Thread Monitoring dashboard also provides us with useful insights and metrics of our enforced Container Network Policy.
We have now successfully protected our application runtime and ensured that no additional attacks can be executed. But we should also find and fix the root cause to ensure that such incidents are not recurring in the future. This is where Static Application Security Testing (SAST) can help us. Static Application Security Testing can be easily integrated into our project using GitLab CI/CD and then allows us to analyze our source code for known vulnerabilities.
In our case (a Golang application) the code scanning is executed using the open-source project Golang Security Checker. The results are displayed in the Security dashboard of our GitLab project for easy access:
In our example, the code scan has identified the root cause and provides us with detailed information about the vulnerability, the line of code that needs to be fixed, and the ability to easily create an issue to fix it.
Finally, of course, we should also talk to the team running the other application to make sure that their Redis instance gets secured too. We should also verify how the other GitLab Secure features can help to further improve the overall security of the application.
If you like to get more insights on GitLab Secure and Defend and want to see it in action, you are welcome to check out Wayne, Philippe and myself in our session “Your Attackers Won't Be Happy! How GitLab Can Help You Secure Your Cloud-Native Applications!” at GitLab Commit where you can gain further insights on Container Host Security, Container Network Security, Web Application Firewall (WAF), and Status Application Security Testing (SAST).