Sandro Reiter

vCard und IT-Blog

Exchange Online: Domain-Spoofing mit DKIM erschweren

Exchange Online bietet im Vergleich zu seinem OnPremises-Gegenstück die Möglichkeit, seine akzeptierten Domänen neben einem SPF-Record auch mittels DKIM (DomainKeys Identified Mail) zu schützen.
Dadurch wird es Angreifern erschwert Phishing- oder Spam-Mails im Namen von Domains (und damit Unternehmen) zu versenden, welche diesen nicht gehören.

DKIM ist eine Erweiterung, die beim Versenden einer E-Mail von einem autorisierten Absender, in diesem Fall aus Exchange Online (Microsoft 365), der Mail ein spezielles Attribut im Mail-Header beifügt.

Das Verfahren basiert auf asymmetrischer Verschlüsselung (Public- und Private-Key). Der sendende Mail-Server signiert die Mail mit einem Hash-Wert (generiert durch den privaten Schlüssel) und die empfangende Gegenstelle (Empfänger-Server) prüft mittels des zugehörigen frei verfügbaren Public-Keys den Hash-Wert im Header ab.

Stimmt der Hash-Wert im Header mit dem durch den Empfänger-Server generierten Hash-Werts, welcher anhand des Public-Keys generiert wurde, überein, wird die E-Mail in der Regel zugestellt, da der Absender als valide gilt.

Stimmen die Werte nicht überein, liegt es an der Konfiguration des empfangenden Mail-Systems was mit der Mail passiert – zum Beispiel verwerfen, zur Prüfung in Quarantäne, in den Spam-Ordner des Benutzers oder zurückweisen der Mail an den Absender.

 

Um DKIM in Exchange Online zu aktivieren, sind folgende Schritte nötig:

1. Setzen der nötigen CNAME-Einträge im öffentlichen DNS-Verzeichnis
2. Erzeugen der DKIM-Keys in Exchange Online
3. Aktivieren von DKIM in Exchange Online

 

Im DNS müssen CNAME Einträge gemäß der folgenden Syntax angelegt werden:

Hostname: selector1._domainkey
Ziel: selector1-domain-tld._domainkey.tenant.onmicrosoft.com
TTL: 3600

Hostname: selector2._domainkey
Ziel: selector2-domain-tld._domainkey.tenant.onmicrosoft.com
TTL: 3600

Mit Werten befüllt, könnte es dann so aussehen:

Hostname: selector1._domainkey
Ziel: selector1-meinefirma-de._domainkey.meinefirma.onmicrosoft.com
TTL: 3600

Hostname: selector2._domainkey
Ziel: selector2-meinefirma-de._domainkey.meinefirma.onmicrosoft.com
TTL: 3600

 

Ein Hinweis, der die Erstellung der Einträge erleichtert ist, das die Punkte der Domain im Ziel-Wert für den CNAME immer durch Bindestriche ersetzt werden.
Aus der Domain meinefirma.de wird im CNAME Eintrag also meinefirma-de.
Genauso auch für Subdomains: Aus mail.meinefirma.de wird mail-meinefirma-de.


Sind die DNS Einträge gesetzt und veröffentlicht, muss im Exchange Online nun noch die DKIM-Konfiguration angelegt werden.

Dazu wird das ExchangeOnlineManagement PowerShell-Modul benötigt.

Mit den folgenden PowerShell-Cmdlets wird DKIM letztendlich aktiviert:

#sign in to Exchange Online
Connect-ExchangeOnline -ShowBanner:$false

#create and enable DKIM config with more secure 2048 bit encryption keys
New-DkimSigningConfig -DomainName meinefirma.de -KeySize 2048 -Enabled $true

#remove active PowerShell session
Disconnect-ExchangeOnline

Anschließend ist DKIM für diese Domain aktiv und alle gesendeten Mails werden mit diesem Mechanismus zusätzlich abgesichert.

Zu erkennen ist es zum Beispiel im Mail-Header anhand folgender Werte:

