Skip to content

Commit

Permalink
azure vm-custom-script-extension: rework detonation code
Browse files Browse the repository at this point in the history
  • Loading branch information
christophetd committed Jun 20, 2022
1 parent 07c93b5 commit 80a318a
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -1,43 +1,66 @@
---
title: Execute Commands on Virtual Machine using Custom Script Extension
title: Execute Command on Virtual Machine using Custom Script Extension
---

# Execute Commands on Virtual Machine using Custom Script Extension
# Execute Command on Virtual Machine using Custom Script Extension

<span class="smallcaps w3-badge w3-orange w3-round w3-text-sand" title="This attack technique might be slow to warm up or detonate">slow</span>
<span class="smallcaps w3-badge w3-blue w3-round w3-text-white" title="This attack technique can be detonated multiple times">false</span>


Platform: Azure

## MITRE ATT&CK Tactics


- Execution

## Description


By utilizing the 'CustomScriptExtension' extension on a Virtual Machine, an attacker can pass PowerShell commands to the VM as SYSTEM.

References:

- https://docs.microsoft.com/en-us/azure/virtual-machines/extensions/custom-script-windows
- https://github.com/hausec/Azure-Attack-Matrix/blob/main/Execution/AZT201/AZT201-2.md

<span style="font-variant: small-caps;">Warm-up</span>:
<span style="font-variant: small-caps;">Warm-up</span>:

- Create a virtual machine

<span style="font-variant: small-caps;">Detonation</span>:
<span style="font-variant: small-caps;">Detonation</span>:

- Configure and provision a Custom Script Extension for the virtual machine
- Configure a custom script extension for the virtual machine


## Instructions

```bash title="Detonate with Stratus Red Team"
stratus detonate azure.execution.vm-custom-script-extension
```

## Detection

1. Look for <code>Microsoft.Compute/virtualMachines/extensions/write</code> events in Azure Activity logs
2. Review files on disk located in <code>C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension</code>

Identify Azure events of type <code>Microsoft.Compute/virtualMachines/extensions/write</code>. Sample below (redacted for clarity).

```json hl_lines="7"
{
"duration": 0,
"resourceId": "/SUBSCRIPTIONS/<your-subscription-id>/RESOURCEGROUPS/RG-HAT6H48Q/PROVIDERS/MICROSOFT.COMPUTE/VIRTUALMACHINES/VM-HAT6H48Q/EXTENSIONS/CUSTOMSCRIPTEXTENSION-STRATUS-EXAMPLE",
"evt": {
"category": "Administrative",
"outcome": "Start",
"name": "MICROSOFT.COMPUTE/VIRTUALMACHINES/EXTENSIONS/WRITE"
},
"resource_name": "customscriptextension-stratus-example",
"time": "2022-06-18T19:57:27.8617215Z",
"properties": {
"hierarchy": "ecc2b97b-844b-414e-8123-b925dddf87ed/<your-subscription-id>",
"message": "Microsoft.Compute/virtualMachines/extensions/write",
"eventCategory": "Administrative",
"entity": "/subscriptions/<your-subscription-id>/resourceGroups/rg-hat6h48q/providers/Microsoft.Compute/virtualMachines/vm-hat6h48q/extensions/CustomScriptExtension-Stratus-Example"
},
}
```


6 changes: 4 additions & 2 deletions docs/attack-techniques/azure/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ Note that some Stratus attack techniques may correspond to more than a single AT

## Execution

- [Execute Command on Virtual Machine using Custom Script Extension](./azure.execution.vm-custom-script-extension.md)

- [Execute Commands on Virtual Machine using Run Command](./azure.execution.vm-run-command.md)
- [Execute on Virtual Machine using Custom Script Extension](./azure.execution.vm-custom-script-extension.md)


## Exfiltration

- [Export Disk Through SAS URL](./azure.exfiltration.disk-export.md)
- [Export Disk Through SAS URL](./azure.exfiltration.disk-export.md)

2 changes: 1 addition & 1 deletion docs/attack-techniques/list.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ This page contains the list of all Stratus Attack Techniques.
| [Create a Login Profile on an IAM User](./AWS/aws.persistence.iam-create-user-login-profile.md) | [AWS](./AWS/index.md) | Persistence, Privilege Escalation |
| [Backdoor Lambda Function Through Resource-Based Policy](./AWS/aws.persistence.lambda-backdoor-function.md) | [AWS](./AWS/index.md) | Persistence |
| [Overwrite Lambda Function Code](./AWS/aws.persistence.lambda-overwrite-code.md) | [AWS](./AWS/index.md) | Persistence |
| [Execute Command on Virtual Machine using Custom Script Extension](./azure/azure.execution.vm-custom-script-extension.md) | [Azure](./azure/index.md) | Execution |
| [Execute Commands on Virtual Machine using Run Command](./azure/azure.execution.vm-run-command.md) | [Azure](./azure/index.md) | Execution |
| [Virtual Machine Custom Script Extension](./azure/azure.execution.vm-custom-script-extension.md) | [Azure](./azure/index.md) | Execution |
| [Export Disk Through SAS URL](./azure/azure.exfiltration.disk-export.md) | [Azure](./azure/index.md) | Exfiltration |
| [Dump All Secrets](./kubernetes/k8s.credential-access.dump-secrets.md) | [Kubernetes](./kubernetes/index.md) | Credential Access |
| [Steal Pod Service Account Token](./kubernetes/k8s.credential-access.steal-serviceaccount-token.md) | [Kubernetes](./kubernetes/index.md) | Credential Access |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
var tf []byte

