Secret of Meow Olympurr

Secret of Meow Olympurr

Category: Cloud Difficulty: Medium Tags: AWS, Azure

Challenge Description

From the challenge description, I identified a few key information

  1. There are misconfiguration in the cloud configuration

  2. It is a multi-cloud configuration, with two environment

  3. To get the flag, I will need to invoke a function

I am also given the URL to a AWS CloudFront

d2p9lw76n0gfo0.cloudfront.net

Enumeration

Visiting the URL shows a website with alot of cute cats, and it also reminds me of CloudyNekos from TISC 2022

Viewing the source code of the website does not reveal any useful information, however when visiting the error page, it shows some interesting information.

Error page

The image src is http://18.141.147.115:8080/https://meowolympurr.z23.web.core.windows.net/images/ohno.jpg which made me suspect that it is a possible remote file inclusion (RFI) vector, and I went down a really long rabbit hole of enumerating and trying to exploit the RFO.

Attempting to exploit RFI (Rabbit Hole)

I first identified the API that is running at http://18.141.147.115:8080 is Cors_anywhere

I am also able to visit http://18.141.147.115:8080/http://169.254.169.254/latest/meta-data and extract the credentials at http://18.141.147.115:8080/http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance

However, after spending hours enumerating with the credentials, I was unable to proceed anywhere. I revisited this http://18.141.147.115:8080/https://meowolympurr.z23.web.core.windows.net/images/ohno.jpg url, and I realized that I missed out on the glaringly obvious Azure URL Syntax.

I double check my suspicion by visiting Microsoft documentation and identified that it is an Azure DNS zone endpoints.

Visiting https://meowolympurr.z23.web.core.windows.net/ shows the exact page as the AWS CloudFront end point, with an extra endpoint pointing to Azure Function App (which we will revisit in later steps), however things get interesting again when visiting the error page.

When visiting view-source:https://meowolympurr.z23.web.core.windows.net/asd it shows a SAS Key for Azure Storage Account, and I connected to the storage account with Microsoft Azure Storage Explorer.

💡 SAS (Shared Access Signature) key is a string of characters that allows access to a specific Azure storage account resource. SAS keys are typically used to grant access to resources in a storage account to users or applications that do not have direct access to the storage account key. The SAS key provides a secure and flexible way to grant access to storage account resources without giving users or applications access to the storage account key.

https://meowolympurr.blob.core.windows.net?sv=2017-07-29&ss=b&srt=sco&sp=rl&se=2022-12-12T00:00:00Z&st=2022-09-01T00:00:00Z&spr=https&sig=UE2%2FTMTAzDnyJEABpX4OYFBs1b1uAWjwEEAtjeQtwxg%3D

Connecting to Azure Storage Account

I used the GUI application Microsoft Azure Storage Explorer

Upon connecting to the storage account with the SAS, it shows that there are 3 blobs containers.

Looking at the dev container shows a readme.md file which shows hints to continue the challenge.

# Meow Olympurr 
One stop service for all fun activites in Meow Olympurr! 
    
All resources are hosted on a single tenant: 83e595f4-f086-4f2f-9de8-d698b6012093

Meows are not cy-purr security trained, but we are willing to learn! 
    
# To do 
1. Consolidate the asset list 
2. Seek advice from Jaga and team when they arrive! 
3. Integrate services 
4. Remove credentials used for debugging access to function app

# Function app - https://olympurr-app.azurewebsites.net/api/meowvellous
SAS token to access the scm-releases container: ?sv=2018-11-09&sr=c&st=2022-09-01T00%3A00%3A00Z&se=2022-12-12T00%3A00%3A00Z&sp=rl&spr=https&sig=jENgCFTrC1mYM1ZNo%2F8pq1Hg9BO1VLbXlk%2FpABrK4Eo%3D

## Credentials for debugging
The following service principal has the same privileges as the function app
Application ID: ee92075f-4ddc-4522-a12c-2bc0ab874c85
Client Secret: kmk8Q~mGYD9jNfgm~rcIOMRgiC9ekKtNEw5GPaS7

