Post

DART CTF - Objective 3

DART CTF - Objective 3 Walkthrough

Objective 3

Task

  • Extract information about Azure Functions in the target environment.
  • Use a function key to retrieve Flag 3 from a function.
  • Find Flag 4 by using a logic app parameter.
  • Use a function key from the above task to retrieve Flag 5 from another function.
  • Use a function key from the above task to retrieve Flag 6 from another function.

Solution

Lets continue analysing and understanding the code we identified in Objective - 2. The code appears to implement a simple encryption mechanism using the XOR bitwise operation. Let’s break down the script:

1
2
3
4
5
6
7
8
9
10
11
Imp = b'Use the same carefully'
MyValue =  b'a*)h\x1f/!U9&\x1f\x1cz\x19\x038\r%/?\x15)\x10\x1d\t\x15A\\\nt&S8:L2%7\tW\x1dZ54\x14\t#U8\r?b70PX'

def enc(MyValue):
    bytevalue = bytearray()
    for i in range(len(MyValue)):
        bytevalue.append(MyValue[i] ^ Imp[i % len(Imp)])
    return bytes(bytevalue)

value = enc(MyValue.encode())
print(value)
  • Variables:
    • Imp is a byte string. In Python, b'' denotes a byte string.
    • MyValue is another byte string.
  • Function enc:
    • This function takes a byte string as input and creates an empty bytearray, which is a mutable sequence of bytes.
    • The function then iterates over each byte in the input byte string.
    • For each byte, it performs an XOR (^) operation with the corresponding byte in Imp. The use of i % len(Imp) ensures that if MyValue is longer than Imp, the process will loop back to the start of Imp.
    • The result of each XOR operation is appended to the bytearray.
    • Finally, the bytearray is converted back to a bytes object and returned.
  • Encryption Process:
    • The script calls enc with MyValue.encode(). The XOR operation is a common method for simple encryption. When you XOR a piece of data with a key, you can reverse the process by XORing the result with the same key.
  • Print Statement:
    • The script prints the result of the enc function, which should be the obfuscated version of MyValue.

However, since MyValue is already a byte string, .encode() is not needed and will cause an error.

image

Instead we can pass MyValue directly to the enc function.

1
2
3
4
5
6
7
8
9
10
11
12
Imp = b'Use the same carefully'
MyValue =  b'a*)h\x1f/!U9&\x1f\x1cz\x19\x038\r%/?\x15)\x10\x1d\t\x15A\\\nt&S8:L2%7\tW\x1dZ54\x14\t#U8\r?b70PX'

def enc(MyValue):
    bytevalue = bytearray()
    for i in range(len(MyValue)):
        bytevalue.append(MyValue[i] ^ Imp[i % len(Imp)])
    return bytes(bytevalue)

value = enc(MyValue)
print(value)

image

Smooth. Now we have a Key. Earlier on when we fuzzed the test parameter we found two possible parameter’s that we can visit, i.e action & debug. So far we’ve explored debug . TIme to check out action. On visiting the following URL:

1
https://prod-61.eastus.logic.azure.com/workflows/250827f3ebc54c368f85643619f38ce3/triggers/manual/paths/invoke/action?api-version=2018-07-01-preview&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=avLLG0xOCALGGT-7zmIJsddcUiL5o2GOijT4mPSA4JY

we get another python script and Flag 4

image

Lets dissect it:

  • The function retrieve is defined to accept a code parameter.

  • If a code is provided , the function uses the requests library to send an HTTP GET request to https://rosarray.azurewebsites.net/api/Canister and appends the provided code as a query parameter.

  • After making the request, the function checks the HTTP status code of the response.

  • Outside of the retrieve function, the code variable is set to a specific string. The retrieve function is then called with this code, and the result is stored in the variable results.

  • The code checks if the results contain an “error” key:

