Cloud basierter Password Manager

von Benjamin Schweizer (bs103) und Max Eichinger (me110)

Abstract

Können Passwort Manager Anbieter meine Passwörter lesen? Wir wollten auf Nummer sichergehen und haben unseren Eigenen entwickelt. Dieser Artikel zeigt auf welche Schritte wir hierfür unternehmen mussten.
Dabei haben wir unser Frontend mittels Flutter und unser Backend in AWS umgesetzt. Außerdem gehen wir auf IaC mittels Terraform ein. Am Ende teilen wir unsere Probleme bei der Umsetzung sowie Erweiterungsmöglichkeiten, welche in Zukunft umgesetzt werden könnten.

Mobile App

Für die Umsetzung des Frontends haben wir uns für das Flutter Framework entschieden. Durch Flutter konnten wir eine gemeinsame Codebasis für alle unsere Zielplattformen (iOS, Android) verwenden. Daher konnten neue Features schnell implementiert und Änderungen konnten sofort auf unterschiedlichen Geräten getestet werden. Außerdem wurde durch einen Integrationstest sichergestellt, dass die App auf beiden Plattformen fehlerfrei läuft.


Die App bietet eine einfache Benutzeroberfläche, in welcher folgende Aktionen möglich sind:

  • Login und Registrierung eines Nutzers
  • Hinzufügen und Löschen eines Passworts
  • Ändern von Passwörtern

Diese Funktionen sind in folgenden Benutzeroberflächen abgebildet

Die Oberfläche ist auf Android und iOS identisch.

Architektur

Grundlegend ist unsere Architektur in Frontend und Backend aufgeteilt. Dabei wird, wie bereits erwähnt das Frontend mit Flutter umgesetzt und das Backend über die AWS-Cloud realisiert.
Alle Anfragen an das Backend werden mit HTTP-Requests an das API-Gateway-Service gesendet.
Die Anfragen der Nutzer müssen einen validen JWT (JSON Web Token) enthalten.
Diesen Session Token bekommt der Nutzer bei erfolgreichem Log-in über den Cognito-Service.
Durch den Token kann in den Lambda Funktionen sichergestellt werden, das Nutzer nur Daten ändern können, für die Sie eine Berechtigung haben.
Die Lambda Funktionen evaluieren die Anfragen und Ändern die Passwortdaten im DynamoDB-Service.
Alle Passwortdaten, welche an das Backend übertragen werden, sind bereits lokal vom Client verschlüsselt worden, um Missbrauch zu verhindern.


AWS Services

Da wir dieses Semester bereits in einem anderen Studienfach Erfahrung mit AWS in Verbindung mit IoT sammeln konnten, war AWS unsere erste Wahl. Außerdem waren wir uns am Anfang des Projektes sicher, das AWS alle unsere Anforderungen erfüllt.

DynamoDB
AWS DynamoDB ist ein vollständig verwalteter NoSQL-Datenbankservice. Dort werden alle Passwortdaten gespeichert.
Um schnelle Query Anfragen zu ermöglichen, ist unsere Tabelle in folgende Felder aufgeteilt:

  • Partitionsschlüssel: User_Id (Eine eindeutige ID für jeden Nutzer)
  • Sortierschlüssel: PasswordName
  • Passwort (in verschlüsselter Form)
  • Beschreibung

API-Gateway

Um HTTP-Anfragen an unsere Lambda Funktionen weiterzuleiten, nutzen wir den API-Gateway-Service. Dieser validiert Nutzeranfragen auf erforderliche Parameter und lehnt bei fehlenden Daten die Anfrage ab. Außerdem wird hier der Token mithilfe von Cognito geprüft.
Wir nutzen 3 verschiedene HTTP-Methoden, um unsere Client-Anfragen zu bearbeiten. Zudem sind alle Methoden über einen API-Key gesichert.

  • Die DELETE Methode löscht ein Password von einem Nutzer.
  • Die GET Methode gibt alle Passwörter eines Nutzers zurück.
  • Die PUT Methode erstellt oder überschreibt ein Passwort.

Lambda
Innerhalb jeder unserer Lambda Funktionen haben wir Zugriff auf den Cognito Authorizer. Dieser bietet uns die Möglichkeit, direkt auf die Daten (User_Id, Username etc.) des Nutzers zuzugreifen, welcher den Request geschickt hat.

PUT Methode:

In der PUT Methode werden neue Passwörter gespeichert oder schon vorhandene überschrieben.

Durch das in API-Gateway angelegte JSON-Schema können wir prüfen, ob der HTTP-Body die erforderlichen Parameter enthält.
Trotzdem kann es sein, dass vom Nutzer ein leerer String (“”) geschickt wird.
Dies ist der erste Validierungsschritt, welcher in der Lambda Funktion ausgeführt wird.


Mithilfe der User_Id und der Passwortdaten können wir nun einen neuen Eintrag in DynamoDB erstellen.
Falls der Passwortname bereits in der Datenbank steht, wird das Passwort überschrieben.


GET Methode:

Die GET Methode liefert alle Passwörter eines Nutzers zurück.

Durch die User_Id können wir an DynamoDB eine Query schicken, welche uns alle Daten von einem einzigen Nutzer zurückliefert.
Dadurch wird sichergestellt, dass ein Nutzer nur auf seine eigenen Passwortdaten zugriff hat.

DELETE Methode:

Die DETELE Methode löscht ein Passwort eines Nutzers.

Auch für diese Methode existiert in API-Gateway ein JSON-Schema, welches den Body validiert.

Mithilfe des Authorizers und des Passwortnamens können wir nun für diesen Nutzer das Passwort löschen. Dafür müssen wir den Partitionsschlüssel (User_Id) und den Sortierschlüssel (PasswordName) angeben und diese Anfrage an DynamoDB senden.


Verschlüsselung

Um sicherzustellen, dass alle Passwörter sicher sind und nur von dem Nutzer gelesen werden können, welcher die Passwörter auch angelegt hat, nutzen wir lokale Verschlüsselung.
Damit der Nutzer die App auf mehreren Geräten gleichzeitig verwenden kann, muss es gemeinsamen Schlüssel geben.

Dieser Schlüssel basiert bei uns auf dem Login-Passwort. Dieser Schlüssel wird bei erfolgreichem Einloggen auf dem Gerät in einem sicheren Bereich gespeichert.