dkim=pass (signature was verified) header.d=senderdomain.com; arc=pass (0 oda=1
ltdi=1 spf=[1,1,smtp.mailfrom=senderdomain.com]
dkim=[1,1,header.d=senderdomain.com] dmarc=[1,1,header.from=senderdomain.com])

...

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=senderdomain.com;
s=selector2;
h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
bh=/O9b+/4FCGiuPLbNWFW7dhg8/koNv10LLB+vHg4Zw1I=;
b=PPomU/kCR74JOUiAzKryl5BIag6ceftDWB2KTIl/NW6X1F9TKWT9LWVduM4fe8fWgDR4RzxDjUHMeVzmTK948pS8OdAcob+aV1XfRp4gqV6HrtgoltEG9ZHnR/hgKGR04MkHCZ9RWjPafMDe0hefDPI1Fd/IUXmHam0UxS+8i3g=

 

DKIM kann für mehrere Domains bzw. alle Domains die im Exchange Online zugeordnet sind aktiviert werden, die o.g. Schritte müssen dabei für jede Domain wiederholt werden.

Azure: Hub-Spoke in Tenant-übergreifenden VNet-Peerings

In meinem Blogpost zum Thema Tenant-übergreifendes VNet-Peering habe ich aufgezeigt, wie man zwei Azure Tenants mit einem VNet Peering verbinden kann. Zum Zeitpunkt, als ich den Artikel verfasst habe, gab es noch die Einschränkung, das die zu verbindenden VNets in den zwei Tenants in der selben Azure Region laufen müssen.

 

Ich habe mir diese Woche die Thematik nochmal auf den Tisch geholt und festgestellt: Die Limitierung wurde aufgehoben.

Dadurch ist es nun möglich Hub-Spoke-Topologien über mehrere Azure Tenants und mehrere Azure Regionen aufzubauen.

Die Maus-Klick Mandelas schauen dabei aber in die Röhre, denn die Funktionen für Hub-Spoke “UseRemoteGateways” & “AllowGatewayTransit” können (derzeit) nicht über das Azure Portal, sondern nur per PowerShell oder CLI gesetzt werden.

 

Ein bereits bestehendes Peering (siehe vorheriger Blogeintrag) vorausgesetzt, wird Hub-Spoke mit folgendem Skript aktiviert:

#declare variables
$subscriptionTenantA = "subscriptionID"
$vNetTenantA = "vNet"
$vnetResourceGroupTenantA = "vNetResourceGroup"
$subscriptionTenantB = "subscriptionID"
$vNetTenantB = "vNet"
$vnetResourceGroupTenantB = "vNetResourceGroup"

#connect to AzureRM
Connect-AzAccount

#select subscription in Tenant A
Select-AzSubscription -Subscription $subscriptionTenantA

#Activate GatewayTransit on Hub network
$peerSiteA = Get-AzVirtualNetworkPeering -ResourceGroupName $vnetResourceGroupTenantA -VirtualNetworkName $vNetTenantA
$peerSiteA.AllowGatewayTransit = $true
Set-AzVirtualNetworkPeering -VirtualNetworkPeering $peerSiteA

#select subscription in Tenant B
Select-AzureRmSubscription -Subscription $subscriptionTenantB

#use Remote Gateways on Spoke network
$peerSiteB = Get-AzVirtualNetworkPeering -ResourceGroupName $vnetResourceGroupTenantB -VirtualNetworkName $vNetTenantB
$peerSiteB.UseRemoteGateways = $true
Set-AzVirtualNetworkPeering -VirtualNetworkPeering $peerSiteB

Anschließend sind Ressourcen, bspw. von OnPremises, in der Lage über das Hub-Netzwerk mit Ressourcen in den jeweiligen Spoke-Netzwerken zu kommunizieren.

Teams: E-Mail-Kommunikation in Kanälen anzeigen