Basically this code interacts with an API endpoint that requires a security code for access. The code variable likely represents an API key or token that grants access to the Canister function in the Azure Functions app hosted at rosarray.azurewebsites.net.

With this in mind, lets try access the endpoint using the previously decrypted code:

1
http://rosarray.azurewebsites.net/api/Canister?code=4YLHkGDuJGryZzbJhCZSyPEnl554oTU2U_lQDEl1h6YMAzFuLeZBDQ==

image

But hold that thought there. While exploring the blob earlier using Azure Windows Storage Explorer, i recall seeing a directory called rosarray in the blob container azure-webjobs-secrets. Lets go back and check if we can find more functions other than canister.

image

This time we find blanket and deployer.

image

host.json looks interesting, let’s view it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
  "masterKey": {
    "name": "master",
    "value": "CfDJ8AAAAAAAAAAAAAAAAAAAAAAzpeADcTSwJp_43EQyqIRSd-uDekfdk8Wsk-wIMBlo3GD8da3dL59uaDtstCis3_UB1j-mA_U6zkjKg2cCZxHC7AOPogXiTLiLeUIhO7AJxh5LslOn51LNWNetdEYjPxiWAT4Vl5mVJoJ_DmvZ_PRinq7Sv3jWs1Q7gVO7C_VxtQ",
    "encrypted": true
  },
  "functionKeys": [
    {
      "name": "default",
      "value": "CfDJ8AAAAAAAAAAAAAAAAAAAAABzWmb45YZ95DyetB5fIg--SuQR1bxk4UZ2s8lYXmY3ODMFoPj4wPJWqUupY3OYCvqwGAXQAjVbHDjoBmn7QMDlquz8BNpjEOtZY70apNKmNk1228gnA5FK4F306Ra6awG_cooIuKAuVPTC6RUiHRBkHctVagML4o03bvzsrIhG0w",
      "encrypted": true
    }
  ],
  "systemKeys": [],
  "hostName": "rosarray.azurewebsites.net",
  "instanceId": "0000000000000000000000002B233D22",
  "source": "runtime",
  "decryptionKeyId": "AzureWebEncryptionKey=71K9CPtGDRphMirq9D21FkBghc3YmeQlIbrYA93zK1c=;"
}

The JSON content appears to be a configuration file for an Azure Function application. It contains various keys used by the Azure Functions host. Here’s a breakdown of the contents:

  • masterKey:
    • name: A label for the key, here it is “master”.
    • value: The actual key value, which appears to be encrypted. This key is typically used to provide administrative access to the function app.
    • encrypted: Indicates that the key is stored in an encrypted form.
  • functionKeys:
    • A list of keys that are used to provide access to individual functions within the app.
  • systemKeys:
    • These are keys used by the system, likely for internal Azure processes or extensions. In this case, it appears to be an empty array, indicating no system keys are set.
  • hostName:
    • The DNS name for the function app, which is typically rosarray.azurewebsites.net.
  • instanceId:
    • A unique identifier for the instance of the function app.
  • source:
    • Indicates where these keys are coming from; in this case, it’s “runtime”, which suggests that the keys are used at runtime by the Azure Functions host.
  • decryptionKeyId:
    • This is likely the identifier for the key that is used to decrypt the masterKey and functionKeys.

With that said, lets explore the other three json files:

deployer.json

1
2
3
4
5
6
7
8
9
10
11
12
13
{
  "keys": [
    {
      "name": "default",
      "value": "CfDJ8AAAAAAAAAAAAAAAAAAAAACySloWXZj5BQqDaJAciFzbvl05A5_XcJEysETsnWFCWkssLhWrbMrAkODRp0us2hJz9zZ4Ncpl5f_GcexVKZol7B0ttqzLcv4SEOHYCn8teBEoOLGm5ADlbFI6SBFCytDKgWo3Ko8EhXFbw7ypysRPXrfCMamaKnPYu1twW6Gh0g",
      "encrypted": true
    }
  ],
  "hostName": "rosarray.azurewebsites.net",
  "instanceId": "0000000000000000000000000403D027",
  "source": "runtime",
  "decryptionKeyId": "AzureWebEncryptionKey=71K9CPtGDRphMirq9D21FkBghc3YmeQlIbrYA93zK1c=;"
}