func init() {
const codeBlock = "```"
stratus.GetRegistry().RegisterAttackTechnique(&stratus.AttackTechnique{
ID: "azure.execution.vm-custom-script-extension",
FriendlyName: "Execute Command on Virtual Machine using Custom Script Extension",
Expand All @@ -38,7 +39,29 @@ Detonation:
- Configure a custom script extension for the virtual machine
`,
Detection: "Identify `Microsoft.Compute/virtualMachines/extensions/write` events in Azure Activity logs",
Detection: `
Identify Azure events of type <code>Microsoft.Compute/virtualMachines/extensions/write</code>. Sample below (redacted for clarity).
` + codeBlock + `json hl_lines="7"
{
"duration": 0,
"resourceId": "/SUBSCRIPTIONS/<your-subscription-id>/RESOURCEGROUPS/RG-HAT6H48Q/PROVIDERS/MICROSOFT.COMPUTE/VIRTUALMACHINES/VM-HAT6H48Q/EXTENSIONS/CUSTOMSCRIPTEXTENSION-STRATUS-EXAMPLE",
"evt": {
"category": "Administrative",
"outcome": "Start",
"name": "MICROSOFT.COMPUTE/VIRTUALMACHINES/EXTENSIONS/WRITE"
},
"resource_name": "customscriptextension-stratus-example",
"time": "2022-06-18T19:57:27.8617215Z",
"properties": {
"hierarchy": "ecc2b97b-844b-414e-8123-b925dddf87ed/<your-subscription-id>",
"message": "Microsoft.Compute/virtualMachines/extensions/write",
"eventCategory": "Administrative",
"entity": "/subscriptions/<your-subscription-id>/resourceGroups/rg-hat6h48q/providers/Microsoft.Compute/virtualMachines/vm-hat6h48q/extensions/CustomScriptExtension-Stratus-Example"
},
}
` + codeBlock + `
`,
Platform: stratus.Azure,
IsSlow: true,
IsIdempotent: false,
Expand All @@ -49,10 +72,9 @@ Detonation:
})
}

const ExtensionName = "CustomScriptExtension-Stratus-Example"
const ExtensionName = "CustomScriptExtension-StratusRedTeam-Example"

func detonate(params map[string]string) error {
vmObjectId := params["vm_instance_object_id"]
vmName := params["vm_name"]
resourceGroup := params["resource_group_name"]

Expand All @@ -63,10 +85,11 @@ func detonate(params map[string]string) error {

client, err := armcompute.NewVirtualMachineExtensionsClient(subscriptionID, cred, clientOptions)
if err != nil {
return errors.New("failed to create client: " + err.Error())
return errors.New("failed to create VM extensions client: " + err.Error())
}

log.Println("Configuring Custom Script Extension for VM instance " + vmObjectId)
log.Println("Configuring Custom Script Extension for VM instance " + vmName)
log.Println("This will cause a command to be run as SYSTEM on the machine")

vmExtension := armcompute.VirtualMachineExtension{
Location: to.Ptr("West US"),
Expand Down Expand Up @@ -95,27 +118,20 @@ func detonate(params map[string]string) error {
return errors.New("unable to create virtual machine extension: " + err.Error())
}

log.Println("Waiting for Custom Script Extension to be installed on the VM")
ctxWithTimeout, done := context.WithTimeout(context.Background(), 60*3*time.Second)
defer done()
_, err = poller.PollUntilDone(ctxWithTimeout, &runtime.PollUntilDoneOptions{Frequency: 2 * time.Second})
if err != nil {
return errors.New("unable to retrieve the output of the command ran on the virtual machine: " + err.Error())
}
log.Println("Extension created, the command was executed as SYSTEM")

/*ctxWithTimeout, done = context.WithTimeout(context.Background(), 60*3*time.Second)
defer done()
client2, _ := armcompute.NewVirtualMachinesClient(subscriptionID, cred, clientOptions)
const tpe = armcompute.InstanceViewTypes()
result, _ := client2.Get(ctxWithTimeout, resourceGroup, vmName, &armcompute.VirtualMachinesClientGetOptions{Expand: &tpe})
fmt.Println(result.VirtualMachine.Resources[0].Properties.InstanceView.Substatuses[0].Message)
return nil*/
// TODO enhancement: figure out how to retrieve the output of the executed commabd to ensure it was executed

return nil
}

func revert(params map[string]string) error {
vmObjectId := params["vm_instance_object_id"]
vmName := params["vm_name"]
resourceGroup := params["resource_group_name"]

Expand All @@ -129,7 +145,7 @@ func revert(params map[string]string) error {
log.Fatalf("failed to create client: %v", err)
}

log.Println("Reverting Custom Script Extension for VM instance " + vmObjectId)
log.Println("Reverting Custom Script Extension for VM instance " + vmName)

poller, err := client.BeginDelete(ctx,
resourceGroup,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,6 @@ output "resource_group_name" {
value = azurerm_resource_group.lab_environment.name
}

output "vm_instance_object_id" {
value = azurerm_windows_virtual_machine.lab_windows_vm.id
}

output "vm_name" {
value = azurerm_windows_virtual_machine.lab_windows_vm.name
}
Expand Down

0 comments on commit 80a318a

Please sign in to comment.