Abstract

A small company moved some of its resources to a private cloud installation. The developers left the redirect to the dashboard on their web server. The security team got an email from the alleged attacker stating that the user data was leaked. It is up to you to investigate the situation.

This sherlock provides two packet captures, controller.2025-07-01.pcap and web-server.2025-07-01.pcap.


Question 1

What tool did the attacker use to fuzz the web server ? (Format- include version e.g, nmap@7.80)

Since the question already mentions the web server, I start by loading the associated packet capture into Wireshark. Filtering the traffic for HTTP shows the user-agent Fuzz Faster U Fool v2.1.0-dev and that’s the slogan for ffuf.

ffuf@2.1.0

Question 2

Which subdomain did the attacker discover?

Right after the fuzzing stops, there’s a GET request to cloud.vantage.tech from the same IP 117.200.21.26 with another user-agent.

cloud

Question 3

How many login attempts did the attacker make before successfully logging in to the dashboard?

I keep the filter for the ip.src == 117.200.21.26 and then limit the results to only POST requests with http.request.method == POST. This returns just 4 packets, each to /dashboard/auth/login/. The response to the last one returns a 302 status code and sets cookies, so it’s safe to assume the login worked. That leaves 3 previous attempts.

3

Question 4

When did the attacker download the OpenStack API remote access config file? (UTC)

After getting access to the dashboard, the attacker only accessed a few endpoints. Going through the HTTP responses, the request to /dashboard/project/api_access/openrc/ contains the config with different environment variables.

2025-07-01 09:40:29

Question 5

When did the attacker first interact with the API on controller node? (UTC)

Now I load the packet capture for the controller and filter the traffic for the attacker IP. The first packet in the list occurs shortly after the config was downloaded.

2025-07-01 09:41:44

Question 6

What is the project id of the default project accessed by the attacker?

As earlier, I add a filter for HTTP traffic and scroll through the list as it’s rather short. Towards the end there’s a request to /identity/v3/projects with multiple parameters. The server responds with JSON containing the project ID, followed up by the attacker with a PUT to the project.

9fb84977ff7c4a0baf0d5dbb57e235c7

Question 7

Which OpenStack service provides authentication and authorization for the OpenStack API?

There’s a call to /identity/v3/services at the beginning of the capture. It returns JSON data with all the available services and lists keystone as the identity provider.

{
    "services": [
        {
            "name": "cinder",
            "description": "Cinder Volume Service",
            "id": "2c88abbce32146cc9fc3ec2543ed2590",
            "type": "block-storage",
            "enabled": true,
            "links": {
                "self": "http://134.209.71.220/identity/v3/services/2c88abbce32146cc9fc3ec2543ed2590"
            }
        },
        {
            "description": "Glance Image Service",
            "name": "glance",
            "id": "33e9974d827c44c1858ba54394f83019",
            "type": "image",
            "enabled": true,
            "links": {
                "self": "http://134.209.71.220/identity/v3/services/33e9974d827c44c1858ba54394f83019"
            }
        },
        {
            "description": "Nova Compute Service (Legacy 2.0)",
            "name": "nova_legacy",
            "id": "5511fb633aeb478f80b57f35a573e063",
            "type": "compute_legacy",
            "enabled": true,
            "links": {
                "self": "http://134.209.71.220/identity/v3/services/5511fb633aeb478f80b57f35a573e063"
            }
        },
        {
            "name": "keystone",
            "id": "9bc4045e7dde47a9ae38bea53e0ff05c",
            "type": "identity",
            "enabled": true,
            "links": {
                "self": "http://134.209.71.220/identity/v3/services/9bc4045e7dde47a9ae38bea53e0ff05c"
            }
        },
        {
            "description": "Nova Compute Service",
            "name": "nova",
            "id": "a0ae7efb370840889a621e8c0893f7b4",
            "type": "compute",
            "enabled": true,
            "links": {
                "self": "http://134.209.71.220/identity/v3/services/a0ae7efb370840889a621e8c0893f7b4"
            }
        },
        {
            "name": "placement",
            "description": "Placement Service",
            "id": "dc9b8604dd4f4567b378ea962451582b",
            "type": "placement",
            "enabled": true,
            "links": {
                "self": "http://134.209.71.220/identity/v3/services/dc9b8604dd4f4567b378ea962451582b"
            }
        },
        {
            "description": "Swift Service",
            "name": "swift",
            "id": "f9194820052d4788b09157bf0a0dfdd0",
            "type": "object-store",
            "enabled": true,
            "links": {
                "self": "http://134.209.71.220/identity/v3/services/f9194820052d4788b09157bf0a0dfdd0"
            }
        },
        {
            "name": "neutron",
            "description": "Neutron Service",
            "id": "ff889368f61f4fcfaa6ad584613e56fc",
            "type": "network",
            "enabled": true,
            "links": {
                "self": "http://134.209.71.220/identity/v3/services/ff889368f61f4fcfaa6ad584613e56fc"
            }
        }
    ],
    "links": {
        "next": null,
        "self": "http://134.209.71.220/identity/v3/services",
        "previous": null
    }
}