Bei iOS wird der “Keychain Service” und bei Android das “Android keystore system” genutzt. Das Login-Passwort wird zuvor zu einem Hash konvertiert.

Beim Ver- und Entschlüsseln wird ein AES Algorithmus verwendet. Die verschlüsselten Bytes müssen danach nur noch zu einem String encodiert werden, damit man das Passwort leichter zu einem JSON serialisieren kann.


Testing in Flutter

Um alle Funktionen in Flutter leicht testen zu können, haben wir uns für einen Integrationstest entschieden. Damit können wir herausfinden, ob alle wichtigen Funktionen richtig funktionieren. Unsere Hauptfunktionen, welche wir getestet haben sind:

  • Login eines Nutzers
  • Hinzufügen und Löschen eines Passworts
  • Ändern von Passwörtern
  • Ver- und Entschlüsselung
Die Login Prozedur prüft ob die App die richtigen Daten anzeigt, sobald der Nutzer eingeloggt wurde.


Terraform

Wir haben in unserem Projekt Terraform eingesetzt. In unser Ziel war es hierbei, das jeder einfach dieses Projekt bei sich zu Hause nachbilden kann. Dadurch war es aber auch möglich, schnell den AWS Account oder die Region zu ändern und sämtliche Infrastruktur Änderungen zu versionieren.

Main und Cognito

Grundsätzlich haben wir unseren Terraform Code in mehrere Files aufgeteilt. Dabei werden in der main.tf vor allem die Standard Terraform Parameter gesetzt und zusätzlich wird hier noch der Cognito Service aufgesetzt.

Variablen

Im variable.tf File werden für Terraform die AWS AccountID und die Region festgelegt. Diese Daten werden von Terraform benötigt, um die richtigen Account und Region für die Cloud Infrastruktur zu finden.

DynamoDB

Dienst und die Tabellen dem dynamodb.tf File werden, wie zu erwarten, alle DynamoDB Einstellungen übernommen. Hier wird also der AWS Dienst und die Tabellen Felder angelegt.

API Gateway

Im api.tf wird zunächst der normale AWS API Gateway Dienst eingestellt. Danach werden die Methoden der API definiert. Für jede Methode muss zudem angegeben werden welche Lambda Funktion ausgeführt werden soll, zusätzlich kann hier ein Template für die Request hinzugefügt werden. Dadurch wird unter anderem auch der Lambda Code vereinfacht. Jetzt wo in den Methoden alles Wichtige eingestellt ist, wird im tf File die Response erstellt.
Als Nächstes wird in Terraform definiert, wie die API bereitgestellt wird. Dadurch spart der Entwickler die Zeit später in AWS API Gateway den Deploy Butten von Hand zu drücken. Am Ende vom api.tf File wird noch für jede API Methode ein Model / Schema für die JSON Daten angeben. Das hat den Vorteil das Request an die API, ohne diese benötigten Daten, automatisch abgelehnt werden. Und zum Schluss wird noch der Authorizer von Cognito für die API richtig eingerichtet.


Lambda

Alle Lambda Funktionen müssen lokal gespeichert sein. Im lambda.tf File wird dann der Pfad zur Funktion definiert, beim Ausführen von Terraform wird dann ein zip File von jeder Funktion erstellt und in AWS Lambda hochgeladen.
Danach wird werden noch die Policies für das Logging mit Cloudwatch und die Access Rechte für DynamoDB geben.
Am Ende werden noch Permissions für API Gateway und Cognito an die richtigen Lambda Funktionen verteilt.

Probleme

Jedes Projekt hat seine Probleme, so auch unseres. Direkt am Anfang hatten wir viel mit AWS zu kämpfen, den wenn man für die Cloud entwickelt ist Debugging nicht mehr so einfach wie in einer IDE. Man kann dadurch kaum mehr nachvollziehen, was das AWS Setup oder der Lambda Code macht. Am Ende konnten wir das Problem über den Service Cloudwatch lösen. Hier werden alle Aktion geloggt, dadurch können Fehler schnell gefunden und gelöst werden.

Weitere Schwierigkeiten sind beim Arbeiten mit Terraform aufgetaucht. So sollte Terraform eigentlich von alleine alle Dienste in der richtigen Reihenfolge anlegen. Leider geht dies oft schief, und wir mussten im Terraform File von Hand mittels depens_on, die Reihenfolge einstellen. Ein weiteres Problem war, dass AWS beim Erstellen von Services viele Optionen im Hintergrund von alleine einstellt. Später mit Terraform raus zu finden, welche Einstellungen man jetzt genau braucht, war nur über das ausführliche Lesen der Dokumentation möglich.

Beim Arbeiten mit den AWS Dienst Cognito hatten wir Schwierigkeiten mit dem Bestätigen eines Nutzers. Denn Cognito legt zwar alleine alle Nutzer an, aber die Bestätigung des Accounts muss man von Hand gemacht werden. Jedoch konnten wir dieses Problem schnell über eine eigene Lambda Funktion lösen, welche automatisch jeden Nutzer verifiziert.

Erweiterungen

Das Projekt wurde von Anfang an mit dem Zeitlimit eines Semesters geplant. Jedoch könnte man mit weiterem zeitlichen Investment noch viele wichtige Features umsetzen:

  • So funktioniert Flutter auch im Web, leider haben wir innerhalb des Codes viele Abhängigkeiten zu iOS / Android. Jedoch wäre der Aufwand, die App auch als Web App laufen zu lassen, überschaubar.
  • Momentan sind die Passwörter in der Detailansicht noch sichtbar, in Zukunft sollte man diese verbergen und ein Kopierbutton hinzufügen. So könnte man die Passwörter noch besser schützen.
  • Zudem könnte man Power-Usern das Leben vereinfachen, in dem man eine Passwortsuche einbauen würde, so könnten Nutzer aus einem Berg von Passwörtern schnell das Richtige finden.
  • Ein weiter Feature wäre das Ändern des Masterpassworts, hier wäre aber der Aufwand sehr groß. Da jedes Passwort des Nutzers in der Datenbank mittels des Masterpassworts verschlüsselt ist, müsste jedes Passwort neu verschlüsselt werden.

Lessons Learned