Microsoft Teams ist in seinem Segment als “eierlegende Wollmilchsau” wohl einer der größten und gelungensten Würfe der IT-Branche in den letzten Jahren!

MS Teams hat sich so stark in meinen Arbeitsalltag integriert, das ich es nicht mehr missen möchte und vermutlich auch gar nicht kann. Ich bin bereits in Q4 2018 den Weg gegangen und habe mich als ersten User in unserem Tenant auf “teams-only”-Benutzung umgestellt.

Mein Skype for Business Client sagt mir beim Start nur noch freundlich:
Geh doch bitte zu Teams 😉
Meine letzte verbliebene S4B Funktionalität: An S4B-Meetings teilnehmen.

 

Teams auf Office 365 Gruppen aufzusetzen ist eine gelungene Entscheidung, mit einem großen Nachteil: Gruppenunterhaltungen – also E-Mails – tauchen nicht im jeweiligen Team auf. Ich muss zur Diskussion einer E-Mail diese immer erst an den Kanal weiterleiten.

 

Natürlich gibt es aber einen Workaround:

Jeder Teams-Kanal hat eine eigene E-Mail-Adresse welche auf @emea.teams.ms endet. Dieses Feature machen wir uns zu Nutze.

Als erstes empfiehlt es sich einen eigenen Kanal, beispielsweise namens “E-Mails”, im Team anzulegen.

Anschließend kann über das Kanal-Kontextmenü (•••) mit einem Klick auf “E-Mail-Adresse abrufen” die Kanal-E-Mail-Adresse ausgelesen werden.

Mit dieser E-Mail-Adresse wird im Azure AD ein Gast-Nutzer angelegt.

Der angelegte Gastnutzer muss anschließend nur noch als Mitglied zur Office 365 Gruppe hinzugefügt werden. Das erledigt am besten die PowerShell um zu garantieren das der Gastnutzer auch ein Abonnent der Gruppe wird:

#add guest user as member to o365 group
Add-UnifiedGroupLinks -LinkType Members -Identity "myO365Group" -Links "myTeamsChannelGuestUser"
#add guest user as subscriber to o365 group to receive emails
Add-UnifiedGroupLinks -LinkType Subscribers -Identity "myO365Group" -Links "myTeamsChannelGuestUser"

Ab diesem Moment werden E-Mails an die O365 Gruppe auch in dem jeweiligen Teams-Kanal zugestellt.

Azure: Tenant-übergreifendes VNet-Peering

Peerings zwischen virtuellen Netzwerken in Azure sind eine tolle Sache: Einfach zu konfigurieren, schnell bereitgestellt und die Performance ist ebenfalls klasse!

Zum Verbinden von virtuellen Netzwerken aus verschiedenen Azure Active Directory Tenants, wie es beispielsweise in Unternehmensgruppen der Fall ist, mussten bis vor Kurzem noch VPN-Gateways bereitgestellt werden.

Jetzt ist es möglich VNet-Peerings Tenant-übergreifend zu erstellen, derzeit allerdings nur über Azure CLI, PowerShell oder als ARM-Template.

Ich zeige Euch die PowerShell Variante.

Als Voraussetzung benötigt Ihr einen Azure AD-Benutzer, welcher sowohl in Tenant A als auch Tenant B (dann als Gast) die Berechtigung “Network Contributor” auf das jeweilige virtuelle Netzwerk hat, um das VNet “auf der anderen Seite” auslesen und das Peering erstellen zu können.

 

Ist das gegeben, kann es losgehen. Folgendes Skript erledigt alles nötige für Euch, wenn Ihr die Variablen korrekt befüllt:

#declare variables
$subscriptionTenantA = "subscriptionID"
$vNetTenantA = "vNet"
$vnetResourceGroupTenantA = "vNetResourceGroup"
$peerAtoBname = "TenantA-TenantB-Peer01"
$subscriptionTenantB = "subscriptionID"
$vNetTenantB = "vNet"
$vnetResourceGroupTenantB = "vNetResourceGroup"
$peerBtoAname = "TenantB-TenantA-Peer01"