keystone

Question 8

What is the endpoint URL of the swift service?

There’s a call to /identity/v3/auth/tokens that returns the service catalog1 containing the link to the service(s).

{
    "token": {
        "methods": [
            "password"
        ],
        "user": {
            "domain": {
                "id": "default",
                "name": "Default"
            },
            "id": "b1cbe2fc995a47ae85a4408a52aeca38",
            "name": "admin",
            "password_expires_at": null
        },
        "audit_ids": [
            "rj-93LP-RPW_jYnyVnX4Lw"
        ],
        "expires_at": "2025-07-01T10:43:26.000000Z",
        "issued_at": "2025-07-01T09:43:26.000000Z",
        "project": {
            "domain": {
                "id": "default",
                "name": "Default"
            },
            "id": "9fb84977ff7c4a0baf0d5dbb57e235c7",
            "name": "admin"
        },
        "is_domain": false,
        "roles": [
            {
                "id": "d3649868c2f341c6888d66ca0081f688",
                "name": "reader"
            },
            {
                "id": "65d7c4b6697b4b82a18ebb500ce3958d",
                "name": "member"
            },
            {
                "id": "0501401642464242bcd799437b71bdc9",
                "name": "admin"
            },
            {
                "id": "0f9fa828df4c4ff083eb16461dd78e9e",
                "name": "manager"
            }
        ],
        "catalog": [
            // --- SNIP ---
            {
                "endpoints": [
                    {
                        "id": "968f23a3924346a3bdddae69879080bb",
                        "interface": "admin",
                        "region_id": "RegionOne",
                        "url": "http://134.209.71.220:8080",
                        "region": "RegionOne"
                    },
                    {
                        "id": "fa462e9eb3174b5d9af61ea50e8f23cb",
                        "interface": "public",
                        "region_id": "RegionOne",
                        "url": "http://134.209.71.220:8080/v1/AUTH_9fb84977ff7c4a0baf0d5dbb57e235c7",
                        "region": "RegionOne"
                    }
                ],
                "id": "f9194820052d4788b09157bf0a0dfdd0",
                "type": "object-store",
                "name": "swift"
            },
            // --- SNIP ---
        ]
    }
}

http://134.209.71.220:8080/v1/AUTH_9fb84977ff7c4a0baf0d5dbb57e235c7

Question 9

How many containers were discovered by the attacker?

The request to the URL from Question 8 returns three containers.

[
    {
        "name": "dev-files",
        "count": 0,
        "bytes": 0,
        "last_modified": "2025-07-01T04:22:36.008860",
        "storage_policy": "Policy-0"
    },
    {
        "name": "employee-data",
        "count": 0,
        "bytes": 0,
        "last_modified": "2025-07-01T04:22:28.334080",
        "storage_policy": "Policy-0"
    },
    {
        "name": "user-data",
        "count": 0,
        "bytes": 0,
        "last_modified": "2025-07-01T04:22:07.707130",
        "storage_policy": "Policy-0"
    }
]

3

Question 10

When did the attacker download the sensitive user data file? (UTC)

At 09:45:23 the attacker downloaded user-details.csv from the user-data container.

2025-07-01 09:45:23

Question 11

How many user records are in the sensitive user data file?

Going to File Export Objects HTTP.. I can download all files from the HTTP streams. There I search for user-details.csv, save the file to disk and count the lines.

28

Question 12

For persistence, the attacker created a new user with admin privileges. What is the username of the new user?

There’s a POST to /identity/v3/users with the following JSON payload to create user jellibean.

{
    "user": {
        "password": "P@$$word",
        "enabled": true,
        "default_project_id": "9fb84977ff7c4a0baf0d5dbb57e235c7",
        "name": "jellibean"
    }
}

jellibean

Question 13

What is the password of the new user?

P@$$word

Question 14

What is MITRE tactic id of the technique in task 12?

The attacker created a new cloud account.

T1136.003

Footnotes

  1. OpenStack API Documentation