Wie im Projekt bereits zu erkennen ist, haben wir viel Erfahrung mit den AWS Diensten: IAM, Cognito, Lambda, API Gateway, Cloudwatch und DynamoDB, sammeln können. Dank Terraform ist uns auch das Konzept der IaC (Infrastructure as Code) jetzt viel greifbarer geworden, zusätzlich hat uns Terraform fast schon gezwungen, von jedem benutztem AWS Service, die wichtigste Einstellung zu kennen. Außerdem konnten wir erste Kenntnisse in der App Entwicklung sammeln. Zuletzt haben wir unser Wissen im Bereich Testing um das Thema Integrations Tests erweitert.

How do you get a web application into the cloud?

by Dominik Ratzel (dr079) and Alischa Fritzsche (af094)

For the lecture “Software Development for Cloud Computing”, we set ourselves the goal of exploring new things and gaining experience. We focused on one topic: “How do you get a web application into the cloud?”. In doing so, we took a closer look at Continuous Integration / Continuous Delivery, Infrastructure as a Code, and Secure Sockets Layer. In the following, we would like to share our experiences.

Overview of the content of this blog post

  • Comparison GitLab and GitHub 
    • CI/CD in GitLab 
      • Problem: Where are the CI/CD settings in the HdM Gitlab? 
      • Problem: Solve Docker in Docker by creating a runner 
    • CI/CD in GitHub 
  • Set up SSL for the web application 
    • Problem: A lot of manual effort 
      • Watchtower 
      • Terraform 
  • Testing 
    • Create a test environment 
    • Automated Selenium frontend testing in GitHub 
  • Docker Compose 
  • Problem: How to build amd64 images locally with an arm64 processor? 

Continuous Integration / Continuous Delivery

At the very beginning, we asked ourselves which platform was best suited for our approach. We limited ourselves to the best-known platforms so that the comparison would not be too complex: GitHub and GitLab.
Another point we wanted to try was setting up a runner. For this purpose, we set up a simple pipeline in both GitLab and GitHub to update Docker images on Docker Hub.

GitLab vs. GitHub

GitHub is considered the original cloud-based Git platform. The platform focuses primarily on the community. Comparatively, it is also the largest (as of January 2020: 40 million users). GitLab is the self-hosted open-source alternative to GitHub. During our research, we noticed the following differences concerning our project.

GitLab GitHub 
Free private and public repositories ✓ ✓ (since Jan. 2019)
Enterprise versions ✓ ✓ 
Self-hosted version ✓ ○ (only with paid Enterprise plan) 
CI/CD with shared or personal runners ✓ ○ (with third-party apps) 
Wiki ✓ ✓ 
Preview code changes ✓ ✓ 

Especially the point that it is only possible in GitLab to use self-hosted runners for the CI/CD pipeline caught our attention. From our point of view, this is a plus for GitLab in terms of data protection. The fact that GitLab can be self-hosted is an advantage but not necessary for our project. Nevertheless, it is worth mentioning, which is why we have included the point in our list. In all other aspects, GitLab and GitHub are very similar.

CI/CD – GitLab vs. GitHub

GitHub: provides the user so-called GitHub Actions. This way, the user does not have to set up, configure or host his runner.
+ very easy to use
+ free of charge
– Critical from a data protection perspective, as the code is executed/read “somewhere”

GitLab: To use the CI/CD, a custom runner must be configured, hosted, and integrated into the code repository.
+ code stays on own runner (e.g., passwords and source code are safe)
+ the runner can be configured according to one’s wishes
– complex to set up and configure
– Runner could cost money depending on the platform (e.g., AWS)

Additional information: HdM offers students so-called shared runners. However, Docker-in-Docker is not possible with these runners for security reasons. In the following, we will explain how we configured our GitLab runners to allow Docker-in-Docker. Another insight was that the Docker_Host variable must not be specified in the pipeline, otherwise the Docker socket will not be found, and the pipeline will fail.

CI/CD in GitLab 

Where are the CI/CD settings in the HdM GitLab?