#connect to AzureRM
Connect-AzAccount

#select subscription in Tenant A
Select-AzSubscription -Subscription $subscriptionTenantA

#peer vnet in tenant A to vnet in tenant B
$vNet = Get-AzVirtualNetwork -Name $vNetTenantA -ResourceGroupName $vnetResourceGroupTenantA
Add-AzVirtualNetworkPeering -Name $peerAtoBname -VirtualNetwork $vNet -RemoteVirtualNetworkId "/subscriptions/$subscriptionTenantB/resourceGroups/$vnetResourceGroupTenantB/providers/Microsoft.Network/virtualNetworks/$vNetTenantB"

#select subscription in Tenant B
Select-AzSubscription -Subscription $subscriptionTenantB

#peer vnet in tenant B to vnet in tenant A
$vNet = Get-AzVirtualNetwork -Name $vNetTenantB -ResourceGroupName $vnetResourceGroupTenantB
Add-AzVirtualNetworkPeering -Name $peerBtoAname -VirtualNetwork $vNet -RemoteVirtualNetworkId "/subscriptions/$subscriptionTenantA/resourceGroups/$vnetResourceGroupTenantA/providers/Microsoft.Network/virtualNetworks/$vNetTenantA"

Läuft, oder? 😉

 

Der Vollständigkeit halber noch folgender Hinweis zum Schluss:

Die Optionen “Allow gateway transit” und “Use remote gateway” stehen nur zur Verfügung, wenn sich die virtuellen Netzwerke in der selben Azure Region befinden. Bei einer Verbindung bspw. zwischen Westeuropa und Frankreich-Mitte funktioniert das derzeit leider noch nicht.

Azure AD: UPN eines Hybrid-Users ändern

Als wir vor Kurzem einen neuen Kollegen eingestellt haben, wünschte dieser sich einen kürzeren Anmeldenamen (UPN) für Office 365 und Co.
Da ich natürlich vorbildlich bereits vor seinem Dienstantritt das Active Directory-Konto erstellt habe, änderte ich einfach den UPN am AD-Objekt und auch die neue Adresse im ProxyAdresses-Attribut wurde veröffentlicht und als primär festgelegt.

Als nach mehrfachen automatischen AAD Connect Synchronisationen der kosmetische Eingriff noch nicht geglückt war, habe ich eine manuelle Synchronisation angestoßen…

Start-ADSyncSyncCycle -PolicyType Delta

… allerdings ebenfalls ohne Erfolg.

 

Ich musste ein wenig in meinem Gedächtnis kramen – denn genau diese Änderung habe ich bereits an meinem eigenen Benutzerkonto durchgeführt – Déjà-vu! Mir fiel wieder ein, was ich schon mal vergessen habe.

Es ist natürlich richtig und wichtig den UPN und die neue Mail-Adresse im OnPremises AD zu ändern. Wenn das Konto aber bereits synchronisiert ist und in Azure AD angelegt, muss der UPN auch nochmal auf Azure AD-Seite geändert werden. Das gelingt ganz einfach wie folgt:

#connect to Azure AD tenant
Connect-AzureAD

#change UPN to default tenant-domain
Set-AzureADUser -ObjectId user@contoso.com -UserPrincipalName user@contoso.onmicrosoft.com

#set the UPN like the UPN in OnPrem AD
Set-AzureADUser -ObjectId user@contoso.onmicrosoft.com -UserPrincipalName mrright@contoso.com

 

Nachdem das nun erledigt ist, gilt der neue UPN in beiden IDPs – sowohl im Active Directory als auch Azure AD.

 

Famous last words: Wenn der UPN geändert wird, ändert sich auch die SIP-Adresse des jeweiligen Benutzers. Diese Adresse wird u.a. im Skype for Business-Verzeichnisdienst verwendet. Das wiederum hat die Folge, das bereits bestehende Kontakte den Benutzer mit neuem UPN erneut zur Kontaktliste hinzufügen müssen.

