Defender IOC by abuse.ch

Hello wonderful security minds out there, let’s talk about indicators of compromise (IOC). One way to defend against threat actors is through “indicators of compromise” (IOC) or “tactics, techniques, and procedures” (TTP). The word “or” is out of place here. Both have their strengths and can only be used to their full potential when used together.

But what exactly are they? Data such as hash values, IP addresses, or certificates from reverse engineering a malware package are IOC’s. This means that after a malware analysis, an IP address of the C2 is known, and if some clients in your environment are communicating to this IP, there is a possible infection. In contrast, TTP’s analyze the behavior of an infection, for example, a certain group always uses RDP as an initial attack point, then exploits the system using a certain technique, and always proceeds in the same way.

A very recognized and in my opinion genious supplier of such IOCs is abuse.ch. Without getting into raptures now, really, check out the project, awesome! Enough praise, let’s see how we can use the data provided by abuse.ch to feed our MS Defender. By default, MS Defender offers the option to add your own indicators in addition to the ones provided by Microsoft. Today, we focus on three platforms from abuse.ch. On the one hand “Feodo Tracker” which tracks C2 infrastructure IPs, on the other hand “URLhaus” which provides malware distribution sites and “SSL Blacklist” which provides malicious SSL certificates.

But we don’t want to manually enter this data into our Defender Portal, because it has a short lifetime and that would be a daily task. So we do it with good old PowerShell. But first, we need an Azure Application to get a token from so we can write the data to Defender via the API. This application must have the following permissions.

Wonderful, let’s go and get a token now.

# define variables
    $tenant_id = '[your tenant id]'
    $app_id ="[your app id]"
    $app_sec ="[your app secret]"
    $ioc_exp = Get-Date -Format "o" -Date (Get-Date).ToUniversalTime().AddHours(23).AddMinutes(57)
# get token
    $jwt_aud = 'https://api.securitycenter.microsoft.com'
    $jwt_iss = "https://login.microsoftonline.com/$tenant_id/oauth2/token"
    $api_body = @{
        resource = "$jwt_aud"
        client_id = "$app_id"
        client_secret = "$app_sec"
        grant_type = 'client_credentials'
    }
    $api_data = Invoke-RestMethod -Method POST-Uri $jwt_iss -Body $api_body -ErrorAction Stop
    $jwt = $api_data.access_token
    $api_header = @{
        'Authorization' = 'Bearer ' + $jwt
        'Content-Type' = 'application/json'
    }

Next, we need to get the desired data from abuse.ch, this can be done as follows.

# get abuse.ch data
    $abuse_feodo  = Invoke-WebRequest -UseBasicParsing -Uri "https://feodotracker.abuse.ch/downloads/ipblocklist_recommended.txt"
    $abuse_feodo = $abuse_feodo.Content -split "`r`n" | Select-String -NotMatch -Pattern "^#"
    $abuse_urlhaus = Invoke-WebRequest -UseBasicParsing -Uri "https://urlhaus.abuse.ch/downloads/text_online/"
    $abuse_urlhaus = $abuse_urlhaus.Content -split "`r`n" | Select-String -NotMatch -Pattern "^#"
    $abuse_ssl  = Invoke-WebRequest -UseBasicParsing -Uri "https://sslbl.abuse.ch/blacklist/sslblacklist.csv"
    $abuse_ssl = $abuse_ssl.content -split "`r`n" | Select-String -NotMatch -Pattern "^#"

Now we have everything we need to populate the Defender indicators. Let’s start with the IP list based on the Feodo Tracker data. As you can see, the maximum we can send per payload is 500 records, so this is done in multiple requests if needed.