We are probably not the first to notice that the CI/CD is missing in the MI GitLab navigation. The “advanced features” have been disabled to avoid “overwhelming” students. However, they can be easily activated via the GitLab settings (Settings > General > Visibility, project features, permissions) (https://docs.gitlab.com/ee/ci/enable_or_disable_ci.html). 

Write the .gitlab-ci.yml file

The next step is to write an individual .gitlab-ci.yml file (https://docs.gitlab.com/ee/ci/quick_start/index.html).  
The script builds a Docker container and pushes it to Docker Hub. The DOCKER_USERNAME and DOCKER_PASSWORD are stored as Variables in GitLab (Settings > CI/CD > Variables). 
Tip: If you want to keep the images private but do not want to pay for the second private repository on Docker Hub (5$/month), you can create a private repo and push the images separated by tag (in our case, “frontend” and “backend”). 

stages:
  - docker

build-push-image:
  stage: docker
  image: docker:stable
  tags:
    - gitlab-runner
  cache: {}
  services:
    - docker:18.09-dind
  variables:
    DOCKER_DRIVER: overlay2
    DOCKER_TLS_CERTDIR: ""
    # This variable DOCKER_HOST should never be set, because otherwise the default address of the Docker host will be
    # overwritten and the runner will not be able to access the socket and the pipeline will fail!
    # DOCKER_HOST: tcp://localhost:2375/
  before_script: # Install docker-compose
    - apk add --update --no-cache curl py-pip docker-compose
  script:
    - echo $DOCKER_PASSWORD | docker login --username $DOCKER_USERNAME --password-stdin
    - docker-compose build
    - docker-compose push
  only:
    - master

Configuring Gitlab

Next, we asked ourselves how we could restrict merges into the master. The goal was only to allow a branch to be added to the master if the pipeline was successful. This setting can be found in Settings > General > Merge requests > Merge checks the item “Pipelines must succeed”.

Setting up and configuring GitLab Runner

For this, we have written a runnerSetup.sh.

#!/bin/bash

# Download the binary for your system
sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64

# Give it permission be executed
sudo chmod +x /usr/local/bin/gitlab-runner

# Create a GitLab CI user
sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash

# Install and run as service
sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
sudo gitlab-runner start
sudo gitlab-runner status

# Command to register the runner
sudo gitlab-runner register --non-interactive --url https://gitlab.mi.hdm-stuttgart.de/ \
 --registration-token asdfX6fZFdaPL5Ckna4qad3ojr --tag-list gitlab-runner --description gitlab-runner \
 --executor docker --docker-image docker:stable \
 --docker-volumes /var/run/docker.sock:/var/run/docker.sock \
 --docker-privileged

# Install Docker and give the GitLab runner permissions so that it can access the Docker socket.
echo "Installing Docker"
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install -y docker-ce

sudo usermod -aG docker gitlab-runner

# Restart Docker and GitLab Runner Service
sudo systemctl restart gitlab-runner
sudo systemctl restart docker.service

During the step “# Command to register the runner” we fixed the problem we had with the HdM runners. “–docker-volumes/var/run/docker.sock:/var/run/docker.sock” gives the runner access to the Docker socket. “–docker-privileged” allows the runner to access all devices on the host and processes outside the container (be careful).

CI/CD in GitHub

This is done by adding the following code in the GitHub repository in the self-created .github/workflows/ci.yml file.
Like the previous .gitlab-ci.yml file, the script creates a Docker container and pushes it to Docker Hub. The DOCKER_USERNAME and DOCKER_PASSWORD are stored in the Action Secrets of GitHub (Settings > Actions).

name: Build and Push to Docker.io

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Login to Docker.io
      run: docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} 
 
    - name: Build Docker-Compose
      run: docker-compose build
 
    - name: Deploy Container to Docker.io
      run: docker-compose push

SSL

SSL is used to encrypt the data exchange between the web browser and web server. It thus protects against access by third parties. To set up SSL, it is necessary to have an SSL certificate.

Configuration

We decided to use “all-inkl.com” due to an existing subscription.
In the KAS admin center (after setting up the domains and subdomains), new DNS records can be created and edited (Domain > DNS Settings > Actions (Edit)). Here, a new Type-A record can be created that points to the IP address of the AWS reverse proxy. The email (which needed for verification) can easily be created in email > email Inbox.

Server configuration 

We used the free CA Let’s Encrypt (https://letsencrypt.org/) for the creation and renewal of the SSL certificates. For the configuration, we used the following images: jwilder/nginx-proxy as Nginx Proxy and jrcs/letsencrypt-nginx-proxy-companion as Nginx Proxy Companion (it creates the certificates and mounts them via the volumes into the Nginx Proxy so that it can use them).  
In the docker-compose.yml, the environment variables can now be added for the service “frontend”. 

  frontend:
    image: dr079/webshop:frontend
    build:
      context: ./frontend
      dockerfile: Dockerfile
    restart: always
    environment:
      API_HOST: backend
      API_PORT: 8080
      # Subdomain
      LETSENCRYPT_HOST: webshop.designmyhouse.de
      # Email for domain verification
      LETSENCRYPT_EMAIL: admin@designmyhouse.de
      # For the Nginx proxy
      VIRTUAL_HOST: webshop.designmyhouse.de
      # The Port on which the frontend responds. Tells the Nginx proxy who to send the requests to.
      VIRTUAL_PORT: 80
# Not needed when deploying with reverse proxy
#    ports:
#      - "80:80"

After that, we created the docker-compose-cert.yml file, which starts the Nginx Proxy and the Nginx Proxy Companion.

version: "3.3"
services:
  nginxproxy:
    image: jwilder/nginx-proxy
    restart: always
    volumes:
      - ./nginx/data/certs:/etc/nginx/certs
      - ./nginx/conf:/etc/nginx/conf.d
      - ./nginx/dhparam:/etc/nginx/dhparam
      - ./nginx/data/vhosts:/etc/nginx/vhost.d
      - ./nginx/data/html:/usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock
    ports:
      - 80:80
      - 443:443
    labels:
      - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"

  nginxproxy_comp:
    image: jrcs/letsencrypt-nginx-proxy-companion
    restart: always
    depends_on:
      - nginxproxy
    volumes:
      - ./nginx/data/certs:/etc/nginx/certs:rw
      - ./nginx/conf:/etc/nginx/conf.d
      - ./nginx/dhparam:/etc/nginx/dhparam
      - ./nginx/data/vhosts:/etc/nginx/vhost.d
      - ./nginx/data/html:/usr/share/nginx/html
      - /var/run/docker.sock:/var/run/docker.sock:ro

AWS EC2 instance

In AWS, an EC2 instance (consisting of an Ubuntu server and a security group) can now be created and started with the settings Verify and Launch. 

The IP address of the created instance can now be entered as a Type-A entry under “all-inkl.com”.

Install Docker on Ubuntu

It is now possible to connect to the EC2 instance and run the following commands to make the project accessible through the domain/subdomain. (Note: It may take a few hours for the DNS server to apply the settings. Solution: Use the Tor browser)

# Add GPG key of Docker repository from APT sources.
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

# Update Ubuntu package database
sudo apt-get update

# Install Docker
sudo apt-get install -y docker-ce

# Install Docker Compose
sudo curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

# Give Docker Compose the execute permission
sudo chmod +x /usr/local/bin/docker-compose

# Log in as root user
sudo -s

# Clone project
git clone https://github.com/user_name/project_name.git

# Build and launch project
docker-compose -f ./project_name/docker-compose-cert.yml up --build -d

# Pull images from DockerHub
sudo docker-compose -f ./cloud-webshop/docker-compose.yml pull

sudo docker-compose -f ./cloud-webshop/docker-compose.yml up -d

Watchtower

With Watchtower, updates to the Docker registry can be automatically detected and downloaded. The container will then be rebooted with the new image. Watchtower accesses the Docker repo via REPO_USER & REPO_PASS and checks in the set time interval (— interval 30) if the Docker images have changed and updates them on the fly.
This requires adding the following code to the docker-compose.yml (replace REPO_USER and REPO_PASS with Docker.io Access Token credentials (Settings > Security)).

  watchtower:
    image: v2tec/watchtower
    environment:
      REPO_USER: REPO_USER
      REPO_PASS: REPO_PASS
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    command: --interval 30

Terraform

The preceding steps involve a considerable manual effort. However, it is possible to automate this, e.g., with Terraform. To achieve this, the following files must be written.

main.tf

resource "aws_instance" "test" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = var.ec2_instance_type

  tags = {
    Name = var.ec2_tags
  }

  user_data = file("docker/install.sh")
//  user_data = file("docker/setupRunner.sh")
  key_name = aws_key_pair.generated_key.key_name
  security_groups = [
    aws_security_group.allow_http.name,
    aws_security_group.allow_https.name,
    aws_security_group.allow_ssh.name]
}

output "instance_ips" {
  value = aws_instance.test.*.public_ip
}

providers.tf

provider "aws" {
  access_key = var.aws-access-key
  secret_key = var.aws-secret-key
  region = var.aws-region
}

security_groups.tf

resource "aws_security_group" "allow_http" {
  name = "allow_http"
  description = "Allow http inbound traffic"
  vpc_id = aws_default_vpc.default.id

  ingress {
    from_port = 80
    to_port = 80
    protocol = "tcp"
    cidr_blocks = [
      "0.0.0.0/0"
    ]
  }

  egress {
    from_port = 0
    to_port = 0
    protocol = "-1"
    cidr_blocks = [
      "0.0.0.0/0"]
  }
}

resource "aws_security_group" "allow_https" {
  name = "allow_https"
  description = "Allow https inbound traffic"
  vpc_id = aws_default_vpc.default.id

  ingress {
    from_port = 443
    to_port = 443
    protocol = "tcp"
    cidr_blocks = [
      "0.0.0.0/0"
    ]
  }

  egress {
    from_port = 0
    to_port = 0
    protocol = "-1"
    cidr_blocks = [
      "0.0.0.0/0"]
  }
}

resource "aws_security_group" "allow_ssh" {
  name = "allow_ssh"
  description = "Allow ssh inbound traffic"
  vpc_id = aws_default_vpc.default.id

  ingress {
    from_port = 22
    to_port = 22
    protocol = "tcp"
    # To keep this example simple, we allow incoming SSH requests from any IP. In real-world usage, you should only
    # allow SSH requests from trusted servers, such as a bastion host or VPN server.
    cidr_blocks = [
      "0.0.0.0/0"
    ]
  }
}

variables.tf

variable "ec2_instance_type" {
  default = "t2.micro"
}

variable "ec2_tags" {
  default = "Webshop"
//  default = "Gitlab-Runner"
}

variable "ec2_count" {
  default = "1"
}


data "aws_ami" "ubuntu" {
  most_recent = true
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }
  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
  owners = ["099720109477"] # Canonical
}