Azure Automation: Anfordern eines Ad-Hoc SAS Tokens

Wer mit Azure Storage arbeitet, kommt über kurz oder lang nicht daran vorbei die Verarbeitung von Dateien zu automatisieren. Was über die Web-UI so einfach geht, ist via PowerShell nicht ganz so trivial.

In einem Container mit dem AccessLevel “private” wird ein SAS Token benötigt um auf die Dateien zuzugreifen und mit diesen zu arbeiten.

Wie genau dieser Token in einem Azure Automation PowerShell RunBook angefordert werden kann, zeigt das folgende Skript:

#define parameter
Param(
    [Parameter(Mandatory=$True)]
    [string]$AzureAutomationAccount,

    [Parameter(Mandatory=$True)]
    [string]$FileWebUrl,

    [Parameter(Mandatory=$True)]
    [string]$StorageAccountName,

    [Parameter(Mandatory=$True)]
    [string]$StorageResourceGroup,

    [Parameter(Mandatory=$True)]
    [string]$StorageContainerName,

    [Parameter(Mandatory=$True)]
    [string]$BlobName,

    [Parameter(Mandatory=$false)]
    [ValidateSet("r","rw","rcw","rwcd")] 
    [string]$AccessRights = "r",
    
    [Parameter(Mandatory=$false)]
    [int]$TokenLifeTime = 2
)

#get credentials from Azure Automation vault
$myCredential = Get-AutomationPSCredential -Name $AzureAutomationAccount

#sign in to AzureRM
Login-AzureRmAccount -Credential $myCredential

#get current utc time for sas token starttime and expiration
$TokenStartTime = Get-Date
$TokenStartTime = $TokenStartTime.ToUniversalTime()
$TokenEndTime = $TokenStartTime.AddHours($TokenLifeTime)

#get storageaccount key, set context to container and request adhoc SAS token
$StorageAccountKey = (Get-AzureRmStorageAccountKey -ResourceGroupName $StorageResourceGroup -AccountName $StorageAccountName).Value[0]
$StorageContext = New-AzureStorageContext $StorageAccountName -StorageAccountKey $StorageAccountKey
$SASKey = New-AzureStorageBlobSASToken -Protocol HttpsOnly -Container $StorageContainerName -Blob $BlobName -Context $StorageContext -Permission $AccessRights -StartTime $TokenStartTime -ExpiryTime $TokenEndTime

#join file-uri and SAS token to full download uri
$FullUri = "$FileWebUrl$SASKey"

 

Sobald das Skript in einem RunBook hinterlegt ist, können die Parameter übergeben und das Snippet im Azure Automation Kontext ausgeführt werden.

 

Das Skript verarbeitet die Datei nicht, sondern fordert nur den Token an. Die komplette URL (Blob+Token), welche am Ende als Variable ($FullUri) bereitsteht, kann für Dateioperationen, bspw. der Import des Dateiinhalts in eine Variable, verwendet werden solange der SAS-Token gültig ist.

#import csv content into variable
$content = ConvertFrom-Csv -Delimiter ";" (Invoke-WebRequest -Uri $FullUri).ToString()

Exchange Online: Auf welche Shared Mailboxes hat ein User Zugriff?

Erst kürzlich erhielt ich einen Anruf mit der Frage: “Sehe ich eigentlich irgendwo auf welche Shared Mailboxes ich Zugriff habe?”

Beunruhigende Stille machte sich auf meiner Seite der Leitung breit…

“Da muss ich nachsehen”, sagte ich und sicherte zu mich zeitnah zu melden.

Mir waren die Möglichkeiten bewusst die ein Nutzer hat um die Mitgliedschaft in O365 Gruppen und Verteilerlisten einzusehen, aber die geteilten Postfächer anzeigen auf die man selbst Zugriff hat, suchte ich vergeblich.

 

