office 365
268 TopicsThreat Hunting with PowerShell - Security even with a small budget - there is no excuse!
Dear Threat Hunter, Lack of IT security is often excused by little or no available money. In my view, this is a very poor excuse. In this article I will try to give you a jump start on how to investigate threats with PowerShell. Is this a comprehensive and conclusive list of how you can find or detect threats/threats? NO, absolutely not. But it is meant to provide you with the support that you need to move forward on your own. Let's talk about the "general conditions": 1. If you use the PowerShell scripts I show/explain in this article, this is entirely your responsibility. I use the scripts in different situations, they are not dangerous, but you should already know what you are doing. 2. Written permission! If you are not sure if you are allowed to do an investigation, organize a written permission from your supervisor. 3. In the different scripts I sometimes (for this article deliberately) use standard search words like "malware", "malicious", "hacker" etc. Such search patterns/search words need to be customized, of course. These simply serve as an example. 4. The last part of the article examines some Microsoft cloud services. I am absolutely aware that there are a huge number of tools for hunting in the Microsoft cloud services. It starts with Azure Sentinel and continues with Cloud App Security. Since the focus is on a small budget, I'll leave those tools on the side. Introduction: So first, why should you use PowerShell for threat hunting? PowerShell is a useful threat hunting tool because it is a powerful scripting language and a platform for automating tools and accessing data across any Windows environment. It allows you to quickly gather information from various sources such as event logs, registries, files, and processes. Additionally, it can also be easily integrated with other tools and technologies making it a flexible and efficient tool for threat hunting. Some common use cases for PowerShell in the threat hunting environment include automated collection of log data, identification of unusual behavior anomalies in the system, the discovery of malware or malicious activity by known signatures or patterns or behaviors. These are just a few examples of how PowerShell can be used in a threat hunting capacity. Its versatility and ability to access and manipulate data from across the Windows environment make it a very valuable tool for any security professional. Threat Hunting in PowerShell - Use Cases: All right. So now that we understand where PowerShell can benefit an organization from a threat hunting perspective. Let's take a deeper look at some of the actual use cases you might encounter on a day to day basis, first being identify malicious processor files. So specifically, you can conduct raw file analysis to sift through different data shares to look for particular files in question whether that be a signature or even an extension of a certain file being able to quickly search and triage through files is an extreme benefit of using PowerShell for threat hunting. But how exactly do we start, what can we use as a guide? For example, the MITRE ATT&CK Framework. Here are a few examples: Indicator Removal: Clear Windows Event Logs https://attack.mitre.org/techniques/T1070/001/ Event Triggered Execution: Installer Packages https://attack.mitre.org/techniques/T1546/016/ Hide Artifacts: NTFS File Attributes https://attack.mitre.org/techniques/T1564/004/ Command and Scripting Interpreter: PowerShell https://attack.mitre.org/techniques/T1059/001/ Command and Scripting Interpreter: Windows Command Shell https://attack.mitre.org/techniques/T1059/003/ Event Triggered Execution: Windows Management Instrumentation Event Subscription https://attack.mitre.org/techniques/T1546/003/ Credentials from Password Stores: Windows Credential Manager https://attack.mitre.org/techniques/T1555/004/ Abuse Elevation Control Mechanism: Bypass User Account Control https://attack.mitre.org/techniques/T1548/002/ The MITRE ATT@CK framework provides a comprehensive and regularly updated overview of tactics, techniques, and procedures (TTPs) used by various threat actors. We can locate these TTPs using PowerShell, here are a few examples: Indicator Removal: Clear Windows Event Logs https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Hunting_Active_Directory/06_Account_Events.ps1 Event Triggered Execution: Installer Packages https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Tactics_Techniques_Procedures_(TTPs)/08_Get-ItemProperty_Software.ps1 Hide Artifacts: NTFS File Attributes https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Tactics_Techniques_Procedures_(TTPs)/08_Get-ItemProperty_Software.ps1 Windows Installer Service is running https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Tactics_Techniques_Procedures_(TTPs)/01_WIS_is_running.ps1 Search Alternate Data Streams on NTFS File Systems https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Tactics_Techniques_Procedures_(TTPs)/02_Search_ADS_on_NTFS%20_(specific%20file).ps1 https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Tactics_Techniques_Procedures_(TTPs)/03_Search_ADS_on_NTFS_file_systems.ps1 Read the Contents of a File https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Tactics_Techniques_Procedures_(TTPs)/06_Read_the_contents_file.ps1 Locating Data Patterns within a File https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Tactics_Techniques_Procedures_(TTPs)/05_locating_data_patterns_within_file.ps1 Search for Encoding with Regex https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Tactics_Techniques_Procedures_(TTPs)/07_Search_encoding_with_regex.ps1 Search for Command and Scripting Interpreter: https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Tactics_Techniques_Procedures_(TTPs)/04_Searching_for_PIDs.ps1 Threat hunting in different environments with PowerShell: Coming examples are about collecting information in very different environments. Also here a few examples as a kind => as first starting points: Hunt for Threats in Active Directory: https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Hunting_Active_Directory/01_Resetting_Password_Unlocking_Accounts.ps1 https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Hunting_Active_Directory/02_Search_stale_accounts.ps1 https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Hunting_Active_Directory/03_Users_without_Manager.ps1 https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Hunting_Active_Directory/04_Password_Expiration.ps1 https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Hunting_Active_Directory/05_Group_Membership_Report.ps1 https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Hunting_Active_Directory/06_Account_Events.ps1 https://github.com/tomwechsler/Active_Directory_Advanced_Threat_Hunting/blob/main/PowerShell/Tracking_the_Source_of_Account_Lock_Outs_and_Bad_Passwords.ps1 https://github.com/tomwechsler/Active_Directory_Advanced_Threat_Hunting/blob/main/PowerShell/Finding_Unused_Group_Policy_Objects.ps1 Some of the scripts are structured in such a way that they must be executed block by block/line by line. So do not execute the whole script at once. Pay attention to the different information that is collected. With some investigations in the Active Directory accounts can be indicated like "guest" or "krbtgt", there must be clear of course how this information is to be estimated. Depending on how and what information is searched. Hunt for Threats in Exchange Online: https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Hunting_Exchange_Online/Exchange_Mailbox_LastLogin.ps1 Find mailboxes with the last login. Hunt for Threats in Azure: https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Hunting_Azure/Collect_vms_subscription.ps1 We search Azure for all virtual machines in a subscription. https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Hunting_Azure/02_Graph_Create_Time_Last_Password.ps1 When was the last password change and when were the accounts created? Hunt for Threats in SharePoint: https://github.com/tomwechsler/Threat_Hunting_with_PowerShell/blob/main/Hunting_SharePoint_Online/SharePoint_Online_specific_files.ps1 With this script we search for files with the extension .ps1 in a SharePoint Online page. Summary: Is this the best tactic to hunt for threats? No! There are many different tactics/techniques to search for threats. First of all, there are a huge number of different tools that can be used, for example SIEM/SOAR (Security Information and Event Management/Security Orchestration, Automation and Response). These tools are really great, sometimes cost a lot and often it takes a lot of knowledge to use such tools. But what is the use of such tools if the information generated by these tools cannot be understood properly, not very much. For this reason, I have tried in this article with simple tools to generate information that hopefully can be interpreted. Is finished here at this point. NO, the journey continues. The examples in this article are neither exhaustive nor complete, but they should give you a starting point. I hope you can build on this foundation. I hope that this information is helpful to you and that you have received a good "little" foundation. But I still hope that this information is helpful for you. Thank you for taking the time to read the article. Happy Hunting, Tom Wechsler P.S. All scripts (#PowerShell, Azure CLI, #Terraform, #ARM) that I use can be found on github! https://github.com/tomwechsler62KViews5likes0CommentsGenerate vCard for each user in Exchange online and attach to user's mail.
We are looking best method to create vCard for each user in Exchange online and attach vCard in user's outlook for outgoing email. Is there any script or tool to programmatically create a vCard, that can generate .vcf files with the desired contact information for each user and integrate to Exchange online to apply to corresponding user.3Views0likes0CommentsMicrosoft Graph Sign in Log Script
Hi all, I'm trying to create a script that will check sign ins based on the location. How ever the location always appears as 'Microsoft.Graph.PowerShell.Models.MicrosoftGraphSignInLocation'. I am able to see the location if I select the property 'location' by itself and expand the property, but then that only show's a list of the locations. If I add other properties, it either doesn't work or it displays like this: I tried exporting as a csv and the location column values showed up as 'Microsoft.Graph.PowerShell.Models.MicrosoftGraphSignInLocation'. This is what I have currently: Get-MgAuditLogSignIn -Filter "location/countryOrRegion eq 'AU'" -Top 10 | format-list And if I try selecting properties (I would add more properties later, this is just an example: $properties = 'location, userprincipalname' Get-MgAuditLogSignIn -All -Filter "location/countryOrRegion eq 'AU'" -Top 10 -Property $properties | Select -ExpandProperty $properties Has anyone tried something similar?17Views0likes0CommentsTrying to fetch mail info using Microsoft Graph
# Replace these with your app registration details $tenantId = "" $clientSecret = "" $clientId = "" # OAuth 2.0 token endpoint for your tenant $tokenUrl = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" # Microsoft Graph API base URL $graphApiUrl = "https://graph.microsoft.com/v1.0" # The resource scope we are requesting (Mail.Read, MailboxSettings.Read, User.ReadBasic.All) $scope = "https://graph.microsoft.com/.default" # Request an OAuth 2.0 token from Azure AD using the client credentials flow $tokenResponse = Invoke-RestMethod -Method Post -Uri $tokenUrl -ContentType "application/x-www-form-urlencoded" -Body @{ client_id = $clientId client_secret = $clientSecret scope = $scope grant_type = "client_credentials" } # Extract the access token from the response $accessToken = $tokenResponse.access_token # Headers for authenticated requests to Microsoft Graph $headers = @{ Authorization = "Bearer $accessToken" } # Function to fetch paginated results from Microsoft Graph API function Get-PaginatedData { param ( [Parameter(Mandatory = $true)] [string]$initialUrl ) $results = @() $nextLink = $initialUrl while ($nextLink) { try { $response = Invoke-RestMethod -Uri $nextLink -Headers $headers $results += $response.value # Check if there is more data to fetch if ($response.'@odata.nextLink') { $nextLink = $response.'@odata.nextLink' } else { $nextLink = $null } } catch { # Capture and display detailed error information Write-Host "Error fetching data:" if ($_.Exception.Response -is [System.Net.HttpWebResponse]) { $httpResponse = $_.Exception.Response Write-Host "StatusCode: $($httpResponse.StatusCode)" Write-Host "StatusDescription: $($httpResponse.StatusDescription)" # Read the response stream for detailed error $streamReader = New-Object System.IO.StreamReader($httpResponse.GetResponseStream()) $responseBody = $streamReader.ReadToEnd() Write-Host "Response Body: $responseBody" } else { Write-Host "An unknown error occurred." } break } } return $results } # Function to get all emails for a user function Get-EmailsForUser { param ( [Parameter(Mandatory = $true)] [string]$userPrincipalName ) $mailApiUrl = "$graphApiUrl/users/$userPrincipalName/messages" return Get-PaginatedData -initialUrl $mailApiUrl } # Function to get attachment details for a specific email function Get-AttachmentsForEmail { param ( [Parameter(Mandatory = $true)] [string]$userPrincipalName, [Parameter(Mandatory = $true)] [string]$emailId ) $attachmentApiUrl = "$graphApiUrl/users/$userPrincipalName/messages/$emailId/attachments" return Get-PaginatedData -initialUrl $attachmentApiUrl } # Function to get mailbox settings for a user (including last access time) function Get-MailboxSettings { param ( [Parameter(Mandatory = $true)] [string]$userPrincipalName ) $mailboxSettingsApiUrl = "$graphApiUrl/users/$userPrincipalName/mailboxSettings" $mailboxSettings = Invoke-RestMethod -Uri $mailboxSettingsApiUrl -Headers $headers return $mailboxSettings } # Step 1: Fetch only user mailboxes by filtering on userType eq 'Member' $usersApiUrl = "$graphApiUrl/users?`$filter=userType eq 'Member'" Write-Host "Fetching user mailboxes..." $users = Get-PaginatedData -initialUrl $usersApiUrl if ($users.Count -eq 0) { Write-Host "No user mailboxes found. Aborting script." exit } # Initialize result collection $mailboxDataCollection = @() # Step 2: Loop through each user and gather mailbox data foreach ($user in $users) { $userPrincipalName = $user.userPrincipalName Write-Host "Processing mailbox for $userPrincipalName..." # Initialize user data $mailData = @{ User = $userPrincipalName TotalEmails = 0 TotalAttachments = 0 AttachmentsTypeCount = @{ 'PDF' = 0; 'Word' = 0; 'Excel' = 0; 'PPT' = 0; 'Image' = 0; 'Other' = 0 } LastEmailReceived = $null LastAccessTime = $null } # Get emails for this user $emails = Get-EmailsForUser -userPrincipalName $userPrincipalName foreach ($email in $emails) { $mailData.TotalEmails++ # Track the last email received time if (-not $mailData.LastEmailReceived -or $mailData.LastEmailReceived -lt $email.receivedDateTime) { $mailData.LastEmailReceived = $email.receivedDateTime } # Check for attachments if ($email.hasAttachments) { $attachments = Get-AttachmentsForEmail -userPrincipalName $userPrincipalName -emailId $email.id foreach ($attachment in $attachments) { $mailData.TotalAttachments++ # Determine the type of attachment by file extension if ($attachment.name -match '\.pdf$') { $mailData.AttachmentsTypeCount['PDF']++ } elseif ($attachment.name -match '\.docx?$') { $mailData.AttachmentsTypeCount['Word']++ } elseif ($attachment.name -match '\.xlsx?$') { $mailData.AttachmentsTypeCount['Excel']++ } elseif ($attachment.name -match '\.pptx?$') { $mailData.AttachmentsTypeCount['PPT']++ } elseif ($attachment.contentType -match 'image/') { $mailData.AttachmentsTypeCount['Image']++ } else { $mailData.AttachmentsTypeCount['Other']++ } } } } # Get mailbox settings (last access time) $mailboxSettings = Get-MailboxSettings -userPrincipalName $userPrincipalName $mailData.LastAccessTime = $mailboxSettings.lastSignInDateTime # Add user data to the results $mailboxDataCollection += $mailData } # Step 3: Output results $mailboxDataCollection | Format-Table -AutoSize # Optionally, export the results to CSV $mailboxDataCollection | Export-Csv -Path "MailboxDataReport.csv" -NoTypeInformation My goal is to achieve: Total Numbers of email by each mailbox Total Attachments per email by each mailbox Type of attachments (PDF, Word, Excel, PPT, Image, Etc..) Last access Can someone help me in guiding where i am going wrong i have created azure app with proper permissions but my script is not giving me output as expected.226Views0likes2CommentsM365 Exchange & Shared Mailbox Calendar Notifications
M365 Business Premium tenant here. We have a shared mailbox (not resource mailbox) called meetings@ The aim is to have an anonymous email address staff can send out meeting requests to our clients and have a dedicated calandar for those meetings. I've set up the staff members with Receive and SendAs permissions so everyone can set up meetings using that account so that the meeting invite appears to come from meetings@ instead of the staff members email address. Staff can create meetings and the invite is anonymous so that part is working as planned. The problem is, all the staff gets flooded with Accept/Decline messages going to their personal mailboxes. Is there a way to set it so that only the shared mailbox gets the notifications or even supress those messages entirely. I've resorted to email rules for each staff member to either block or divert the messages but I'd really prefer it if there was a one stop shop rahter than having to configure individual's mailboxes to block them. I tried Set-CalendarProcessing -Identity "email address removed for privacy reasons" -RemoveForwardedMeetingNotifications $true -AutomateProcessing AutoUpdate but it didn't seem to do much. Any other ideas?14Views0likes0CommentsHow do I disable attachments in Outlook draft messages for my organization via Powershell?
My company wants to create a policy that prevents people from starting an Outlook message, adding an attachment to that message, going to another computer or device, opening Outlook on that device, and downloading the file from their draft message. we have O365 and Exchange Online. All the information I've found on setting Outlook options or draft options or any of that has been for individual users rather than organizations. I've been told that it can be done via powershell and office group policies, but TBH, I don't have much Powershell familiarity. Any suggestions?133Views0likes6CommentsImport Calendar Event CSV File via Powershell to Room Resource Calendar
Greetings all, Here's what I am trying to do: We manage our room scheduling with our student management system. I can export room schedule information to a CSV file. I need to be able to import this CSV file to Exchange 365, into a Room Resource Mailbox. We have all of our rooms set up as Resources in Exchange 365, and we have a meeting room display system that shows room availability via displays outside each room. I would like to set up the CSV import via Powershell so my users can schedule rooms in one place and it automatically populate to the Room Resource Calendar. Thanks for the help... TLDR: Need to import CSV calendar events via PowerShell into a room resource calendar. What's the best way? 🙂1.8KViews0likes5CommentsManage Teams Apps via PowerShell
Ahoi, I'm in the process of automating our Office365 via PowerShell and currently working on everything related to "Microsoft Teams (Admin Center)". I managed to do almost anything but I'm now stuck at the management of apps. I'm unable to find a powerShell cmd-let for Org-Wide App settings. I.e. "Disable 3rd Party Apps". Also, I'm having a hard time finding the correct commands for the "Manage App" Lists and to understand how this all fits together with the Permission/Setup Policies. The cmd-lets for the Policies are almost straight forward, so I'm basically asking: Is there a concise way to manage the org-wide App Settings/Manage App Lists via PowerShell (MicrosoftTeams module)?7.8KViews0likes3CommentsUShort Error with the Exchange Module
Hello everyone, For the past few days New-DkimSigningConfig has outputted this error: Unable to find type [ushort] The error was reproduced the following way with PowerShell: Connect-ExchangeOnline (Multiple different tenants with global admin access tried just in case) New-DkimSigningConfig -DomainName example.com -Enabled $true (Example.com is a placeholder for an actual verified domain in a given tenant) Separate and different Windows setups with clean PowerShell and moduleinstallations have also been tried to no avail. Everything was working fine a couple days ago. What is going on? How can one fix this? Thanks2.9KViews0likes8Comments