Andreas Bruns

Softwareentwicklung für Oldenburg und Bremen

Schwachstellen finden dank Dependency-Check der OWASP

Diese Woche veröffentlichte die Non-Profit-Organisation OWASP (Open Web Application Security Project) nach vier Jahren Ihre neueste Version der OWASP Top Ten. Die OWASP widmet sich der Sicherheit von Web-Anwendungen und weist mit ihren Top Ten auf die gravierendsten Sicherheitsschwachstellen in Web-Anwendungen hin. Damit stärkt sie das Sicherheitsbewusstsein von Unternehmen und Entwicklern und gibt Hilfestellung bei der Entwicklung von sicheren Web-Anwendungen.

Neben der Erstellung von Security-Dokumenten und Security-Empfehlungen entwickelt OWASP auch freie Security-Werkzeuge. Mit ihrem Flagship-Projekt OWASP Dependency Check gehen sie die Nummer Neun der Top Ten an: Nutzung von Komponenten mit bekannten Schwachstellen (Using Components with Known Vulnerabilities). Eingesetzte Bibliotheken können mit dem Werkzeug auf Sicherheitsschwachstellen geprüft werden, die bei der National Vulnerability Database (NVD) dokumentiert sind.

Die OWASP Dependency Check – Dokumenation zeigt, dass neben der Analyse von Java-Bibliotheken (Jar-Archive) auch zahlreiche andere Programmiersprachen unterstützt werden. Die Nutzung kann auf verschiedene Arten erfolgen (z.B. Kommandozeile, Ant, Maven, Gradle, Jenkins). Für meine Java-Projekte setze ich oft Gradle und Spring-Boot ein, sodass ich das folgende Spring-Boot-Beispiel mit der Gradle-Erweiterung des Dependency-Checks auf Sicherheitsschwachstellen analysiere.

Minimale Web-Anwendung mit Spring-Boot

Eine minimale Web-Anwendung, die auf Spring-Boot basiert und mit Gradle gebaut wird, benötigt nur zwei Dateien: die build.gradle und eine Java-Klasse mit einem Spring-Controller:

example-dependency-check git:(master) ✗ tree       
.
├── build.gradle
└── src
    └── main
        └── java
            └── dependencycheck
                └── HomeController.java
4 directories, 2 files

Die build.gradle zum Bauen des Projekts:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.9.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:1.5.9.RELEASE")
}

Java-Klasse mit dem Spring-Controller:

package dependencycheck;

import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;

@Controller
@EnableAutoConfiguration
public class HomeController {

    @RequestMapping("/")
    @ResponseBody
    String home() {
        return "OWASP Dependency Check - Hello World!";
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(HomeController.class, args);
    }
}

Die Applikation kann dann mit „gradle clean build bootrun“ gebaut und gestartet werden. Im Browser wird das Ergebnis unter der Adresse http://localhost:8080 angezeigt.

Dependency-Check Browser

Dependency-Check Browser

Dependency-Check der Web-Anwendung

Jetzt binden wir in der build.gradle den Dependency-Check für Gradle ein. Außerdem können wir dort konfigurieren, wie der Dependency-Check gefundene Schwachstellen bewerten soll. Beispielsweise können wir den Build fehlschlagen lassen, wenn die Bewertung der Schwachstellen einen bestimmten Wert überschreitet:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.9.RELEASE")
        classpath("org.owasp:dependency-check-gradle:3.0.2")
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'org.owasp.dependencycheck'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencyCheck {
    failBuildOnCVSS=1
    skipTestGroups=true
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:1.5.9.RELEASE")
}

Mit dem Befehl „gradle dependencyCheckAnalyze“ führen wir die Analyse aus und erhalten unter „build/reports/dependency-check-report.html“ den erstellten Report.

Dependency-Check Report

Dependency-Check Report

Report des Dependency-Checks auswerten

Der Beispiel-Report zeigt drei Schwachstellen in der verwendeten Bibliothek org.apache.tomcat:tomcat-annotations-api:8.5.23: CVE-2016-5425, CVE-2016-6325, CVE-2017-6056. Nachdem wir uns einen Überblick mit „gradle dependencies“ zu den von Spring-Boot eingesetzten Bibliotheken verschafft haben, können wir überlegen, wie wir mit der Bibliothek des eingebetteten Tomcat-Servers umgehen.

➜  example-dependency-check git:(master) ✗ gradle dependencies

