%3CLINGO-SUB%20id%3D%22lingo-sub-1513935%22%20slang%3D%22en-US%22%3ERe%3A%20SharePoint%20%2F%20Script%20to%20locate%20documents%20encrypted%20with%20passwords%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1513935%22%20slang%3D%22en-US%22%3E%3CP%3EHi%20Mike%2C%3C%2FP%3E%3CP%3EThanks%20for%20sharing!%20Not%20many%20organisations%20recognize%20the%20need%20to%20identify%20encrypted%20documents%20in%20SharePoint%20eventhough%20there%20are%20several%20reasons%20(e.g.%20compliance%2C%20searchable%20content%2C%20password%20management%2C%20...).%3CBR%20%2F%3E%3CBR%20%2F%3E%3C%2FP%3E%3CP%3EThere%20are%203rd%20party%20solutions%20with%20this%20capability.%20See%20e.g.%20%3CA%20href%3D%22https%3A%2F%2Fwww.slimapplications.com%2Fwp-content%2Fuploads%2F2020%2F07%2FEncrypted-Documents.jpg%22%20target%3D%22_blank%22%20rel%3D%22noopener%20nofollow%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3Ehttps%3A%2F%2Fwww.slimapplications.com%2Fwp-content%2Fuploads%2F2020%2F07%2FEncrypted-Documents.jpg%3C%2FA%3E%3C%2FP%3E%3CP%3EThis%20tool%20will%20list%20encrypted%20files%20based%20on%20the%20extension%20(%22hc%2Cpgp%2Cbexpk%2Csda%2Cp7a%2Cp7z%2Cp7m%2Cp7s%2Cpfx%22)%20or%20whether%20the%20file%20contains%20an%20encryption%20marker%20(e.g.%20docx%2C%20xlsx%2C%20pptx%2C%20vsdx%2C%20zip%2C%20pdf%2C%20..).%20The%20tool%20only%20retrieves%20part%20of%20the%20file%20to%20avoid%20downloading%20the%20full%20document.%3C%2FP%3E%3CP%3EPaul%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1514094%22%20slang%3D%22en-US%22%3ERe%3A%20SharePoint%20%2F%20Script%20to%20locate%20documents%20encrypted%20with%20passwords%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1514094%22%20slang%3D%22en-US%22%3E%3CP%3EHi%2C%26nbsp%3B%3CBR%20%2F%3EJust%20tested%20your%20PowerShell%20script%20against%20my%20set%20with%20test%20files.%20You%20may%20want%20to%20consider%20adding%20certain%20extensions%20like%20pgp%2C%20hc%2C%20etc%20..%20as%20encrypted.%20I%20also%20noted%20that%20it%20does%20not%20detect%20encrypted%20PDF%20files%20or%20encrypted%20zip%20files.%20You%20should%20be%20able%20to%20extend%20the%20match%20statement%20to%20also%20detect%20the%20patterns%20used%20by%20encrypted%20PDF%20and%20encrypted%20zip%20files.%3C%2FP%3E%3CP%3Echeers%2C%3CBR%20%2F%3EPaul%3CBR%20%2F%3E%3CBR%20%2F%3E%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1514369%22%20slang%3D%22en-US%22%3ERe%3A%20SharePoint%20%2F%20Script%20to%20locate%20documents%20encrypted%20with%20passwords%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1514369%22%20slang%3D%22en-US%22%3E%3CP%3EHello%20Paul%2C%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EI%20should%20have%20mentioned%20that%20this%20will%20only%20work%20with%20Office%20documents%20that%26nbsp%3B%3CSPAN%3Euse%20the%20OpenXML%20format%20(Office%202007%20and%20later).%20The%20file%20is%20being%20parsed%20as%20text%2C%20so%20you%20can%20open%20your%20files%20in%20NOTEPAD%2C%20to%20find%20a%20common%20encrypted%20string%2C%20then%20create%20several%20If%20statements%20to%20cover%20all%20the%20files%20you%20want%20to%20find.%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%3EThis%20is%20was%20meant%20to%20be%20a%20starting%20point.%20Please%20feel%20free%20to%20reuse%20this%20and%20expand%20it%20to%20meet%20your%20needs.%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%3EThanks%2C%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%3CSPAN%3EMike%3C%2FSPAN%3E%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1514469%22%20slang%3D%22en-US%22%3ERe%3A%20SharePoint%20%2F%20Script%20to%20locate%20documents%20encrypted%20with%20passwords%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1514469%22%20slang%3D%22en-US%22%3E%3CP%3EHi%20Mike%2C%3CBR%20%2F%3EClear.%3CBR%20%2F%3EThat%20explains.%20It%20is%20indeed%20a%20good%20starting%20point%20for%20most%20companies.%20Thanks%20for%20sharing.%3CBR%20%2F%3EPaul%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1521029%22%20slang%3D%22en-US%22%3ERe%3A%20SharePoint%20%2F%20Script%20to%20locate%20documents%20encrypted%20with%20passwords%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1521029%22%20slang%3D%22en-US%22%3E%3CP%3E%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F4831%22%20target%3D%22_blank%22%3E%40Paul%20de%20Jong%3C%2FA%3E%26nbsp%3B%3C%2FP%3E%3CP%3EThis%20is%20going%20to%20be%20extremely%20useful%20in%20my%20place%20of%20work.%26nbsp%3B%20Thanks%20a%20lot%20for%20posting%20to%20the%20community.%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1512775%22%20slang%3D%22en-US%22%3ESharePoint%20%2F%20Script%20to%20locate%20documents%20encrypted%20with%20passwords%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1512775%22%20slang%3D%22en-US%22%3E%3CH2%20id%3D%22toc-hId--1300959694%22%20id%3D%22toc-hId--1300959695%22%3ESummary%3C%2FH2%3E%0A%3CP%3EA%20customer%20asked%20if%20there%20was%20a%20method%20to%20identity%20documents%20stored%20in%20SharePoint%20online%20that%20were%20encrypted%20with%20passwords.%20Since%20nothing%20like%20this%20existed%2C%20it%20was%20created%20using%20PowerShell.%20I%E2%80%99m%20sharing%20this%20because%20the%20logic%20in%20the%20script%20may%20be%20useful%20for%20others.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH2%20id%3D%22toc-hId-1186553139%22%20id%3D%22toc-hId-1186553138%22%3EThe%20Code%3C%2FH2%3E%0A%3CPRE%20class%3D%22powershell%22%3E%23Title%3A%20find-docpasswords%3CBR%20%2F%3E%23Description%3A%20Iterates%20through%20each%20item%20in%20a%20specified%20list%20to%20find%20documents%20stored%20with%20passwords.%3CBR%20%2F%3E%23Date%3A%207%2F8%2F2020%3CBR%20%2F%3E%23Author%3A%20Mike%20Lee%3CBR%20%2F%3E%23Disclaimer%3A%20This%20PowerShell%20script%20is%20provided%20%22as-is%22%20with%20no%20warranties%20expressed%20or%20implied.%20Use%20it%20at%20your%20own%20risk.%3CBR%20%2F%3E%23Dependencies%3A%20SharePoint%20Online%20Client%20Components%20SDK%3A%20https%3A%2F%2Fwww.microsoft.com%2Fen-us%2Fdownload%2Fdetails.aspx%3Fid%3D42038%3CBR%20%2F%3E%23Tested%20with%20SharePoint%20Online%20Client%20Components%20SDK%20version%2016.0.6906.1200%3CBR%20%2F%3E%23Parameters%3A%20%24SiteURL%2C%20%24ListName%2C%20%24username%3CBR%20%2F%3E%3CBR%20%2F%3E%3CBR%20%2F%3E%23Add%20references%20to%20SharePoint%20client%20assemblies%3CBR%20%2F%3E%5BSystem.Reflection.Assembly%5D%3A%3ALoadWithPartialName(%22Microsoft.SharePoint.Client%22)%3CBR%20%2F%3E%5BSystem.Reflection.Assembly%5D%3A%3ALoadWithPartialName(%22WindowsBase%22)%3CBR%20%2F%3E%3CBR%20%2F%3E%3CBR%20%2F%3E%23Your%20SPO%20Tenant%3CBR%20%2F%3E%24SiteURL%20%3D%20%22https%3A%2F%2Ftenant.sharepoint.com%22%3CBR%20%2F%3E%3CBR%20%2F%3E%23The%20name%20of%20your%20document%20library%3CBR%20%2F%3E%24Listname%20%3D%20%22Documents%22%3CBR%20%2F%3E%3CBR%20%2F%3E%23The%20admin%20account%20that%20has%20access%20to%20the%20library%3CBR%20%2F%3E%24username%20%3D%20%22admin%40tenant.onmicrosoft.com%22%3CBR%20%2F%3E%24password%20%3D%20Read-Host%20%22Enter%20Password%22%20-AsSecureString%3CBR%20%2F%3E%3CBR%20%2F%3E%23Building%20Context%3CBR%20%2F%3E%24ctx%20%3D%20New-Object%20Microsoft.SharePoint.Client.ClientContext(%24SiteURL)%3CBR%20%2F%3E%24ctx.Credentials%20%3D%20New-Object%20Microsoft.SharePoint.Client.SharePointOnlineCredentials(%24userName%2C%20%24password)%3CBR%20%2F%3E%24List%20%3D%20%24ctx.Web.Lists.GetByTitle(%24ListName)%20%3CBR%20%2F%3E%3CBR%20%2F%3E%3CBR%20%2F%3E%23CAML%20Query%20to%20recursively%20look%20at%20all%20items%20in%20the%20library%20with%20a%205000%20item%20row%20limit.%20%3CBR%20%2F%3E%24camlQuery%20%3D%20New-Object%20Microsoft.SharePoint.Client.CamlQuery%3CBR%20%2F%3E%24camlQuery.ViewXml%20%3D%20%40%22%3CBR%20%2F%3E%3CVIEW%20scope%3D%22RecursiveAll%22%3E%3CBR%20%2F%3E%3CQUERY%3E%3CBR%20%2F%3E%3CORDERBY%3E%3CFIELDREF%20name%3D%22ID%22%20ascending%3D%22TRUE%22%3E%3C%2FFIELDREF%3E%3C%2FORDERBY%3E%3CBR%20%2F%3E%3C%2FQUERY%3E%3CBR%20%2F%3E%3CROWLIMIT%20paged%3D%22TRUE%22%3E5000%3C%2FROWLIMIT%3E%3CBR%20%2F%3E%3C%2FVIEW%3E%3CBR%20%2F%3E%22%40%3CBR%20%2F%3E%3CBR%20%2F%3E%24items%20%3D%20%24list.GetItems(%24camlQuery)%3CBR%20%2F%3E%24ctx.Load(%24items)%3CBR%20%2F%3E%24ctx.ExecuteQuery()%3CBR%20%2F%3E%3CBR%20%2F%3E%23function%20to%20read%20documents%3CBR%20%2F%3E%3CBR%20%2F%3Efunction%20find-docpasswords(%24ctx%2C%20%24FileUrl)%3CBR%20%2F%3E%7B%3CBR%20%2F%3E%23Collect%20Documents%20Data%3CBR%20%2F%3E%24FileURL%20%3D%20%24Item.FieldValues%5B'FileRef'%5D%3CBR%20%2F%3E%3CBR%20%2F%3E%23Read%20the%20files%20from%20SharePoint%20online%20document%20library.%3CBR%20%2F%3E%24fileInfo%20%3D%20%5BMicrosoft.SharePoint.Client.File%5D%3A%3AOpenBinaryDirect(%24ctx%2C%24FileURL)%3CBR%20%2F%3E%24stream%20%3D%20New-Object%20System.IO.MemoryStream%3CBR%20%2F%3E%24fileInfo.Stream.CopyTo(%24stream)%3CBR%20%2F%3E%3CBR%20%2F%3E%23Read%20the%20first%20row%20of%20bytes%20as%20text%3CBR%20%2F%3E%24Start%20%3D%20%5BSystem.Text.Encoding%5D%3A%3ADefault.GetString(%24stream.ToArray()%5B0000..2000%5D)%3CBR%20%2F%3E%3CBR%20%2F%3E%23%20Record%20files%20that%20are%20password%20protected%3CBR%20%2F%3Eif(%24Start%20-match%20%22E.n.c.r.y.p.t.e.d.P.a.c.k.a.g.e%22)%3CBR%20%2F%3E%7B%3CBR%20%2F%3EWrite-Host%20%22%24SiteURL%24FileURL%20--%20Is%20Password%20Protected%22%20-ForegroundColor%20Yellow%3CBR%20%2F%3E%7D%3CBR%20%2F%3Eelse%3CBR%20%2F%3E%7B%3CBR%20%2F%3EWrite-Host%20%22%24SiteURL%24FileURL%20--%20Not%20Password%20Protected%22%20-ForegroundColor%20Green%3CBR%20%2F%3E%7D%3CBR%20%2F%3E%3CBR%20%2F%3E%24stream.Close()%3CBR%20%2F%3E%24fileinfo.Dispose()%3CBR%20%2F%3E%24ctx.Dispose()%3CBR%20%2F%3E%7D%3CBR%20%2F%3E%3CBR%20%2F%3E%3CBR%20%2F%3E%23Run%20the%20function%20to%20loop%20through%20all%20items%20in%20the%20library%20and%20find%20documents%20stored%20with%20passwords%3CBR%20%2F%3E%3CBR%20%2F%3Eforeach(%24item%20in%20%24items)%3CBR%20%2F%3E%7B%3CBR%20%2F%3E%24fileUrl%20%3D%20%24item.FieldValues%5B%22fileref%22%5D%3CBR%20%2F%3Efind-docpasswords%20%24ctx%20%24fileurl%3CBR%20%2F%3E%7D%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH2%20id%3D%22toc-hId--620901324%22%20id%3D%22toc-hId--620901325%22%3ETakeaways%3C%2FH2%3E%0A%3CP%3EThis%20scripts%20loops%20though%20a%20specified%20document%20library%20and%20reads%20the%20first%20200%20binary%20bytes%20as%20text.%20If%20the%20encrypted%20string%20is%20found%2C%20the%20document%20URL%20is%20reported%20in%20the%20console%20output.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EHere%20is%20an%20example%20of%20the%20output%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%224.png%22%20style%3D%22width%3A%20982px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F204451i82223FEFF93CFA99%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20title%3D%224.png%22%20alt%3D%224.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EYou%20will%20need%20a%20few%20things%20to%20make%20this%20works.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3COL%20type%3D%221%22%3E%0A%3CLI%3EInstalled%20the%3CSPAN%3E%26nbsp%3B%3C%2FSPAN%3E%3CA%20href%3D%22https%3A%2F%2Fwww.microsoft.com%2Fen-us%2Fdownload%2Fdetails.aspx%3Fid%3D42038%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%22%3ESharePoint%20Online%20Client%20Components%20SDK%3C%2FA%3E%3C%2FLI%3E%0A%3C%2FOL%3E%0A%3COL%20start%3D%222%22%20type%3D%221%22%3E%0A%3CLI%3ESpecify%20the%20%E2%80%9C%24SiteURL%2C%20%24Listname%2C%20and%20%24username%20in%20the%20script.%3C%2FLI%3E%0A%3C%2FOL%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-TEASER%20id%3D%22lingo-teaser-1512775%22%20slang%3D%22en-US%22%3E%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%225.PNG%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F204456i2F5E86AD6B6717FE%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20title%3D%225.PNG%22%20alt%3D%225.PNG%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%3C%2FLINGO-TEASER%3E%3CLINGO-LABS%20id%3D%22lingo-labs-1512775%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3ESupport%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E

