Write-up zu Firejail

Write-up zu Firejail #

Einführung #

Nach den Entwicklern ist Firejail ist eine SUID-Sicherheitssandbox, die auf Linux-Namespaces und seccomp-bpf basiert Es ist nichts einzigartiges an Firejail, da es im Wesentlichen einige Kernel-Sicherheitstechnologien verwendet, die übereinander geschachtelt sind. Der Vorteil ist damit, dass Komplexität für den Benutzer reduziert wird. Ausserdem bieten sie vorkonfigurierte Sicherheitsprofile für viele Programme an.

Kerneltechnologien #

Die Kerneltechnologien sind in 3 Gruppen gegliedert.

Front-end sandboxing Technologien:

  • Mount namespace
  • PID namespace
  • Network namespace
  • Optional: chroot, overlayfs, netfilter

Back-end sandboxing Technologien

  • seccomp-bpf
  • Linux capabilities
  • Optional: noroot user namespace, AppArmor

Kernel config Technologien:

  • SUID

Die Back-end Technologien nähmen eine Support Rolle ein und verhindern, dass der Angreifer root werden kann.

SUID sollte normalerweise nicht gesetzt werden, da dann das Programm mit den Rechten des Dateibesitzers und nicht mit den Rechten des Benutzer ausgeführt wird. In diesem Fall muss jedoch der Kernel konfiguriert werden und erst im Anschluss dropt das Programm dann die Root Rechte. Das SUID Risiko kann weiter minimiert werden, wenn das binary einer bestimmten Gruppe zugewiesen ist und nur wenige Nutzer Zugriff darauf erhalten.

Firejail ist für Einbenutzersysteme konzipiert also beispielsweise nicht für Server, die von mehreren Usern via SSH verwendet werden.

Verwendung #

Start #

Grundsätzlich muss immer zuerst firejail dem Befehl vorangestellt werden und das funktioniert ohne Probleme für gängige Programme, da die Profile schon vorhanden sind. Ansonsten wird ein Default Profil verwendet.

firejail firefox

Konfiguration #

Sollen alle Programme automatisch in einer firejail laufen, hilft der Befehl aus:

sudo firecfg