Lange Rede, kurzer Sinn: Der Kunde wartet – let’s script it!

Das nachfolgende Skript muss der Exchange-Admin ausführen, aber es geht allemal schneller als sich durch alle Shared Mailboxes zu klicken und nachzusehen wo der User berechtigt ist.

$usertosearch = "max@muster.de"
$sharedMailboxes = Get-Mailbox -RecipientTypeDetails SharedMailbox

foreach ($box in $sharedMailboxes) 
{ 
    $perms = Get-MailboxPermission -Identity $box.Alias

    foreach ($perm in $perms)
    { 
        if(
            $perm.User -like $usertosearch) 
            { 
                write-host $box.PrimarySmtpAddress 
            } 
    }
}

 

Azure: S2S-VPN und die IPSec-Policy

Wer kennt es nicht: Eingefleischte Netzwerkadmins, womöglich sogar angestellt bei einem Rechenzentrums-Dienstleister, die alles rund um die Cloud als total unsicher und sowieso überflüssig einschätzen (und in Wahrheit vermutlich nur Angst um den Ast haben, auf dem sie sitzen) meckern über alles wo Microsoft dran steht oder drin ist.

Da ist es doch ein willkommener Aufhänger, wenn eine VPN Verbindung zu Azure nicht die Anforderungen abbilden kann, welche das NOC gern hätte.

Aber falsch gedacht! Was viele nicht wissen: Es ist möglich die Site-to-Site IPSec-Richtlinie einer VPN-Verbindung mithilfe des Azure CLI und des AzureRM PowerShell-Moduls an die gewünschten Anforderungen anzupassen.

 

Um die Richtlinie zu konfigurieren, müssen wir uns zunächst in den Azure Resource Manager einloggen, das gelingt uns wie folgt:

$credentials = Get-Credential

Login-AzureRmAccount -Credential $credentials

$subscriptionId = ( Get-AzureRmSubscription | Out-GridView -Title "Select an Azure Subscription ..." -PassThru).SubscriptionId
Select-AzureRmSubscription -SubscriptionId $subscriptionId

 

Anschließend können wir mit dem nachfolgenden Skript die Parameter der IPSecPolicy festlegen und damit die VPN Verbindung zum VPN-Gateway auf “der anderen Seite” aufbauen.

$rg = "GatewayResourceGroup"

$policy = New-AzureRmIpsecPolicy -IkeEncryption AES256 -IkeIntegrity SHA1 -DhGroup DHGroup2 -IpsecEncryption AES256 -IpsecIntegrity SHA1 -PfsGroup None -SALifeTimeSeconds 27000 -SADataSizeKilobytes 1024000

$vpngw = Get-AzureRmVirtualNetworkGateway -Name "GW1"  -ResourceGroupName $rg
$localvpngw = Get-AzureRmLocalNetworkGateway  -Name "Local-GW1" -ResourceGroupName $rg

New-AzureRmVirtualNetworkGatewayConnection -Name "MyConnection" -ResourceGroupName $rg -VirtualNetworkGateway1 $vpngw -LocalNetworkGateway2 $localvpngw -Location "Azure Region" -ConnectionType IPsec -IpsecPolicies $policy -SharedKey 'PSK' -RoutingWeight 0

Welche Werte von Azure unterstützt werden, können wir unter folgendem Link in den Microsoft Docs nachlesen:

https://docs.microsoft.com/de-de/azure/vpn-gateway/vpn-gateway-ipsecikepolicy-rm-powershell

 

Um zu prüfen, ob die Einstellungen korrekt übernommen wurden, führen wir  folgendes Code-Snippet aus:

$rg = "GatewayResourceGroup"
$con = Get-AzureRmVirtualNetworkGatewayConnection -Name "MyConnection" -ResourceGroupName $rg

Write-Output $con.IpSecPolicies

 

Nach ein paar Augenblicken und korrekter Konfiguration auf beiden Seiten, steht der VPN Tunnel.