SharePoint / Script to locate documents encrypted with passwords

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#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:

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.

Leave a Reply