Summary

A customer asked if there was a method to identity documents stored in SharePoint online that were encrypted with passwords. Since nothing like this existed, it was created using PowerShell. I’m sharing this because the logic in the script may be useful for others.

 

The Code

#Title: find-docpasswords
#Description: Iterates through each item in a specified list to find documents stored with passwords.
#Date: 7/8/2020
#Author: Mike Lee
#Disclaimer: This PowerShell script is provided "as-is" with no warranties expressed or implied. Use it at your own risk.
#Dependencies: SharePoint Online Client Components SDK: https://www.microsoft.com/en-us/download/details.aspx?id=42038
#Tested with SharePoint Online Client Components SDK version 16.0.6906.1200
#Parameters: $SiteURL, $ListName, $username


#Add references to SharePoint client assemblies
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
[System.Reflection.Assembly]::LoadWithPartialName("WindowsBase")


#Your SPO Tenant
$SiteURL = "https://tenant.sharepoint.com"

#The name of your document library
$Listname = "Documents"

#The admin account that has access to the library
$username = "admin@tenant.onmicrosoft.com"
$password = Read-Host "Enter Password" -AsSecureString

#Building Context
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
$ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($userName, $password)
$List = $ctx.Web.Lists.GetByTitle($ListName)


#CAML Query to recursively look at all items in the library with a 5000 item row limit.
$camlQuery = New-Object Microsoft.SharePoint.Client.CamlQuery
$camlQuery.ViewXml = @"
<View Scope="RecursiveAll">
<Query>
<OrderBy><FieldRef Name='ID' Ascending='TRUE'/></OrderBy>
</Query>
<RowLimit Paged="TRUE">5000</RowLimit>
</View>
"@

