sharepoint
131 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/tomwechsler63KViews5likes0CommentsRestore items
On September 23rd (3 days ago) a user deleted a large number of files from SharePoint online. Files are still in 1st Recycle Bin. My question is: What would be the most simple command to restore those files? I'm little confused because I'm not sure from which side to "attack" the issue. Kind regards, Dino4.4KViews1like3CommentsSaving sharepoint list data to excel.
Hi Community, Sharing is good. (Requires PnP.PowerShell & ImportExcel) #Use powershell to save data from specific sharepoint list to excel Cls #Parameters $SiteURL = "https://<company>.sharepoint.com/sites/<sitename>" $ListName = "VM Header List" $SelectedFields = @("Classification","VMName", "IPAddress") $ExcelPath = "$($env:USERPROFILE)\Desktop\Logs\VMHeaderList.xlsx" # User Authentication $ua = @(Get-StoredCredential -Target UserAccount) if($ua.count -eq 0){ Write-Host "Enter UserName & Password..." Exit } $credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $ua.UserName,$ua.Password #Connect to PnP Online Connect-PnPOnline -Url $SiteURL -Credential $credential #Get List items from the list $ListItems = Get-PnPListItem -List $ListName -Fields $SelectedFields -PageSize 2000 #Iterate through each item and extract data $ListDataColl = @() $ListItems | ForEach-Object { $ListData = New-Object PSObject #Get the Field Values of the item as text $ListItem = Get-PnPProperty -ClientObject $_ -Property FieldValuesAsText ForEach($Field in $SelectedFields) { $ListData | Add-Member Noteproperty $Field $ListItem[$Field] } $ListDataColl += $ListData } # Generate Report if (Test-Path $ExcelPath) { Remove-Item $ExcelPath } $ListDataColl $ListDataColl | Export-Excel $ExcelPath -AutoSize -TableName VMHeaderList Write-Host "Finished..."650Views1like0CommentsEditing 'SharePoint added' file properties on the local computer with PowerShell
Hello all, first time posting here, thank you all in advance! We have a SharePoint library with a templates folder that users download documents from. They will then edit and add information, and upload the finished document to another SharePoint folder. I have automated a lot of the process with a PowerShell script on their desktops. My script opens the file (always an excel file, so I use the com object abilities in PowerShell), fill a few cells with some default data based on the user who is logged in and the current date and so on. I then save it to a local folder (with an informative file name) for editing and open the file for the user. But now that our SharePoint library is getting fuller, I am trying to make better use of SharePoint file properties and indexed columns. I have noticed the columns I added to our library are visible on the info page of the workbooks in excel, so they are part of the file even when its on the local computer. And I can even edit the fields in excel, before uploading them to SharePoint. I would like to do this automatically for the user in my PowerShell script. I am already opening the file and filling some cells. Can I also set these properties that are used by SharePoint?629Views1like0CommentsPowerShell SharePoint files count is not accurate
I'm trying to write a powershell script that count all the files inside the main SharePoint folder but some reason my count is not accurate so I'll be really appreciated if I can get any help or suggestion on what might be the reason/ So right now I have "General" folder in my SharePoint Site and it has a ton of file and also nested subfolders. I'm try to count all the files including the files that is located inside the nested subfolders. ``` $SiteURL = "https://comapny.sharepoint.com/sites/Office365Sandbox/" $searchfor = "sites/Office365Sandbox/Shared Documents/General" $folderpath = "Shared Documents/General" $CSVFile = "C:\FileCount\FolderStats.csv" #Connect to SharePoint Online Connect-PnPOnline $SiteURL -useWebLogin #Get the list $List = Get-PnPList -Identity $folderpath | Where-Object {$_.Title -eq 'Documents'} #Get Folders from the Library - with progress bar $global:counter = 0 $FolderItems = Get-PnPListItem -List $folderpath -PageSize 500 -Fields FileLeafRef -ScriptBlock { Param($items) $global:counter += $items.Count; Write-Progress -PercentComplete ` ($global:Counter / ($List.ItemCount) * 100) -Activity "Getting Items from List:" -Status "Processing Items $global:Counter to $($List.ItemCount)";} | Where {$_.FileSystemObjectType -eq "Folder"} Write-Progress -Activity "Completed Retrieving Folders from List $ListName" -Completed $fieldvalues = $FolderItems.Fieldvalues $result = @() foreach ($field in $fieldvalues) { $obj = New-object psobject -property $field $result += $obj.fileref } $final = $result | where-object { $_ -match $searchfor } $item = New-Object psobject -Property @{ FolderName = Split-Path -Path $searchfor -Leaf URL = $searchfor filesfoldercount = $final.count } $item $item | Export-Csv -Path $CSVFile -NoTypeInformation ```776Views1like0CommentsHow to copy a folder from SP online to SP onprem using PowerShell
I have a folder call "General" in my SharePoint Online site. It's about 16GB and a lot of nested folders inside it. I wanted to copy that folder(including all the nested folders) to a different SharePoint Onprem site while it preserved all the data such as created date, modified date..etc using PowerShell so just wondering if anybody know where I might be able to find a PowerShell script that does that?. Any suggestion will be really appreciated.448Views1like0CommentsRestore all files but ones that already exist from the recycle bin using PowerShell
Hello, I have a client that I am working with that had a slight mix-up that lead to many duplicate files being created and then deleted (along with others that they need restored), there are 10,000s of files scattered amongst 100s of sub folders, so a manual process wouldn’t be possible. I know I can restore from the recycle bin by date, but does anyone know of a way that I could use that PowerShell cmdlet to also automatically say “no” to files that already exist? NOTE: the files that are duplicates have the exact same file name and path as the existing ones, meaning that it would make them a “copy” Any help would be appreciated!Solved10KViews1like15CommentsHow to get Variable Data to columns of a CSV - SharePoint Online
Hi, I've been having an issue with getting data from variables to a CSV file. I can run this script and get output data to the screen without issue, but I cannot get that data piped or written to rows of my CSV file. I just keep getting a CSV file with headers and blank data. I've tried using Export-CSV, Add-Content and now I'm trying to use an Array and piping that to the CSV. PLEASE HELP! I've spent hours and days trying to get this to work. Background: I've left the cmlets and comments of the commands I tried but are not working. I'm running the PowerShell script against SharePoint Online and all site collections which returns: $Site.URL = The URL of each Site Collection $Group = The SharePoint groups that have "Full Control" at that site collection $User = The members of users email in that group What does the script do My CSV file has 3 columns GroupName (A1) URL (B1) Users (C1) $AdminCenterURL = "https:\\mytentant-admin.sharepoint.com" $FilePath = "C:\Scripts\PS\SharePoint\Reports\" $CSVReport = "Group_UserReport.csv" $CSV_OutFile = $FilePath + $CSVReport Add-Content -Path $CSV_OutFile -Value '"GroupName","URL","Users"' #Connect to SharePoint Online Connect-SPOService -url $AdminCenterURL -Credential (Get-Credential) #Get all Site collections $Sites = Get-SPOSite -Limit All #Loop through site collections ForEach($Site in $Sites) { Write-host -f Cyan "Searching site: $($Site.URL)" #Get all Groups from the site permissions $SiteGroups = Get-SPOSiteGroup -Site $Site | Where-Object { $_.Roles -ne $NULL -and $_.Users -ne $NULL} #Get Group info and members that have site owners permissions ForEach ($Group in $SiteGroups) { If($Group.Roles.Contains("Full Control")) { Write-Host -f Yellow $Group.Title If(0 -lt $Group.Users.Count) { #Get each member of the group ForEach($User in $Group.Users | Where-Object{$_.contains("@")}) #Exclude system Users { #This line does not add any content to the CSV File (blank file with headers) #Add-Content -Path $CSV_OutFile -Value '$Group.Title, $Site.URL, $User' write-host -f Green $User } } else { # I've try this line and there are no entries add to the CVS file (blank file with just headers #Add-Content -Path $CSV_OutFile -Value $Group.Title, $Site.URL, $User # this line does not work and writes nothing to the file # This line does not add anything to the CSV again no data just a file with headers. #Export-Csv -Path $CSV_OutFile -OutVariable $Group.Title, $Site.URL, $User -NoTypeInformation -Append # I added this Array to see if I can get data because the line above is blank $Group_user_info = @([PSCustomObject]@{ GroupName = $Group.Title URL = $Site.Url User = $User }) # This next line does not seem to contain data either. #$Group_user_info | Export-Csv -Path $CSV_OutFile -NoTypeInformation -Append # I retried this line again and tried to add the Array data to the Add-Content -Path $CSV_OutFile -Value $Group_user_info[0], $Group_user_info[1], $Group_user_info[2] } } } }2.6KViews1like0CommentsScript for Teams-Chat backup
Sometimes it is necessary to save the chat history of a Teams-Channel. I wrote a simple script, where you can select the needed Team(s) and outputting the Chat-Content to a html File. If there are any comments, I'm open for suggestions. Here is the Script: #Install-Module -Name SharePointPnPPowerShellOnline $SecurityScope = @("Group.Read.All") Connect-PnPOnline -Scopes $SecurityScope $PnPGraphAccessToken = Get-PnPGraphAccessToken ,$Headers = @{ "Content-Type" = "application/json" Authorization = "Bearer $PnPGraphAccessToken" } $Date = Get-Date -Format "dd.MM.yyyy, HH:mm" $DOCTYPE = "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'><html xmlns='http://www.w3.org/1999/xhtml'>" $Style ="<style>table {border-collapse: collapse; width:100%;} table th {text-align:left; background-color: #004C99; color:#fff; padding: 4px 30px 4px 8px;} table td {border: 1px solid #004C99; padding: 4px 8px;} td {background-color: #DDE5FF}</style>" $Head = "<head><title>Backup: Teams-Chat</title></head>" $Body = "<body><div style='width: 100%;'><table><tr><th style='text-align:center'><h1>Backup: Teams-Chat from $Date</h1></th></tr></table>" $Table_body = "<div style='width: 100%;'><table><tr><th>TimeStamp</th><th>User Name</th><th>Message</th></tr>" $Content ="" $Footer = "</body>" $response_teams = Invoke-RestMethod -Uri "https://graph.microsoft.com/beta/groups" -Method Get -Headers $Headers -UseBasicParsing $response_teams.value | Where-Object {$_.groupTypes -eq "Unified"} | Select-Object -Property displayName, ID | Out-GridView -PassThru -Title 'Which Team-Chat do you want to backup?' | ForEach-Object { $Team_ID = $_.ID $Team_displayName = $_.displayName Write-Progress -Activity "Bckup Team Chat Mesasages" -Status "Get Team: $($Team_displayName)" Start-Sleep -Milliseconds 50 $Content += "</br></br><hr><h2>Team: " + $Team_displayName + "</h2>" $response_channels = Invoke-RestMethod -Uri "https://graph.microsoft.com/beta/teams/$Team_ID/channels" -Method Get -Headers $Headers -UseBasicParsing $response_channels.value | Select-Object -Property ID, displayName | ForEach-Object { $Channel_ID = $_.ID $Channel_displayName = $_.displayName Write-Progress -Activity "Bckup Team Chat Mesasages" -Status "Get Channel: $($Channel_displayName)" Start-Sleep -Milliseconds 50 $Content += "<h3>Channel: " + $Channel_displayName + "</h3>" $response_messages = Invoke-RestMethod -Uri "https://graph.microsoft.com/beta/teams/$Team_ID/channels/$Channel_ID/messages" -Method Get -Headers $Headers -UseBasicParsing $response_messages.value | Select-Object -Property ID, createdDateTime, from | ForEach-Object { $Message_ID = $_.ID $Message_TimeStamp = $_.createdDateTime $Message_from = $_.from $response_content = Invoke-RestMethod -Uri "https://graph.microsoft.com/beta/teams/$Team_ID/channels/$Channel_ID/messages/$Message_ID" -Method Get -Headers $Headers -UseBasicParsing Write-Progress -Activity "Bckup Team Chat Mesasages" -Status "Get Team: $($Team_displayName), Gett Message-ID: $($Message_ID), from Channel: $($Channel_displayName)" Start-Sleep -Milliseconds 50 $Content += $Table_body + "<td>" + $Message_TimeStamp + "</td><td style='width: 10%;'>" + $Message_from.user.displayName + "</td><td style='width: 75%;'>" + $response_content.body.content + $response_content.attachments.id + "</td></table></div>" $response_Reply = Invoke-RestMethod -Uri "https://graph.microsoft.com/beta/teams/$Team_ID/channels/$Channel_ID/messages/$Message_ID/replies" -Method Get -Headers $Headers -UseBasicParsing $response_Reply.value | Select-Object -Property ID, createdDateTime, from | ForEach-Object { $Reply_ID = $_.ID $Reply_TimeStamp= $_.createdDateTime $Reply_from = $_.from $response_Reply = Invoke-RestMethod -Uri "https://graph.microsoft.com/beta/teams/$Team_ID/channels/$Channel_ID/messages/$Message_ID/replies/$Reply_ID" -Method Get -Headers $Headers -UseBasicParsing Write-Progress -Activity "Bckup Team Chat Mesasages" -Status "Gett Reply-Message-ID: $($Reply_ID)" Start-Sleep -Milliseconds 50 ForEach-Object { $Content += $Table_body + "<td>" + $Reply_TimeStamp + "</td><td style='width: 10%;'>" + $Reply_from.user.displayName + "</td><td style='width: 75%;'>" + $response_Reply.body.content + $response_Reply.attachments.id + $response_Reply.attachments.name + "</td></table></div>" } } } } } $DOCTYPE + $Style + $Head + $Body + $Content + $Footer | Out-File -FilePath "C:\Backup.html" & "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" "C:\Backup.html"18KViews1like4Comments