FTP
Nmap discovered a FTP server running on the port 2121
of the 192.168.210.214
host.
The running service is vsftpd 3.0.5
.
Null Session
┌──(kali㉿kali)-[~/PEN-200/PG_PRACTICE/spidersociety]
└─$ ftp $IP -P 2121
Connected to 192.168.210.214.
220 (vsFTPd 3.0.5)
Name (192.168.210.214:kali):
331 Please specify the password.
Password:
530 Login incorrect.
ftp: Login failed
ftp> ^D
221 Goodbye.
┌──(kali㉿kali)-[~/PEN-200/PG_PRACTICE/spidersociety]
└─$ ftp ftp@$IP -P 2121
Connected to 192.168.210.214.
220 (vsFTPd 3.0.5)
331 Please specify the password.
Password:
530 Login incorrect.
ftp: Login failed
ftp> ^D
221 Goodbye.
┌──(kali㉿kali)-[~/PEN-200/PG_PRACTICE/spidersociety]
└─$ ftp anonymous@$IP -P 2121
Connected to 192.168.210.214.
220 (vsFTPd 3.0.5)
331 Please specify the password.
Password:
530 Login incorrect.
ftp: Login failed
ftp> ^D
221 Goodbye.
The target FTP server does not allow null session. A valid credential is required.
ss_ftpbckuser
Session
An FTP credential was retrieved from the target Web application; ss_ftpbckuser
:ss_WeLoveSpiderSociety_From_Tech_Dept5937!
┌──(kali㉿kali)-[~/PEN-200/PG_PRACTICE/spidersociety]
└─$ ftp ss_ftpbckuser@$IP -P 2121
Connected to 192.168.210.214.
220 (vsFTPd 3.0.5)
331 Please specify the password.
Password: ss_WeLoveSpiderSociety_From_Tech_Dept5937!
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> rstatus
211-FTP server status:
Connected to 192.168.45.182
Logged in as ss_ftpbckuser
TYPE: ASCII
No session bandwidth limit
Session timeout in seconds is 300
Control connection is plain text
Data connections will be plain text
At session startup, client count was 1
vsFTPd 3.0.5 - secure, fast, stable
211 End of status
ftp> put test
local: test remote: test
229 Entering Extended Passive Mode (|||40421|)
150 Ok to send data.
0 0.00 KiB/s
226 Transfer complete.
Successfully authenticated. Additionally, write access is granted.
ftp> ls
229 Entering Extended Passive Mode (|||44808|)
150 Here comes the directory listing.
-rwxr-xr-x 1 0 0 1391 Apr 14 17:53 404.html
drwxr-xr-x 2 0 0 4096 Apr 14 17:53 images
-rwxr-xr-x 1 0 0 4317 Apr 14 17:53 index.html
drwxr-xr-x 2 0 0 4096 Apr 14 17:53 libspider
-rwxr-xr-x 1 0 0 1345 Apr 14 17:53 simple.py
-rw------- 1 1002 1002 0 Jun 26 15:55 test
226 Directory send OK.
Checking the directory reveals that this appears to be the web root directory for the target Web server.
ftp> cd libspider
250 Directory successfully changed.
ftp> put test
local: test remote: test
229 Entering Extended Passive Mode (|||41334|)
553 Could not create file.
Unable to write to the /libspider
directory where a PHP web application is being hosted.
simple.py
ftp> more simple.py
#!/usr/env python3
import http.server
import os
import logging
try:
import http.server as server
except ImportError:
# Handle Python 2.x
import SimpleHTTPServer as server
class HTTPRequestHandler(server.SimpleHTTPRequestHandler):
"""
SimpleHTTPServer with added bonus of:
- handle PUT requests
- log headers in GET request
"""
def do_GET(self):
server.SimpleHTTPRequestHandler.do_GET(self)
logging.warning(self.headers)
def do_PUT(self):
"""Save a file following a HTTP PUT request"""
filename = os.path.basename(self.path)
# Don't overwrite files
if os.path.exists(filename):
self.send_response(409, 'Conflict')
self.end_headers()
reply_body = '"%s" already exists\n' % filename
self.wfile.write(reply_body.encode('utf-8'))
return
file_length = int(self.headers['Content-Length'])
with open(filename, 'wb') as output_file:
output_file.write(self.rfile.read(file_length))
self.send_response(201, 'Created')
self.end_headers()
reply_body = 'Saved "%s"\n' % filename
self.wfile.write(reply_body.encode('utf-8'))
if __name__ == '__main__':
server.test(HandlerClass=HTTPRequestHandler)
This appears to be a simple Python web server that supports file upload via PUT requests. It checks if the file already exists, then it saves it if it doesn’t exist. However, this does not seem to apply to the target web server as it is running Apache.
/libspider/users.php
ftp> more users.php
<?php
$users = [
"admin" => "admin"
];
?>
admin
:admin
/libspider/login.php
ftp> more login.php
<?php
session_start();
include 'users.php'; // Load user credentials
function login($username, $password) {
global $users;
// Validate user credentials
if (isset($users[$username]) && hash_equals($users[$username], $password)) {
$_SESSION["user"] = $username;
return true;
}
return false;
}
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$username = trim($_POST["username"] ?? '');
$password = trim($_POST["password"] ?? '');
if (login($username, $password)) {
echo json_encode(["success" => true]);
} else {
echo json_encode(["success" => false, "message" => "Invalid username or password."]);
}
exit();
}
?>
N/A
/libspider/fetch-credentials.php
ftp> more fetch-credentials.php
<?php
// fetch-credentials.php
// Path to the credentials file
$credentialsFile = __DIR__ . '/.fuhfjkzbdsfuybefzmdbbzdcbhjzdbcukbdvbsdvuibdvnbdvenv';
// Function to parse the credentials file
function getCredentials($filePath) {
if (!file_exists($filePath)) {
die('Credentials file not found.');
}
$lines = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$credentials = [];
foreach ($lines as $line) {
if (strpos($line, '=') !== false) {
list($key, $value) = explode('=', $line, 2);
$credentials[trim($key)] = trim($value);
}
}
return $credentials;
}
// Fetch credentials
$credentials = getCredentials($credentialsFile);
$user = $credentials['FTP_BACKUP_USER'] ?? null;
$pass = $credentials['FTP_BACKUP_PASS'] ?? null;
// Check if the request is coming from contro-panel.php
/* if ($_SERVER['HTTP_REFERER'] !== 'http://yourdomain.com/contro-panel.php') {
http_response_code(403);
die('Unauthorized access.');
} */
// Check if the user is authenticated
session_start();
if (!isset($_SESSION['user'])) {
http_response_code(401);
die('User not authenticated.');
}
// Respond with the credentials
header('Content-Type: application/json');
echo json_encode([
'FTP_BACKUP_USER' => $user,
'FTP_BACKUP_PASS' => $pass
]);
It would appear that the /libspider/fetch-credentials.php
file parses the FTP credential from the .fuhfjkzbdsfuybefzmdbbzdcbhjzdbcukbdvbsdvuibdvnbdvenv
file from the __DIR__
directory, which is a PHP magic constant to denote the current directory.
.fuhfjkzbdsfuybefzmdbbzdcbhjzdbcukbdvbsdvuibdvnbdvenv
Hidden files from within a FTP session can be listed using the
-la
flag.
ftp> more .fuhfjkzbdsfuybefzmdbbzdcbhjzdbcukbdvbsdvuibdvnbdvenv
Failed to open file.
Reading the file is impossible as it is owned by 33
(www-data
) and has its permission bits set to 0400
.
This would mean it can only be accessible from the web server.
The file also contains a DB credential;
spidey
:WithGreatPowerComesGreatSecurity99!
Testing it against the target SSH server for credential reuse.