The readme.md gave a few key information.

  1. Tenant ID

  2. Application ID

  3. Client Secret

  4. Function Application Endpoint

  5. SAS token for the scm-releases container

Using the application id and client secret I am able to login with the service principal, which has the same privileges as the function app. I will be using az powershell, as I am more familiar with it.

💡 An Azure service principal is a security identity that is used by applications or services to access resources in Azure. It is similar to a user identity, but is specific to applications or services, and can be used to grant permissions to access Azure resources

Connecting with the Azure using powershell

powershell -ep bypass

$TenantId = '83e595f4-f086-4f2f-9de8-d698b6012093'
$Credential = Get-Credential
Connect-AzAccount -ServicePrincipal -TenantId $TenantId -Credential $Credential

For the Get-Credential cmdlets, put the application id as username, and client secret as password

Since the readme.md above gave a SAS key I will first try and enumerate storage account with the Get-AzStorageAccount cmdlet.

As suspected, there is another storage account called meowvellousappstorage and I am able to connect to the scm-releases container with the SAS in the readme.

https://meowvellousappstorage.blob.core.windows.net/scm-releases?sv=2018-11-09&sr=c&st=2022-09-01T00%3A00%3A00Z&se=2022-12-12T00%3A00%3A00Z&sp=rl&spr=https&sig=jENgCFTrC1mYM1ZNo%2F8pq1Hg9BO1VLbXlk%2FpABrK4Eo%3D

In the scm-releases container, it shows a zip file scm-latest-olympurr-app.zip which is the source code of the Azure Function enumerated previously.

import boto3
import requests
import json

import azure.functions as func
from azure.identity import ManagedIdentityCredential
from azure.keyvault.secrets import SecretClient

functionName = "event-webservice"
keyName = "AKIA5G4XMRW7TLT6XD7R"

def logURL(url):
    identity = ManagedIdentityCredential()
    secretClient = SecretClient(vault_url="https://olympurr-aws.vault.azure.net/", credential=identity)
    secret = secretClient.get_secret(keyName).value
    session = boto3.Session(
        aws_access_key_id=keyName,
        aws_secret_access_key=secret
    )
    
    lambda_client = session.client("lambda", region_name="ap-southeast-1")

    details = {"url" : url}
    lambda_client.invoke(
        FunctionName=functionName,
        InvocationType="RequestResponse",
        Payload=bytes(json.dumps(details), "utf-8")
    )
    return secret

def main(req: func.HttpRequest) -> func.HttpResponse:
    url = req.params.get('url')

    if not url:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            name = req_body.get('url')

    if url:
        # Log the URL in AWS 
        secret = logURL(url)
        try:
            response = requests.get(url)
            return func.HttpResponse(response.text)
        except Exception as e:
            return func.HttpResponse(str(e))
    
    return func.HttpResponse(
            """Found an interesting event you would like to organise in Meow Olympurr?
Pass the URL as a query string. You will see the submitted information if it is successful. 
e.g. https://olympurr-app.azurewebsites.net/api/meowvellous?url=<INSERT>
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⡷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⡿⠋⠈⠻⣮⣳⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣾⡿⠋⠀⠀⠀⠀⠙⣿⣿⣤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣶⣿⡿⠟⠛⠉⠀⠀⠀⠀⠀⠀⠀⠈⠛⠛⠿⠿⣿⣷⣶⣤⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⣾⡿⠟⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠛⠻⠿⣿⣶⣦⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⣀⣠⣤⣤⣀⡀⠀⠀⣀⣴⣿⡿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠿⣿⣷⣦⣄⡀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣄⠀⠀
⢀⣤⣾⡿⠟⠛⠛⢿⣿⣶⣾⣿⠟⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠿⣿⣷⣦⣀⣀⣤⣶⣿⡿⠿⢿⣿⡀⠀
⣿⣿⠏⠀⢰⡆⠀⠀⠉⢿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠻⢿⡿⠟⠋⠁⠀⠀⢸⣿⠇⠀
⣿⡟⠀⣀⠈⣀⡀⠒⠃⠀⠙⣿⡆⠀⠀⠀⠀⠀⠀⠀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠇⠀
⣿⡇⠀⠛⢠⡋⢙⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠀⠀
⣿⣧⠀⠀⠀⠓⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠛⠋⠀⠀⢸⣧⣤⣤⣶⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⡿⠀⠀
⣿⣿⣤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠻⣷⣶⣶⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⠁⠀⠀
⠈⠛⠻⠿⢿⣿⣷⣶⣦⣤⣄⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⡏⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠉⠙⠛⠻⠿⢿⣿⣷⣶⣦⣤⣄⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠿⠛⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢿⣿⡄⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠙⠛⠻⠿⢿⣿⣷⣶⣦⣤⣄⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣿⡄⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠛⠛⠿⠿⣿⣷⣶⣶⣤⣤⣀⡀⠀⠀⠀⢀⣴⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⡿⣄
   Send us the details!            ⠀⠀⠉⠉⠛⠛⠿⠿⣿⣷⣶⡿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣹
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⠀⠀⠀⠀⠀⠀⢸⣧
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣆⠀⠀⠀⠀⠀⠀⢀⣀⣠⣤⣶⣾⣿⣿⣿⣿⣤⣄⣀⡀⠀⠀⠀⣿
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⢿⣻⣷⣶⣾⣿⣿⡿⢯⣛⣛⡋⠁⠀⠀⠉⠙⠛⠛⠿⣿⣿⡷⣶⣿
            """,
            status_code=200
    )