ssh_key.tf

variable "key_name" {
  default = "Webshop"
}

resource "tls_private_key" "example" {
  algorithm = "RSA"
  rsa_bits = 4096
}

resource "aws_key_pair" "generated_key" {
  key_name = var.key_name
  public_key = tls_private_key.example.public_key_openssh
}

resource "aws_default_vpc" "default" {
  tags = {
    Name = "Default VPC"
  }
}

variable_secrets.tf

variable "aws-access-key" {
  type = string
  default = "aws-access-key"
}

variable "aws-secret-key" {
  type = string
  default = "aws-secret-key" 
}

variable "aws-region" {
  type = string
  default = "eu-central-1"
}

install.sh for EC2 setup

To do this, we created a ./docker/install.sh file with the following content.


#!/bin/bash

# Install wget to update IP at all-inkl.com
echo "Setup all-inkl.com"
sudo apt-get install wget

# Save public IP to variable
ip="$(dig +short myip.opendns.com @resolver1.opendns.com)"

# Add all-inkl.com variables
kas_login="username"
kas_auth_data="pw"
kas_action="update_dns_settings"
sub_domain="sub"
record_id="id"

sudo sleep 10s

# Update all-inkl.com dns-settings with current IP and account data
sudo wget --no-check-certificate --quiet \
  --method POST \
  --timeout=0 \
  --header '' \
    'https://kasapi.kasserver.com/dokumentation/formular.php?kas_login='"${kas_login}"'&kas_auth_type=plain&kas_auth_data='"${kas_auth_data}"'&kas_action='"${kas_action}"'&var1=record_name&wert1='"${sub_domain}"'&var2=record_type&wert2=A&var3=record_data&wert3='"${ip}"'&var4=record_id&wert4='"${record_id}"'&anz_var=4'


echo "Installing Docker"
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install -y docker-ce

echo "Installing Docker-Compose"
sudo curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# Follow guide to create personal access token https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token
sudo git clone https://username:token@github.com/ratzel921/cloud-webshop.git
sudo docker login -u username -p token
sudo docker-compose -f ./cloud-webshop/docker-compose-cert.yml up --build -d
sudo docker-compose -f ./cloud-webshop/docker-compose.yml pull
sudo docker-compose -f ./cloud-webshop/docker-compose.yml up

Next, run the following commands. This will automatically create an EC2 instance (runs the application), a Security_Group (for connections to the EC2 instance via HTTPS, HTTP, and SSH), an SSH_KEY (allows to access the EC2 instance via SSH). In the end, the IP address of the EC2 instance is displayed in the console. This will automatically be entered into all-inkl.com or manually add it.

# Get terraform provider with init and use apply to start the terraform script.
terraform init
terraform apply --auto-approve

# (Optional) Delete EC2 instances
terraform destroy --auto-approve

Testing

Creating a Testing Environment

Using Terraform and an EC2 instance, it is also possible to create a testing environment. We used the GitHub pipeline for this.

Backend/Dockerfile

# Build stage
FROM maven:3.6.3-jdk-8-slim AS build
COPY src /home/app/src
COPY pom.xml /home/app
RUN mvn -f /home/app/pom.xml clean test
RUN mvn -f /home/app/pom.xml clean package