$items = $list.GetItems($camlQuery)
$ctx.Load($items)
$ctx.ExecuteQuery()

#function to read documents

function find-docpasswords($ctx, $FileUrl)
{
#Collect Documents Data
$FileURL = $Item.FieldValues['FileRef']

#Read the files from SharePoint online document library.
$fileInfo = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($ctx,$FileURL)
$stream = New-Object System.IO.MemoryStream
$fileInfo.Stream.CopyTo($stream)

#Read the first row of bytes as text
$Start = [System.Text.Encoding]::Default.GetString($stream.ToArray()[0000..2000])

# Record files that are password protected
if($Start -match "E.n.c.r.y.p.t.e.d.P.a.c.k.a.g.e")
{
Write-Host "$SiteURL$FileURL -- Is Password Protected" -ForegroundColor Yellow
}
else
{
Write-Host "$SiteURL$FileURL -- Not Password Protected" -ForegroundColor Green
}

$stream.Close()
$fileinfo.Dispose()
$ctx.Dispose()
}


#Run the function to loop through all items in the library and find documents stored with passwords

foreach($item in $items)
{
$fileUrl = $item.FieldValues["fileref"]
find-docpasswords $ctx $fileurl
}

 

Takeaways

This scripts loops though a specified document library and reads the first 200 binary bytes as text. If the encrypted string is found, the document URL is reported in the console output.

 