canister.json

1
2
3
4
5
6
7
8
9
10
11
12
13
{
  "keys": [
    {
      "name": "default",
      "value": "CfDJ8AAAAAAAAAAAAAAAAAAAAAAtCjMDQrEZW7OyShi4qC7autHbJ61Te6GcgFDj7N47Vz0pl04lIqDRtlWz8Tj9038K9CwQs0OsSFO_4E_F8fkGo-D8p81Zlk4h4WLhjyyzwQ1GhW00D4kcib5kGLT02StUHLVKOQI3D7YImDXD6dMZu4MId2zcOlqIe7r7Vda6xw",
      "encrypted": true
    }
  ],
  "hostName": "rosarray.azurewebsites.net",
  "instanceId": "0000000000000000000000006B282786",
  "source": "runtime",
  "decryptionKeyId": "AzureWebEncryptionKey=71K9CPtGDRphMirq9D21FkBghc3YmeQlIbrYA93zK1c=;"
}

blanket.json

1
2
3
4
5
6
7
8
9
10
11
12
13
{
  "keys": [
    {
      "name": "default",
      "value": "CfDJ8AAAAAAAAAAAAAAAAAAAAAD9wsuBOAoIYUE14L8q6MaGzJyQFotW7XZSn1Cf4xTtXF6Pm8RDXB7vRJrmmL0krT0D8O7bZs5dQGED51rUcadQLvGaYYH4aPJzx9lfXarajHe6ZCjChYEU3jtcy265ueSa1k-J6hz2XmP6kjI-gB0yxt3zCf0rkhJOjgR6-6DI3w",
      "encrypted": true
    }
  ],
  "hostName": "rosarray.azurewebsites.net",
  "instanceId": "0000000000000000000000002B233D22",
  "source": "runtime",
  "decryptionKeyId": "AzureWebEncryptionKey=71K9CPtGDRphMirq9D21FkBghc3YmeQlIbrYA93zK1c=;"
}

deployer.json, canister.json, blanket.json: Likely represent different components or services within the application environment, each with its own set of keys for access and operation.

They all share the same decryptionKeyId, which implies they use the same encryption key for encrypting and decrypting the stored keys.

Lets now continue testing if we get any results with blanket and deployer functions:

1
2
http://rosarray.azurewebsites.net/api/Blanket?code=4YLHkGDuJGryZzbJhCZSyPEnl554oTU2U_lQDEl1h6YMAzFuLeZBDQ==
http://rosarray.azurewebsites.net/api/Deployer?code=4YLHkGDuJGryZzbJhCZSyPEnl554oTU2U_lQDEl1h6YMAzFuLeZBDQ==

image

image

I did not succeed with deployer but i got a flag on blanket

Moving on, let’s use the code we found in the python script to access the canister function:

1
http://rosarray.azurewebsites.net/api/canister?code=7CIzVAz1-SRtgbuwRG-PMTnL_BYbDhGaXrU-S-ZTEpDGAzFuCDmwrA==

image

We get some statistics in a JSON format. We also find a key potentially usable with the deployer function as highlighted. Towards the end of the json you also get Flag 5 🚩

image

Let’s try access deployer using the key identified:

1
https://rosarray.azurewebsites.net/api/deployer?code=li1u2C-xrQ_xvUA5d18DUKcniUSAAd4NY_tS3KmsnTYGAzFuoYq5vw==

We get a response and the final flag for this objective. (Flag 6)🚩

image

In Objective - 4 we are going to dive even more deeper into the intricacies of Azure and its componets.

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

Comments powered by Disqus.