Dieser liest die /usr/share/application/*.desktop und kopiert sie angepasst nach $HOME/.local/share/ applications/*.desktop, falls die Files absolute Pfade zum Binary beinhalten (z.B. bei Chromium). Anschliessend macht er noch ein symbolischen link von /usr/local/bin/firefox nach /usr/bin/firejail, damit Konsolenaufrufe auch über firejail laufen.

Monitoring #

Mit firejail --list und firejail --top sind die laufenden firejail Programme ersichtlich. Mitfirejail --tree können die Prozesse in jeder Sandbox angezeigt werden.

Security Profile #

Die Security Profile können selber angepasst werden, um z.B. Ordner freizugeben.

Die mitgelieferten Profile sind unter /etc/firejail und Anpassungen sollen unter ~/.config/firejail gespeichert werden. Es kann dann ein Include auf die ursprüngliche Datei mit include /etc/firejail/[...] gesetzt werden, wenn nicht alles neu gemacht werden soll.

Die Anpassung der Profile erfordert etwas Übung und ist an einigen Stellen wie in Creating overrides, Building Custom Profiles und Creating Profiles dokumentiert.

Es gibt blacklisting und whitelisting. Zu beachten ist, dass bei Whitelisting ein temporäres Filesystem bind-mounted wird, und so die Änderungen discarded werden, wenn die Sandbox beendet wird, ausser der Ordner existierte bereits.

Die Regel ist so:

  • blacklist: alles erlaubt ausser explizit verboten
  • noblacklist: Ignore alle folgenden blacklists, die gleichen Pfad wirken.
  • whitelist: verbiete alles, ausser Pfad
  • nowhitelist: Ignoriere alle folgenden whitelists, die auf den gleichen Pfad wirken

Für neue Programmen können auch halb-automatisch Profile erzeugt werden. Das funktioniert aber beispielsweise für Chromium nicht, da dieser die Userberechtigungen erhöht und so strace nicht funktionieren würde.

firejail --build profile-file myprogram

Beispiele #

Bei einem Whitlisting wird oft auch ein noblacklist hinzugefügt, um es beständiger zu machen.

noblacklist ~/MyPictures
whitelist ~/MyPictures

Gleiches bei einem Blacklisting.

nowhitelist ~/MyPictures
blacklist ~/MyPictures

Es gibt viele weitere Einstellungen, die nützlich sind.

ignore nou2f ## dadurch können U2F devices verwendet werden (z.B. im Browser)
ignore net ## aktiviert den Internet Zugriff, wenn er verboten war

Oft gemachte Fehler #

  • blacklist PATH
    PATH sieht man noch ist aber nicht zugänglich. Mit Whitelist existieren sie nicht.

  • noblacklist ~/Documents/presentations blacklist ~/Documents
    funktioniert nicht, weil noblacklist es verhindert.

  • whitelisting in Profilen für Texteditoren.
    Funktioniert nicht, weil diese dann discarded werden nach dem Beenden (Tmpfs über dem originalen Filesystem)

Testing von firejail Profilen #

cd ~
touch test

firejail --whitelist=~/test bash
## oder
firejail --profile=~/mySecurityProfile bash

echo "asdf" > test

Firejail audit #

Firejail liefert auch eine Auditmöglichkeit mit. Diese kann mit einem eigenem Audit Programm oder per default mit faudit ausgeführt werden.

firejail --audit chromium

Firejail - Eigener IP Stack #

firejail --net=eth0 firefox

Das führt dazu, dass ein neues Interface erstellt wird und die Jail nun über dieses kommuniziert (eigener Network Namespace). Dieses Interface hat auch eine eigene MAC Adresse und könnte eine eigene Firewall haben.

DNS Rebinding und CNAME Cloaking #

Nach Cisco 91% der Malware verwendet DNS für ihre Attacken. Es ist also naheliegend, diese zu beobachten und zu schützen.

Analog der Anleitung von Firejail soll ein DNS Rebinding und CNAME Cloaking Schutz implementiert werden.

FDNS Setup #

sudo fdns --daemonize 
fdns --monitor 
firejail --dns=127.1.1.1 firefox &

FDNS Testing #

Die Domain local.learningplatform.ch zeigt auf localhost und kann verwendet werden. Ausserdem können ein paar Werbelastige Websites angesurft werden und es sollte so etwas wie 1x tracker xxx, dropped stehen.

CNAME Cloaking #

Ein CNAME-Eintrag (Canonical Name) im Domain Name System (DNS) ordnet einen Domainnamen einem anderen zu. Mit diesem Ansatz können mehrere Dienste wie ein FTP-Server und ein Webserver, die jeweils auf unterschiedlichen Ports laufen, von einer einzigen IP-Adresse aus betrieben werden.

Ad-Firmen bitten ihre Kunden, eine Subdomain für die Datenerfassung und -verfolgung zu verwenden und diese mit einem externen Server über den CNAME-DNS-Eintrag zu verknüpfen.

Ein DNS Server kann CNAME Cloaking erkennen, indem er den CNAME auflöst, dann zu einem weiteren DNS Eintrag kommt, der dann zu einer IP Adresse zeigt. Firefox enthält einen Stub-DNS Server, den Adblocker ansteuern können, was Chrome nicht hat.

DNS Rebinding #

Die Idee dahinter ist, dass ein Angreifer einen DNS Eintrag mit sehr kurzer TTL besitzt. Dieser kann dann dazu verwendet werden, auf das lokale Netzwerk des Opfers oder auf andere Inhalte zu zeigen. Auch wäre es durch geschicktes timing möglich, mehrere DNS Anfragen auf die gleiche Domain, mit unterschiedlichen IPs zu beantworten. Mit der gleichen Domain greift die SOP nicht.

Der DNS Server fdns verhindert DNS Einträge, die auf lokale IPs zeigen. Timing Attacken sind schwierig zu verhindern, da eine minimum TTL oder IP pinning nicht immer funktioniert.

Weitergedacht #

Wie kann mit fdns ein IPv4 over DNS Kommunikation erschwert werden? Das Tool iodine kann für Tests verwendet werden.

Übung - Hacking the developers #

Der Browser lädt in der Regel ein HTML Datei herunter, die viele weitere Quellen referenziert, um beispielsweise Library-Code herunterzuladen. Was würde passieren, wenn dieses HTML einen Request gegen localhost absetzt? Darum geht es im Artikel von Bouke. E-Bay hatte aus Sicherheitsgründen, den Computer des Benutzers gescannt. Die Details sind auf der Website von Nullsweep nachzulesen.

Die SOP verhindert das Lesen von Informationen einer Origin “Gut” auf der Origin “Böse”. Deshalb kann der Angreifer leider nichts lesen. Senden geht jedoch.

Wenn der firejail-Benutzer eine Website öffnen, die keine strenge CSP implementiert (z.B. example.com), kann er dort diesen JS Code einfügen und testen, ob der Request an den lokalen Webserver gesendet wird, der im nächsten Schritt gestartet werden soll. Alternativ kann der Test auch mit curl durchgeführt werden.

fetch('http://localhost/movies.json')
  .then(response => response.json())
  .then(data => console.log(data));
async function postData(url = '', data = {}) {
  const response = await fetch(url, {
    method: 'POST', 
    headers: {
      'Content-Type': 'text/plain'
    },
    body: data
  });
  return response;
}

postData('http://localhost:8080', "42")
  .then(data => {
    console.log(data);
  });

Der One-Liner python3 -m http.server supported leider keine post request.

Deshalb ein anderer kleiner Server von Miel Donkers:

##!/usr/bin/env python3
"""
Very simple HTTP server in python for logging requests
Usage::
    ./server.py [<port>]
"""
from http.server import BaseHTTPRequestHandler, HTTPServer
import logging

class S(BaseHTTPRequestHandler):
    def _set_response(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()

    def do_GET(self):
        logging.info("GET request,\nPath: %s\nHeaders:\n%s\n", str(self.path), 
                     str(self.headers))
        self._set_response()
        self.wfile.write("GET request for {}".format(self.path).encode('utf-8'))

    def do_POST(self):
        content_length = int(self.headers['Content-Length']) ## <--- Gets the size of data
        post_data = self.rfile.read(content_length) ## <--- Gets the data itself
        logging.info("POST request,\nPath: %s\nHeaders:\n%s\n\nBody:\n%s\n",
                str(self.path), str(self.headers), post_data.decode('utf-8'))

        self._set_response()
        self.wfile.write("POST request for {}".format(self.path).encode('utf-8'))

def run(server_class=HTTPServer, handler_class=S, port=8080):
    logging.basicConfig(level=logging.INFO)
    server_address = ('', port)
    httpd = server_class(server_address, handler_class)
    logging.info('Starting httpd...\n')
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        pass
    httpd.server_close()
    logging.info('Stopping httpd...\n')

if __name__ == '__main__':
    from sys import argv

    if len(argv) == 2:
        run(port=int(argv[1]))
    else:
        run()

Wenn der Code in der Datei server.py gespeichert ist, kann der Server mit python server.py 8080 gestartet werden.

Konfiguration testen #

curl http://localhost:8080/ ## funktioniert und wird geloggt
firejail --net=wlp2s0 curl https://www.google.ch/ ## funktioniert und gibt Ergebnis
firejail --net=wlp2s0 curl http://localhost:8080/ ## connection refused
firejail --net=wlp2s0 firefox ## und localhost ansurfen -> connection refused

Weitergedacht #

Sind andere Browsertechnologien auch der SOP unterstellt? Wenn nein, wäre dann eine Exfiltration von Dateien (z.B. ssh keys, api secrets) des Entwicklers möglich? Wenn der Browser keine Bugs hat nein, denn der File access kontrolliert der User über ein Browser Popup. Erst nach Bestätigung ist der Zugriff via JavaScript möglich. Im 2015 gemäss Aussage von Mozilla war es jedoch möglich, Dateien zu lesen.

Ist es möglich andere Technologien einzusetzen? Vermutlich, denn Postgresql kann beispielsweise auch auf das Filesystem mit dem Befehl select pg_ls_dir('/root') zugreifen.

Übung - Firejail and a vulnerable program #

Es gab im Firefox einen PDF.js Exploit, der dazu verwendet werden konnte, Dateien auszulesen. Der Exploit ist in Metasploit verfügbar.

Zuerst soll der firefox heruntergeladen und entpackt werden. Dann im Anschluss kann der Browser mit Doppelklick auf firefox gestartet werden.

Nun wird noch ein Exploit benötigt, den wir bereits im Metasploit integriert vorfinden.

msfconsole
use auxiliary/gather/firefox_pdfjs_file_theft

options ## default: stiehlt passwd u. shadow, listen to world auf Port 8080

set FILES ...

RUN

Es wird nun eine URL generiert und in der Ausgabe z.B. http://0.0.0.0:8080/A3uJQWEdSha angezeigt, die im verwundbaren Browser aufgerufen werden soll (also z.B. http://localhost:8080/A3uJQWEdSha).

Wie man nun in der msfconsole sieht, wurden die Dateien extrahiert.

Nun soll firejail installiert werden mit:

apt update
apt install firejail

Im Anschluss dann der Browser gestartet werden:

cd firefox ## wechsle in den firefox Ordner
firejail --private-home=/home/hacker/firefox bash ## mache ein privates Home mit dem firefox Ordner 
firejail ./firefox 

Das ist so umständlich, weil wir ein Browser im PATH haben und sonst dieser gestartet würde. Was passiert wenn trotzdem dieser gestartet wird und auf file:/// navigiert wird? Welche Dateien sind zu sehen?

Nun soll der Exploit nochmals ausgeführt werden. Was wurde extrahiert? Nichts.

Calendar December 26, 2021