Here is an example of the output:

 

4.png

 

You will need a few things to make this works.

 

  1. Installed the SharePoint Online Client Components SDK
  1. Specify the “$SiteURL, $Listname, and $username in the script.

 

5 Comments
Frequent Contributor

Hi Mike,

Thanks for sharing! Not many organisations recognize the need to identify encrypted documents in SharePoint eventhough there are several reasons (e.g. compliance, searchable content, password management, ...).

There are 3rd party solutions with this capability. See e.g. https://www.slimapplications.com/wp-content/uploads/2020/07/Encrypted-Documents.jpg

This tool will list encrypted files based on the extension ("hc,pgp,bexpk,sda,p7a,p7z,p7m,p7s,pfx") or whether the file contains an encryption marker (e.g. docx, xlsx, pptx, vsdx, zip, pdf, ..). The tool only retrieves part of the file to avoid downloading the full document.

Paul

Frequent Contributor

Hi, 
Just tested your PowerShell script against my set with test files. You may want to consider adding certain extensions like pgp, hc, etc .. as encrypted. I also noted that it does not detect encrypted PDF files or encrypted zip files. You should be able to extend the match statement to also detect the patterns used by encrypted PDF and encrypted zip files.

cheers,
Paul

Hello Paul,

 

I should have mentioned that this will only work with Office documents that use the OpenXML format (Office 2007 and later). The file is being parsed as text, so you can open your files in NOTEPAD, to find a common encrypted string, then create several If statements to cover all the files you want to find.

 

This is was meant to be a starting point. Please feel free to reuse this and expand it to meet your needs.

 

Thanks,

Mike

Frequent Contributor

Hi Mike,
Clear.
That explains. It is indeed a good starting point for most companies. Thanks for sharing.
Paul

Frequent Contributor

@Paul de Jong 

This is going to be extremely useful in my place of work.  Thanks a lot for posting to the community.