Extracting the source code with unsquashfs identify a few information.

  1. An AWS key with the key name of AKIA5G4XMRW7TLT6XD7R

  2. An Lamba Function with the function name event-webservice

  3. In the function logURL it shows the lambda function getting a managed identity and connecting to Azure Key Vault to retrieve a secret key.

💡 Azure managed identity is a feature of Azure Active Directory that allows an Azure resource, such as a virtual machine, to be authenticated and authorized to access other Azure resources.

Since we knew that the service principal we are connected has the same permission as the managed identity, I am able to directly call the Get-AzKeyVaultSecret cmdlet to retrieve the AWS secret.

💡 Azure Key Vault is a cloud-based service for securely storing and managing cryptographic keys and secrets.

Get-AzKeyVaultSecret -VaultName "olympurr-aws" -Name "AKIA5G4XMRW7TLT6XD7R"

Pivot back to AWS

Using AWS cli, I am able to login with the set of access key and secret access key

Using the tool pacu, I am able to enumerate my user permission.

docker run -it -v ~/.aws:/root/.aws rhinosecuritylabs/pacu:latest
import_keys --all
exec iam__bruteforce_permissions

I am able to identified the allow permissions.

"Allow": [
      "ec2:DescribeLogGroups",
      "s3:DescribeLogGroups",
      "logs:DescribeLogGroups",
      "ec2:DescribeLogStreams",
      "s3:DescribeLogStreams",
      "logs:DescribeLogStreams",
      "ec2:GetQueryResults",
      "s3:GetQueryResults",
      "logs:GetQueryResults"
    ]

Since we have the logs:DescribeLogGroups permission set, lets try running that first

aws logs describe-log-groups

There are quite a few log groups, however two of them caught my eyes.

The /aws/lambda/event-webservice was the function name identified in the source code from scm-releases and

/aws/lambda/internal-secret-of-MeowOlympurr-webservice seems to reveal the secrets (flag).

Recall from the function application source code that the IAM user is able to invoke a lambda function, despite it not being reflected in the permission enumerated from pacu.

lambda_client.invoke(
        FunctionName=functionName,
        InvocationType="RequestResponse",
        Payload=bytes(json.dumps(details), "utf-8")
    )

I attempted to invoke the internal-secret-of-MeowOlympurr-webservice and I am given the flag.

aws lambda invoke  --function-name internal-secret-of-MeowOlympurr-webservice outfile

Conclusion

Flag: STF22{LIveInTh3Me0wmen7_:3}

The challenge is a nice step above Cloudy Nekos from TISC. It covers misconfiguration in a multi-cloud environment, testing participants capability in enumerating services in both AWS and Azure.

ps the cats were really cute

Last updated