# update ip block list
    cls
    Write-Host("[+] updating ip block list") -ForegroundColor Green
    $payload = @()
    $ioc_title = "C2 communication detected"
    $ioc_desc = "Connection to C2 server based on Feodo Tracker blocklist"
    foreach ($ip in $abuse_feodo) {
        $data = [PSCustomObject]@{
            'IndicatorType' = "IpAddress"
            'IndicatorValue' = $ip
            'ExpirationTime' = $ioc_exp
            'Action' = 'Block'
            'Severity' = 'High'
            'Title' = $ioc_title
            'Description' = $ioc_desc
            'RecommendedActions' = 'ip: ' + $ip
            'GenerateAlert' = 'true'
        }
        $payload += $data
        $api_url = "https://api.securitycenter.microsoft.com/api/indicators/import"
        if ( $payload.count -eq 498 ) {
            $ioc = @{ 'Indicators' = $payload } | ConvertTo-Json
            $api_req = Invoke-RestMethod -Method POST -Uri $api_url -Headers $api_header -Body $ioc 
            $payload = @()        
        }     
    }  
    $ioc = @{ 'Indicators' = $payload } | ConvertTo-Json
    $api_req = Invoke-RestMethod -Method POST -Uri $api_url -Headers $api_header -Body $ioc  
    # prevent (429) Too Many Requests
        Start-Sleep 15

We’re having a good run! so let’s get right to the URL blacklist.

# update url block list
    Write-Host("[+] updating url block list") -ForegroundColor Green
    $payload = @()
    $ioc_title = "C2 communication detected"
    $ioc_desc = "Connection to C2 server based on URLhaus blocklist"
    foreach ($url in $abuse_urlhaus) {
        $data = [PSCustomObject]@{
            'IndicatorType' = "Url"
            'IndicatorValue' = $url
            'ExpirationTime' = $expire
            'Action' = 'Block'
            'Severity' = 'High'
            'Title' = $ioc_title
            'Description' = $ioc_desc
            'RecommendedActions' = 'url: ' + $url
            'GenerateAlert' = 'true'
        }
        $payload += $data
        $api_url = "https://api.securitycenter.microsoft.com/api/indicators/import"
        if ( $payload.count -eq 498 ) {
            $ioc = @{ 'Indicators' = $payload } | ConvertTo-Json
            $api_req = Invoke-RestMethod -Method POST -Uri $api_url -Headers $api_header -Body $ioc 
            $payload = @()        
        }     
    }
    $ioc = @{ 'Indicators' = $payload } | ConvertTo-Json
    $api_req = Invoke-RestMethod -Method POST -Uri $api_url -Headers $api_header -Body $ioc 
    # prevent (429) Too Many Requests
        Start-Sleep 15

We have already achieved a lot and the last thing we are doing now is the certificate blacklist.

# update cert block list
    Write-Host("[+] updating cert block list") -ForegroundColor Green
    $payload = @()
    $ioc_title = "Malicious certificate detected"
    $ioc_desc = "certificate based on SSL Cert Blacklist detected"
    foreach ($cert in $abuse_ssl) {
        $thumbprint = ($cert -split ",")[1] 
        $data = [PSCustomObject]@{
            'IndicatorType' = "CertificateThumbprint"
            'IndicatorValue' = $thumbprint
            'ExpirationTime' = $expire
            'Action' = 'Block'
            'Severity' = 'High'
            'Title' = $ioc_title
            'Description' = $ioc_desc
            'RecommendedActions' = 'cert: ' + $thumbprint
            'GenerateAlert' = 'true'
        }
        $payload += $data
        $api_url = "https://api.securitycenter.microsoft.com/api/indicators/import"
        if ( $payload.count -eq 498 ) {
            $ioc = @{ 'Indicators' = $payload } | ConvertTo-Json
            $api_req = Invoke-RestMethod -Method POST -Uri $api_url -Headers $api_header -Body $ioc 
            $payload = @()     
        }   
    }  
    $ioc = @{ 'Indicators' = $payload } | ConvertTo-Json
    $api_req = Invoke-RestMethod -Method POST -Uri $api_url -Headers $api_header -Body $ioc 

Now we have all the data filled in, but be careful, they are only active for 23 hours and 57 minutes. I recommend setting up this script as a scheduled task so that the IOCs are always rewritten. You can find the entries in the security portal “https://security.microsoft.com/” under “Settings / Endpoints / Indicators“.

If a client communicates with one of the specified IPs or URLs, the Defender will raise a high level alert and also block the traffic. So we can feel a bit safer again ๐Ÿ™‚

Thatโ€™s it so far, stay tuned and see you soon!

** midjourney string โ€œcyber mastermind defend against threat actorsโ€œ