runtime - Runtime dependencies for source set 'main'.
\--- org.springframework.boot:spring-boot-starter-web:1.5.9.RELEASE
     +--- org.springframework.boot:spring-boot-starter:1.5.9.RELEASE
     |    +--- org.springframework.boot:spring-boot:1.5.9.RELEASE
     |    |    +--- org.springframework:spring-core:4.3.13.RELEASE
     |    |    \--- org.springframework:spring-context:4.3.13.RELEASE
     |    |         +--- org.springframework:spring-aop:4.3.13.RELEASE
     |    |         |    +--- org.springframework:spring-beans:4.3.13.RELEASE
     |    |         |    |    \--- org.springframework:spring-core:4.3.13.RELEASE
     |    |         |    \--- org.springframework:spring-core:4.3.13.RELEASE
     |    |         +--- org.springframework:spring-beans:4.3.13.RELEASE (*)
     |    |         +--- org.springframework:spring-core:4.3.13.RELEASE
     |    |         \--- org.springframework:spring-expression:4.3.13.RELEASE
     |    |              \--- org.springframework:spring-core:4.3.13.RELEASE
     |    +--- org.springframework.boot:spring-boot-autoconfigure:1.5.9.RELEASE
     |    |    \--- org.springframework.boot:spring-boot:1.5.9.RELEASE (*)
     |    +--- org.springframework.boot:spring-boot-starter-logging:1.5.9.RELEASE
     |    |    +--- ch.qos.logback:logback-classic:1.1.11
     |    |    |    +--- ch.qos.logback:logback-core:1.1.11
     |    |    |    \--- org.slf4j:slf4j-api:1.7.22 -> 1.7.25
     |    |    +--- org.slf4j:jcl-over-slf4j:1.7.25
     |    |    |    \--- org.slf4j:slf4j-api:1.7.25
     |    |    +--- org.slf4j:jul-to-slf4j:1.7.25
     |    |    |    \--- org.slf4j:slf4j-api:1.7.25
     |    |    \--- org.slf4j:log4j-over-slf4j:1.7.25
     |    |         \--- org.slf4j:slf4j-api:1.7.25
     |    +--- org.springframework:spring-core:4.3.13.RELEASE
     |    \--- org.yaml:snakeyaml:1.17
     +--- org.springframework.boot:spring-boot-starter-tomcat:1.5.9.RELEASE
     |    +--- org.apache.tomcat.embed:tomcat-embed-core:8.5.23
     |    |    \--- org.apache.tomcat:tomcat-annotations-api:8.5.23
     |    +--- org.apache.tomcat.embed:tomcat-embed-el:8.5.23
     |    \--- org.apache.tomcat.embed:tomcat-embed-websocket:8.5.23
     |         \--- org.apache.tomcat.embed:tomcat-embed-core:8.5.23 (*)
     +--- org.hibernate:hibernate-validator:5.3.6.Final
     |    +--- javax.validation:validation-api:1.1.0.Final
     |    +--- org.jboss.logging:jboss-logging:3.3.0.Final -> 3.3.1.Final
     |    \--- com.fasterxml:classmate:1.3.1 -> 1.3.4
     +--- com.fasterxml.jackson.core:jackson-databind:2.8.10
     |    +--- com.fasterxml.jackson.core:jackson-annotations:2.8.0
     |    \--- com.fasterxml.jackson.core:jackson-core:2.8.10
     +--- org.springframework:spring-web:4.3.13.RELEASE
     |    +--- org.springframework:spring-aop:4.3.13.RELEASE (*)
     |    +--- org.springframework:spring-beans:4.3.13.RELEASE (*)
     |    +--- org.springframework:spring-context:4.3.13.RELEASE (*)
     |    \--- org.springframework:spring-core:4.3.13.RELEASE
     \--- org.springframework:spring-webmvc:4.3.13.RELEASE
          +--- org.springframework:spring-aop:4.3.13.RELEASE (*)
          +--- org.springframework:spring-beans:4.3.13.RELEASE (*)
          +--- org.springframework:spring-context:4.3.13.RELEASE (*)
          +--- org.springframework:spring-core:4.3.13.RELEASE
          +--- org.springframework:spring-expression:4.3.13.RELEASE (*)
          \--- org.springframework:spring-web:4.3.13.RELEASE (*)

Folgende Möglichkeiten haben wir:

  • wir behandeln die Schwachstelle nicht (da in unserem Einsatzkontext nicht relevant) und markieren sie als „False Positive“ in einer SuppressionFile-Datei
  • wir binden eine aktuellere Bibliothek ein, die keine Schwachstellen aufweist
    dependencies {
        compile("org.springframework.boot:spring-boot-starter-web:1.5.9.RELEASE")
        compile("org.apache.tomcat:tomcat-annotations-api:8.5.24")
    }
    
  • wir nehmen die Bibliothek heraus, falls sie nicht benötigt wird
    dependencies {
        compile("org.springframework.boot:spring-boot-starter-web:1.5.9.RELEASE") {
            exclude group: 'org.apache.tomcat', module: 'tomcat-annotations-api'
        }
    }
    
  • wir ersetzen die gesamte Tomcat-Komponente durch einen eingebetteten Jetty-Server
    dependencies {
        compile("org.springframework.boot:spring-boot-starter-web:1.5.9.RELEASE") {
            exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
        }
        compile("org.springframework.boot:spring-boot-starter-jetty")
    }
    

Fazit

In einem umfangreichen Projekt kann das Bewerten der Schwachstellen sehr aufwändig werden. Die einfachste Lösung für die Behandlung der Schwachstelle ist es, die entsprechende Bibliothek herauszunehmen, falls das möglich ist. Leider ist es mit einer einzelnen Prüfung von Schwachstellen nicht getan, da viele Schwachstellen natürlich erst im Laufe der Zeit in Bibliotheken gefunden werden. Daher empfiehlt sich die Integration des Dependency-Checks in eine Continuous-Integration-Pipeline.

Kommentare sind geschlossen.