# Package stage
FROM openjdk:8-jre-slim
COPY --from=build /home/app/target/*.jar /usr/local/backend.jar
COPY --from=build /home/app/target/lib/*.jar /usr/local/lib/
EXPOSE 8080
ENTRYPOINT ["java","-jar","/usr/local/backend.jar"]

frontend/nginx/nginx.conf

server {
  listen 80;
  server_name www.${VIRTUAL_HOST} ${VIRTUAL_HOST};

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
        proxy_cookie_path / "/; SameSite=lax; HTTPOnly; Secure";
    }

    location /api {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;

        proxy_pass_header Set-Cookie;

        proxy_cookie_domain www.${VIRTUAL_HOST} ${VIRTUAL_HOST};
        #rewrite ^/api/?(.*) /$1 break;
        proxy_pass http://${API_HOST}:${API_PORT};
        proxy_redirect off;
    }

   error_page   500 502 503 504  /50x.html;

   location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

frontend/Dockerfile

# Build stage
# Use node:alpine to build static files
FROM node:15.14-alpine as build-stage

# Create app directory
WORKDIR /usr/src/app

# Install other dependencies via apk
RUN apk update && apk add python g++ make && rm -rf /var/cache/apk/*

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm install

# Bundle app source
COPY . .

# Build static files
RUN npm run test
RUN npm run build


# Package stage
# Use nginx alpine for minimal image size
FROM nginx:stable-alpine as production-stage

# Copy static files from build-side to build-server
COPY --from=build-stage /usr/src/app/dist /usr/share/nginx/html

RUN rm /etc/nginx/conf.d/default.conf
COPY nginx/nginx.conf /etc/nginx/templates/

# EXPOSE 80
CMD ["/bin/sh" , "-c" , "envsubst '${API_HOST} ${API_PORT} ${VIRTUAL_HOST}' < /etc/nginx/templates/nginx.conf > /etc/nginx/conf.d/nginx.conf && exec nginx -g 'daemon off;'"]

Modifying the docker-compose.yml

To do this, we created a copy of docker-compose.yml (docker-compose-testStage.yml). We changed the images and the LETSENCRYPT_HOST & VIRTUAL_HOST for the “backend” and “frontend” service in this file.

Modifying the Terraform files

In the testStage.sh, we changed the record_id and “docker-compose -f ./cloud-webshop/docker-compose.yml pull & sudo docker-compose -f ./cloud-webshop/docker-compose.yml up -d” to “sudo docker-compose -f ./cloud-webshop/docker-compose-testStage.yml pull sudo docker-compose -f ./cloud-webshop/docker-compose-testStage.yml up -d
In the main.tf, “user_date = file(“docker/test_Stage.sh”)” is set.
After that, the EC2 instance, the security group, and SSH can be started as usual using Terraform.

Automated Selenium frontend testing with GitHub 

To do this, create the .github/workflows/selenium.yml file with the following content.
The script is executed on every push to the repository. It installs all necessary packages, creates a screenshot folder, and runs the pre-programmed Selenium tests located in the frontend folder.
After a push or manual execution, the test results with the artifacts (screenshots) are located on the Actions tab.

name: selenium tests
on: push
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Build the stack
        run: docker-compose up -d
      - name: npm install
        run: cd frontend && npm install
      - name: install jest
        run: cd frontend && npm install jest
      - name: install selenium-webdriver
        run: cd frontend && npm install selenium-webdriver
      - name: run tests
        run: mkdir -p /tmp/screenshots/ && cd frontend && npm test
      - name: Archive screenshots
        uses: actions/upload-artifact@v2
        with:
          name: selenium-screenshots
          path: /tmp/screenshots/
      - name: Shutdown
        run: docker-compose down

Note that Chromedriver must be run headless, as GitHub cannot run a browser on a screen.

var driver = await new Builder()
        .forBrowser('chrome')
        .setChromeOptions(new chrome.Options().headless())
        .build();

Infrastructure as a Code

Cloud computing is the on-demand provision of IT resources (e.g., servers, storage, databases) via the Internet. Cloud computing resources can be scaled up or down depending on business requirements. You only pay for the IT resources you use. 
On July 27, 2021, Gartner published the latest “Magic Quadrant” for Cloud Infrastructure and Platform Services. Like last year, Amazon Web Service is the top performer in the Magic Quadrant. Followed by Microsoft and Google. (
https://www.gartner.com/doc/reprints?id=1-271OE4VR&ct=210802&st=sb). Since we were interested in trying Docker Compose, we decided to use AWS for deployment.

Deployment on Amazon ECS with Docker Compose 

Since early 2020, AWS and Docker have started working on an open Docker Compose specification, which will make it possible to use the Docker Compose format to deploy containers on Amazon ECS and AWS Fargate. In July 2020, the first beta version for Docker Desktop was released; the first stable version has been available since September 15, 2020.

Customize docker-compose.yml

The AWS ECS CLI supports Compose versions 1, 2, and 3. By default, it looks for docker-compose.yml in the current directory. Optionally, you can specify a different filename or path to a Compose file with the –file option. The Amazon ECS CLI only supports a few parameters, so correcting the yml may be necessary (https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cmd-ecs-cli-compose-parameters.html).

# (Optional) Create a new Docker context to point the Docker CLI to the correct endpoint. For this step you need the AWS_ACCESS_KEY and AWS_SECRET_ACCESS_KEY.
docker context create ecs myecscontext

# (Optional) Use context
docker context use myecscontext

# Deploy application to AWS
docker compose up 

# Here you can see which containers were started as well as the URLs
docker compose ps

# (Optional) Shut down container. (Don't forget to change the context back to default).
docker compose down

# Convert Docker Compose file to CloudFormation to track which resources are created or updated
docker compose convert

BuildX

Building images for other processors

For example, if you have an M1 with an arm64 processor, a locally created image would not be accepted by AWS (error message “EssentialContainerExited: Essential container in task exited”). The reason is that ECS instances only support amd64 images.

Since Docker version >= 19.03, Docker offers buildX. The plugin is officially no longer considered experimental as of August 5, 2020. With the buildX functionality, it is relatively easy to create Docker images that work on multiple CPU architectures.

# (optional) Create a new Builder instance
docker buildx create --name mybuilder

# (optional) Use created builder
docker buildx use mybuilder    

# Show all available builder instances (here you can also see which CPU architectures are supported by the builder)
docker buildx ls

# Build and push image for example for amd64, arm64 and arm/v7
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 --tag username/repository_name:tag_name --push .

# Delete images
docker buildx prune --all

Why It’s So Easy to Hack Your Smart Home

Every day, new smart home accessories go online for the first time to join the Internet of Things (IoT). Many of them enjoy the unwarranted trust of their owners. This blog post is a case study of the haunted smart home.

Earlier this year, I visited my family for a few days. After sitting and talking at the kitchen table for a bit, they told me about their new smart wall plugs that integrate into their Apple Home ecosystem. Using the plugs, they can turn on their kitchen lights from their phones — or automatically at sunset. Pretty cool. After I had a closer look at one of the plugs, I searched for the brand on the Internet, because I had never heard of it. Turns out, these “Meross Smart Plugs” are the first item that pops up on Amazon when you search for a HomeKit-compatible socket outlet that can switch “dumb” devices like lamps, coffee makers or hi-fi equipment on and off. At the time of writing, they cost about 17 € apiece.

As I had never heard of the brand and I would consider myself somewhat of a curious person, I thought it’d be a good idea to see if it was possible to control these plugs without being a part of the smart home environment. So I continued chatting with my family while investigating the local network.

Continue reading

HAFNIUM EXCHANGE SERVER ATTACKS – What happened and how to protect yourself

an article by Carina Szkudlarek, Niklas Schildhauer and Jannik Smidt

This post is going to review the zero day exploit of the Microsoft Exchange Servers starting in January 2021.
It will look into the methods of SSRF and the exploitation of mistakes in the deserialization of input values to procure privileged code execution.

INTRODUCTION

In early 2021, several vulnerabilities were discovered in the Microsoft Exchange server software of the 2010, 2013, 2016 and 2019 releases that could be used by attackers to gain access to such an Exchange server.

With Exchange Server, Microsoft offers a service with which e-mail communication can be controlled in networks, but electronic communication can also be checked for harmful files such as viruses. All incoming and outgoing e-mails end up on the corresponding Exchange server. From there they are distributed to the recipients. Although there are alternatives, numerous state and private-sector institutions around the world rely on Microsoft Exchange servers.

On January 6, 2021 the security company Volexity observed several attacks via a previously unpublished Exchange vulnerability. In the course of the following weeks there were additional individual attacks on selected Exchange servers.

Microsoft instantly planned to release a security patch. However, the responsible attacker group Hafnium had already started a large amount of mass scans starting several months prior to january 6th when the attack was first exploited (see R[17]) . Exchange servers that were vulnerable were automatically infected with a webshell. Less than a week later, Microsoft published several security updates. However only a few hours after the publication of these unscheduled updates for the known vulnerabilities, the unprecedented infection of all unpatched Exchange servers accessible via the Internet began. As a result, administrators had little time and opportunity to react.

Generally, the exploit of overall four known vulnerabilities can be used as a gateway to penetrate deeper into the corporate network, as the Exchange servers are often publicly accessible. Yet it only affects on-premise Microsoft Exchange Server and not Exchange Online or Microsoft 365.

According to estimates, generally around 250,000 Exchange servers worldwide are open like a barn door to cyberattacks. 30,000 US customers have already been hacked, according to Heise [R1] tens of thousands of Exchange servers are affected in Germany alone, some of them in German federal authorities, according to the BSI [see: R2]

Continue reading

Die elektronische Patientenakte – Wie sicher ist die zentrale Digitalisierung im Gesundheitswesen?

Oftmals ist es für Ärzte schwer Behandlungen optimal durchzuführen, weil Befunde fehlen oder der Arzt keine Informationen darüber hat wie frühere Behandlungen abgelaufen sind. Um dies in Zukunft vermeiden zu können, wurde am 01. Januar 2021 die elektronische Patientenakte (kurz: ePA) in einem 3 Phasen Modell eingeführt. In der ersten Phase konnten alle gesetzlich Versicherten eine ePA bei ihrer Krankenkasse beantragen. Im zweiten Quartal startete die Rollout-Phase um testweise Arztpraxen anzubinden. Seit dem 01. Juli 2021 sind alle Ärzte gesetzlich verpflichtet die ePA anzubinden. [11]

Dieser Blogbeitrag beschäftigt sich damit was die ePA eigentlich ist, wie die darunterliegende Technik funktioniert und welche Rolle der Datenschutz und die Informationssicherheit dabei spielt.

Continue reading

Digital Ghostbusters – Der Malware auf der Spur

Mit dem Beginn des digitalen Zeitalters haben unzählige Unternehmen vermehrt einen Fuß in die Online-Welt gesetzt, um dort möglichst profitabel zu agieren. Innerhalb des letzten Jahrzehnts haben wir große Schritte in Richtung der vollständigen Digitalisierung gemacht und mit der Einführung von digitalen Währungen auch den Umgang mit Geld deutlich verändert. Mittlerweile benötigen wir keine riesigen Geldspeicher gefüllt mit millionen goldener Taler a lá Dagobert Duck, sondern können ein milliardenschweres Vermögen auf mikroelektronischen Speicherstrukturen mit binären Schaltzuständen speichern und verwalten. Seit jeher liegt es in unserer Natur, wertvolle Dinge und Vermögen so gut wie möglich vor Angreifern zu schützen und so nehmen unzählige IT-Security-Firmen den Kampf gegen das Böse der Neuzeit auf. Denn eines ist sicher: Wo viel Geld im Umlauf ist, ist die Kriminalität nicht weit entfernt.

Nun könnte man davon ausgehen, dass Personen und Unternehmen ohne großes Vermögen auch kein Angriffsziel für Cyberkriminelle darstellen, denn dort gibt es ja theoretisch auch nichts zu holen, oder nicht? Diesen Gedankengang haben leider viel zu viele und gehen daher oft leichtsinnig mit der Sicherheit ihrer digitalen Systeme um. So ist es für potentielle Angreifer ein Leichtes, das sogenannte “digitale Vermögen” zu ergattern. Doch zu digitalem Vermögen gehört nicht nur der Zugang zu privaten E-Wallets mit einem Wert in Millionenhöhe. Nicht umsonst gibt es seit einiger Zeit das Sprichwort: “Data is the new Oil”.

Zu diesen Daten gehören auch Informationen über Personen, neue Innovationen, die finanzielle Situation von Unternehmen oder Systemstrukturen von im Unternehmen eingesetzten IT-Systemen. Sehr oft sind solche Informationen für Cyberkriminelle wertvoller als der direkte Zugang zu einem E-Wallet. Der Grund liegt hierbei auf der Hand: In einem E-Wallet befindet sich, genau wie auf einem Bankkonto, lediglich eine begrenzte Menge an Vermögen. Ist dieses einmal aufgebraucht, hat der Angreifer keinen Nutzen mehr von dem Zugang. Wie in Filmen oft dargestellt wird, arbeiten Kriminelle daher mit Methoden wie Kidnapping und anschließender Erpressung, um so mehr Profit aus ihrem Verbrechen zu schlagen.

Wie funktioniert digitales Kidnapping, was sind die primären Hintergründe und wie kann man sich dagegen schützen?

Continue reading

Der Staat und die IT-Sicherheit: Was Staatstrojaner, Luca und die CDU-Wahlkampf-App verbindet

In der IT-Sicherheit war viel los in letzter Zeit. Das haben wir auch in der Vorlesung „Sichere Systeme“ bei Herrn Kriha gemerkt, in der wir jede Woche aktuelle IT-Sicherheits-News gesammelt haben – im Laufe des Semesters kamen wir auf über 20 Seiten mit Links zu Heise, Golem und Co.

Im Rahmen dieser Lehrveranstaltung schreibe ich diesen Blogartikel und möchte mich hierbei einem Thema widmen abseits von einzelnen Angriffen auf IT-Systeme, von bösen Hackern, von spezifischen Sicherheitslücken oder Tipps, wie man seine privaten Accounts besser schützt. Es ist die Frage, welchen Einfluss der Staat auf die IT-Sicherheit hat. Dafür möchte ich ein paar aktuelle netzpolitische Themen aufgreifen, die in den letzten Monaten stark diskutiert wurden und die zeigen, wie unser Staat Einfluss auf die IT-Sicherheit in Deutschland (und darüber hinaus) nehmen kann.

Continue reading

Mechanismen bei System-Programmiersprachen zum Erreichen von Memory-, Thread- und Type-Safety

Motivation

Ende letzten Monats (Juli, 2021) hat die CWE (Common Weakness Enumeration) einen Bericht veröffentlicht, welcher die Top 25 der Software-Schwachstellen aufzeigt. Es handelt sich dabei um eine Auswertung von gefundenen Schwachstellen der letzten zwei Jahre in verschiedenen Software-Systemen. Der Bericht umfasst eine Liste der 40 schwerwiegensten Schwachstellen. Dabei handelt es sich um Schwachstellen, welche einfach zu finden oder auszunutzen sind, häufig vorkommen und äußerst wirkungsvoll und dementsprechend gefährlich sind. [1]

Platz 1 der Liste wird von einer Speicher-Schwachstelle belegt, dem Out-Of-Bounds-Write dicht gefolgt vom Out-Of-Bounds-Read auf Platz 3. Insgesamt sind 7 der 40 vorgestellten Schwachstellen solche, welche aufgrund mangelnder Speicher-Sicherheit entstehen können. Andere gefährliche Schwachstellen entstehen aus Fehlern in der parallelen Programmierung sowie durch zu schwache Typ-Systeme in der verwendeten Programmier-Sprache. [1]

Speicher-spezifische Software-Schwachstellen sind die mit am häufigsten vorkommenden Schwachstellen. Circa 70% der Schwachstellen in Systemen von Microsoft sind auf Speicher-Fehler zurück zu führen. [11]

Andere Beispiele für die Häufigkeit von Speicher-Fehlern sind der Exim-Mail-Server vergangenen Mai, bei dem 12 der 21 gefundenen Schwachstellen Speicher-spezifische Fehler waren. [12] Aber auch zwei schwerwiegende Sicherheits-Lücken beim Samba-LDAP-Server vom März diesen Jahres sind auf Speicher-Fehler in der Software zurück zu führen. [13] In der Webkit-Komponente von Apple’s MacOS wurde ebenfalls ein Speicher-Fehler in Form eines Puffer-Überlaufs entdeckt. [14]

Unsafe Languages, Inadequate Defense Mechanisms and Our Dangerous Addiction to Legacy Code

bugs, bugs everywhere

A recent study found that 60-70% of vulnerabilities in iOS and macOS are caused by memory unsafety. Microsoft estimates that 70% of all vulnerabilities in their products over the last decade have been caused by memory unsafety. Google estimated that 90% of Android vulnerabilities are memory unsafety. An analysis of 0-days that were discovered being exploited in the wild found that more than 80% of the exploited vulnerabilities were due to memory unsafety.

(Gaynor, 2019)

Over the last 20 years, developing secure software has become increasingly important. To this day, we write a significant amount of code in languages with manual memory management. However, the Peter Parker principle states that “great power comes with great responsibility”. Many scoring systems classify, enumerate and rank prevalence of known vulnerabilities. In theory, developers should be aware of common programming mistakes leading to these bugs. Yet, the last 20 years are living proof that manual memory management is highly error-prone. Because most systems share memory between data and instructions, controlling small portions of memory can be enough to take over entire systems (Szekeres et al., 2013). The fight over attacking and defending the security measures on top of unsafe systems is often called the eternal war in memory.

In this blog post, I want to examine what properties make programming languages like C/C++ fundamentally unsafe to use. After that, I briefly discuss the inadequacies of our defense mechanisms. Last of all, I reflect on the sociopolitical implications arising from the continued use of unsafe languages.

Continue reading

Supply Chain Attacks – Die Lieferkette schlägt zurück

ein Artikel von Verena Eichinger, Amelie Kassner und Elisa Zeller

Nach SolarWinds schafft es eine neue Schlagzeile aus der IT-Welt in den Massenmedien ihre Kreise zu ziehen. Über 500 Supermärkte in Schweden mussten wegen eines Cyberangriffs schließen. Wie bereits bei SolarWinds handelt es sich auch hier um eine Supply Chain Attack (SCA). Mittlerweile fällt dieser Begriff immer häufiger und er schafft es nicht nur allgemein für Aufmerksamkeit zu sorgen, sondern führt auch zu großer Besorgnis in IT-Kreisen. [12]

Wir alle, die wir diesen Artikel lesen, sitzen gerade vor einem technischen Gerät, das ein komplexes Zusammenspiel aus Hardware und Software darstellt. Diese Komplexität können wir in der heutigen Zeit nicht mehr vollständig durchdringen, oder wissen Sie, woher die einzelnen Komponenten stammen und wer zu diesen Zugang hatte? Ist jegliche Software auf dem neuesten Stand und sind genutzte Bibliotheken auch wirklich vertrauenswürdig? Kann man sich sicher sein, dass in das letzte Softwareupdate keine Malware eingeschleust wurde? Das alles sind Fragen, die sich stellen, wenn man sich mit SCAs befasst und beginnt, die Tiefe der dahinterstehenden Problematik zu begreifen. Zwar waren bisher stets Firmen das Ziel der Angriffe, doch wie es der kürzliche Vorfall bei der Supermarktkette Coop in Schweden zeigt, sind deren Auswirkungen auch beim Endnutzer angekommen. An dieser Stelle lohnt es sich für jedermann, die Thematik genauer zu betrachten. Dazu wird im ersten Abschnitt dieses Artikels das zugrundeliegende Prinzip der SCAs erläutert und geklärt, womit wir es genau zu tun haben. Anschließend werden die genannten Beispiele SolarWinds und der Angriff auf Kaseya, zu dessen Opfern auch die Supermarktkette Coop gehört, betrachtet. Diese beiden Angriffe sind Musterbeispiele für die Gefahr und den Wirkungsgrad der SCAs. Zuletzt soll es darum gehen, was gegen die Bedrohung durch SCAs unternommen werden kann.

Continue reading