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 inImp
. The use ofi % len(Imp)
ensures that ifMyValue
is longer thanImp
, the process will loop back to the start ofImp
. - The result of each XOR operation is appended to the bytearray.
- Finally, the
bytearray
is converted back to a bytes object and returned.
- This function takes a byte string as input and creates an empty
- Encryption Process:
- The script calls
enc
withMyValue.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.
- The script calls
- Print Statement:
- The script prints the result of the
enc
function, which should be the obfuscated version ofMyValue
.
- The script prints the result of the
However, since MyValue
is already a byte string, .encode()
is not needed and will cause an error.
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)
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
Lets dissect it:
The function
retrieve
is defined to accept acode
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. Theretrieve
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==
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.
This time we find blanket
and deployer
.
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==
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==
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 🚩
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)🚩
In Objective - 4 we are going to dive even more deeper into the intricacies of Azure and its componets.
Comments powered by Disqus.