Documenting with PowerShell: Increasing the Office365 Secure Score.

So previously we’ve spoken about documenting the Office 365 Secure Score. For a great resource on this I’d suggest you check out Eliot’s blog on documenting the Secure Score here. Its a fantastic resource.

This time I’m not going to focus on documenting the Secure Score directly – But increasing it. we want to make sure that the Secure Score is as high as possible with as little user impact as possible. To do this, I’ve selected some items that increase your secure score but have next to no impact on normal usage. Of course you’ll have to check if this is true for your environment too.

The Script

The script is set up to enable the following features for all tenants in your partner portal.

  • Move mail with a high confidence spam rating to the Junk Folder (Does not increase SecureScore, but was requested to add on Slack. You can remove this item if you only want the Secure Score increase)
  • Mailbox Auditing for all users
  • Mailbox Litigation hold where possible.
  • DelegateSentitemsStyle for mailboxes
  • NDR report for journaling.
  • Set the outbound spam filter reporting e-mail address
  • Set “Do not allow users to grant consent to unmanaged applications”
  • Disable password expire on user accounts
  • Enable the self-service password reset(I’d strongly recommend to first enable multi factor authentication for all your users.

I believe I could’ve added more features but I chose to only enable the ones with no to very little user impact. Using this script you can adapt it to all your wishes. It’s also very easy to disable one of the features – Just remove the the entire block of code that you do not want to enable.

#Set the recipient for outbound spam reports and Journaling NDRs.
$SpamAndEmailRecipient = "Helpdesk@limenetworks.nl"
#######################################################################
###################  CREDENTIALS     ##################################
$ApplicationId         = 'xxxx-xxxx-xxx-xxxx-xxxx'
$ApplicationSecret     = 'TheSecretTheSecrey' | Convertto-SecureString -AsPlainText -Force
$TenantID              = 'YourTenantID'
$RefreshToken          = 'RefreshToken'
$ExchangeRefreshToken  = 'ExchangeRefreshToken'
$upn                   = 'UPN-Used-To-Generate-Tokens'
###################  END CREDENTIALS ##################################
$credential = New-Object System.Management.Automation.PSCredential($ApplicationId, $ApplicationSecret)

$aadGraphToken = New-PartnerAccessToken -ApplicationId $Applicatio nId -Credential $credential -RefreshToken $refreshToken -Scopes 'https://graph.windows.net/.default' -ServicePrincipal -Tenant $tenantID 
$graphToken = New-PartnerAccessToken -ApplicationId $ApplicationId -Credential $credential -RefreshToken $refreshToken -Scopes 'https://graph.microsoft.com/.default' -ServicePrincipal -Tenant $tenantID 

Connect-MsolService -AdGraphAccessToken $aadGraphToken.AccessToken -MsGraphAccessToken $graphToken.AccessToken
$customers = Get-MsolPartnerContract -All
foreach ($customer in $customers) {
    $token = New-PartnerAccessToken -ApplicationId 'a0c73c16-a7e3-4564-9a95-2bdf47383716'-RefreshToken $ExchangeRefreshToken -Scopes 'https://outlook.office365.com/.default' -Tenant $customer.TenantId
    $tokenValue = ConvertTo-SecureString "Bearer $($token.AccessToken)" -AsPlainText -Force
    $credential = New-Object System.Management.Automation.PSCredential($upn, $tokenValue)
    $customerId = $customer.DefaultDomainName
    $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://ps.outlook.com/powershell-liveid?DelegatedOrg=$($customerId)&BasicAuthToOAuthConversion=true" -Credential $credential -Authentication Basic -AllowRedirection
    Import-PSSession $session -AllowClobber -DisableNameChecking
    Write-Host "Starting process for client $($customer.name)" -ForegroundColor Green
    #Move mail with a high confidence spam to the Junk folder. 
    try {
        Get-HostedContentFilterPolicy -ErrorAction Stop | Set-HostedContentFilterPolicy -HighConfidenceSpamAction MoveToJmf -ErrorAction Stop 
    }
    catch {
        Write-Output "Failed to change the spam policy. $($_.Exception.Message)"
    }
    #Enable mailbox auditing for each user.
    try {
        Get-Mailbox -ResultSize Unlimited -ErrorAction Stop | Set-Mailbox -ErrorAction Stop -AuditEnabled $true -AuditOwner MailboxLogin, HardDelete, SoftDelete, Update, Move -AuditDelegate SendOnBehalf, MoveToDeletedItems, Move -AuditAdmin Copy, MessageBind 
    }
    catch {
        Write-Output "Failed to enable Mailbox auditing. $($_.Exception.Message)"
    }

    #Enable mailbox litigation hold
    try {
        Get-Mailbox -ResultSize Unlimited -ErrorAction Stop | Set-Mailbox -ErrorAction Stop -LitigationHoldEnabled $true -LitigationHoldDuration 2555 
    }
    catch {
        Write-Output "Failed to enable Mailbox Litigation hold. $($_.Exception.Message)"
    }
    #Enable DelegateSentItems.
    try {
        Get-Mailbox -ResultSize Unlimited -ErrorAction Stop | set-mailbox -ErrorAction Stop -MessageCopyForSentAsEnabled $true -MessageCopyForSendOnBehalfEnabled $true 
    }
    catch {
        Write-Output "Failed to enable DelegateSentItems style. $($_.Exception.Message)"
    }
    #Set Journaling NDR
    try {
        set-transportconfig -JournalingReportNdrTo "$SpamAndEmailRecipient" -ErrorAction Stop 
    }
    catch {
        Write-Output "Failed to set Transport Config Journaling NDR $($_.Exception.Message)"
    }
    #Set outbound spamfilter reporting
    try {
        Set-HostedOutboundSpamFilterPolicy "Default" -NotifyOutboundSpam $true -NotifyOutboundSpamRecipients $SpamAndEmailRecipient -ErrorAction Stop 
    }
    catch {
        Write-Output "Failed to set outbound spam settings $($_.Exception.Message)"
    }
    
    #Set "Do not allow users to grant consent to unmanaged applications"
    try {
        Set-MsolCompanySettings -tenantID $customer.TenantId -UsersPermissionToUserConsentToAppEnabled:$false -ErrorAction Stop 
    }
    catch {
        Write-Output "Failed to set Permissions to allow user to grant consent to unmanaged applications $($_.Exception.Message)"
    }
    #Disable password expire on accounts.
    try {
        Get-MsolUser -TenantId $customer.TenantId -ErrorAction Stop | Set-MsolUser PasswordNeverExpires $true -ErrorAction Stop 
    }
    catch {
        Write-Output "Disable password expire failed. $($_.Exception.Message)"
    }

    #Enable Self Service Password Reset
    try {
        Set-MsolCompanySettings -TenantId $customer.TenantId -SelfServePasswordResetEnabled:$true -erroraction Stop
    }
    catch {
        Write-Output "Enabling Self Service Password Reset Failed. $($_.Exception.Message)"
    }


    Write-Host "Finished process for client $($customer.name)" -ForegroundColor Green
    Remove-PSSession $session
}

and that’s it! as always, Happy PowerShelling!

Recent Articles

The return of CyberDrain CTF

CyberDrain CTF returns! (and so do I!)

It’s been since september that I actually picked up a digital pen equivalent and wrote anything down. This was due to me being busy with life but also my side projects like CIPP. I’m trying to get back into the game of scripting and blogging about these scripts. There’s still so much to automate and so little time, right? ;)

Monitoring with PowerShell: Monitoring Acronis Backups

Intro

This is a monitoring script requested via Reddit, One of the reddit r/msp users wondered how they can monitor Acronis a little bit easier. I jumped on this because it happened pretty much at the same time that I was asked to speak at the Acronis CyberSummit so it kinda made sense to script this so I have something to demonstrate at my session there.

Monitoring with PowerShell: Monitoring VSS Snapshots

Intro

Wow! It’s been a while since I’ve blogged. I’ve just been so swamped with CIPP that I’ve just let the blogging go entirely. It’s a shame because I think out of all my hobbies it’s one I enjoy the most. It’s always nice helping others achieve their scripting target. I even got a couple of LinkedIn questions asking if I was done with blogging but I’m not. Writing always gives me some more piece of mind so I’ll try to catch up again. I know I’ve said that before but this time I’ll follow through. I’m sitting down right now and scheduling the release of 5 blogs in one go. No more whining and no more waiting.