SharePointDumper 是一个基于 PowerShell 的提取和审计工具,能够枚举用户通过 Microsoft Graph 可访问的 SharePoint 站点,并通过 SharePoint 下载文件。
该工具专为 SOC / DLP 测试、紫队行动以及非复杂的红队评估而设计,因此会生成详细的报告,包括下载的文件以及每次 HTTP 请求(Graph + SharePoint)的记录,便于 SIEM 关联。
该工具不执行身份认证,而是需要已经获取的、具备适当 Microsoft Graph 权限(Sites.Read.All 或 Sites.ReadWrite.All)的 OAuth2 访问令牌。
如果需要获取此类令牌,可以使用 EntraTokenAid(下文包含示例),它简化了可用访问令牌的生成过程。
执行过程:

示例 CSV API 日志(可输出为 CSV 或 JSON):

示例文件下载日志(可输出为 CSV 或 JSON):

git clone https://github.com/zh54321/SharePointDumper.git
cd SharePointDumper
SharePointDumper 需要一个有效的 Microsoft Graph 访问令牌,并具有委派权限来枚举站点和文件:
Sites.Read.All 或Sites.ReadWrite.All此外,OAuth 客户端必须被允许调用 SharePoint API。
超过 23 个 Microsoft 第一方应用程序已经预先同意 Sites.Read… 权限。它们可以从 SharePoint 下载文件,并且无需额外的租户配置即可用于获取有效令牌。
如果可能,请使用启用 CAE 的访问令牌,其有效期最长可达 24 小时,可减少长时间转储期间的干扰。
你可以使用 EntraTokenAid 通过 PowerShell 获取合适的访问令牌
(默认请求 CAE 令牌):
# 克隆模块
git clone https://github.com/zh54321/EntraTokenAid.git
Import-Module EntraTokenAid/EntraTokenAid.psm1
# 获取令牌
$tokens = Invoke-Auth -ClientID 'b26aadf8-566f-4478-926f-589f601d9c74' -RedirectUrl 'urn:ietf:wg:oauth:2.0:oob'
# 可选:存储到与以下示例兼容的变量中
$AccessToken = $tokens.access_token
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -UserAgent "Not SharePointDumper"
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -IncludeSites "Finance","Projects"
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -ExcludeSites "HR","Legal"
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -IncludeExtensions pdf,docx
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -ExcludeExtensions jpg,bmp
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -MaxFiles 500
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -MaxTotalSizeMB 100
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -RequestDelaySeconds 2
带抖动:
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -RequestDelaySeconds 2 -Variation 3
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -Resume -OutputFolder .\20251121_1551_MyTenant
在恢复模式下,-OutputFolder 必须指向之前运行的文件夹。
SharePointDumper 可以使用刷新令牌和 EntraTokenAid 自动刷新过期的访问令牌(HTTP 401)。
# 必须:导入模块,以便工具可以使用 Invoke-Refresh 命令
Import-Module .\EntraTokenAid\EntraTokenAid.psm1
# 可选:使用 EntraTokenAid 获取令牌(其他方法也可以)
$tokens = Invoke-Auth -ClientId 'b26aadf8-566f-4478-926f-589f601d9c74' -RedirectUrl 'urn:ietf:wg:oauth:2.0:oob'
# 运行 SharePointDumper 并开启刷新支持
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -RefreshToken $tokens.refresh_token -RefreshClientId 'b26aadf8-566f-4478-926f-589f601d9c74'
注意:令牌刷新尝试不会记录在 API 日志中。
20261115_MySecureTenant/
├── SharePointDumper_Report_20261115_080333.txt
├── SharePointDumper_ApiLog_20261115_080333.csv
├── SharePointDumper_FileLog_20261115_080333.csv
├── Site A/
│ └── Documents/
│ ├── file1.docx
│ └── file2.pdf
└── Site B/
└── Site Assets/
Report_*.txt)ApiLog_*.csv 或 .json)SharePointDumper_ReportResume_*SharePointDumper_ApiLogResume_*访问令牌无效或已过期。
访问令牌有效,但缺少所需的 Microsoft Graph 或 SharePoint 权限。
SharePointDumper 的活动会在以下位置记录:
/organization、/sites、/drives)。UAL 示例:

Graph 活动日志示例:

基于 MIT 许可证 发布。
| 应用名称 | 客户端 ID | FOCI | EntraTokenAid 认证命令 |
|---|
| Microsoft Teams | 1fec8e78-bce4-4aaf-ab1b-5451cc387264 | TRUE | $tokens = Invoke-Auth -ClientID '1fec8e78-bce4-4aaf-ab1b-5451cc387264' -RedirectUrl 'https://login.microsoftonline.com/common/oauth2/nativeclient' |
| Outlook Mobile | 27922004-5251-4030-b22d-91ecd9a37ea4 | TRUE | $tokens = Invoke-Auth -ClientID '27922004-5251-4030-b22d-91ecd9a37ea4' -RedirectUrl 'x-msauth-outlook-prod://com.microsoft.Office.Outlook' |
| OneDrive SyncEngine | ab9b8c07-8f02-4f72-87fa-80105867a763 | TRUE | $tokens = Invoke-Auth -ClientID 'ab9b8c07-8f02-4f72-87fa-80105867a763' -RedirectUrl 'https://login.microsoftonline.com/common/oauth2/nativeclient' |
| OneDrive iOS App | af124e86-4e96-495a-b70a-90f90ab96707 | TRUE | $tokens = Invoke-Auth -ClientID 'af124e86-4e96-495a-b70a-90f90ab96707' -RedirectUrl 'ms-onedrive-auth://com.microsoft.skydrive.shareextension' |
| Microsoft Bing Search | cf36b471-5b44-428c-9ce7-313bf84528de | TRUE | $tokens = Invoke-Auth -ClientID 'cf36b471-5b44-428c-9ce7-313bf84528de' -RedirectUrl 'msauth.com.microsoft.bing://auth' |
| OneDrive | b26aadf8-566f-4478-926f-589f601d9c74 | TRUE | $tokens = Invoke-Auth -ClientID 'b26aadf8-566f-4478-926f-589f601d9c74' -RedirectUrl 'urn:ietf:wg:oauth:2.0:oob' |
| SharePoint | d326c1ce-6cc6-4de2-bebc-4591e5e13ef0 | TRUE | $tokens = Invoke-Auth -ClientID 'd326c1ce-6cc6-4de2-bebc-4591e5e13ef0' -RedirectUrl 'msauth://code/ms-sharepoint-auth%3A%2F%2Fcom.microsoft.sharepoint' |
| SharePoint Android | f05ff7c9-f75a-4acd-a3b5-f4b6a870245d | TRUE | $tokens = Invoke-Auth -ClientID 'f05ff7c9-f75a-4acd-a3b5-f4b6a870245d' -RedirectUrl 'msauth://com.microsoft.sharepoint/gSoqzhbCjkyvI%2Fl7kC7IdG7KbPU%3D' |
| OfficeHome | 4765445b-32c6-49b0-83e6-1d93765276ca | FALSE | $tokens = Invoke-Auth -ClientID '4765445b-32c6-49b0-83e6-1d93765276ca' -RedirectUrl 'https://scuprodprv.www.microsoft365.com/spalanding' -Origin 'https://doesnotmatter' |
| SharePoint Online Web Client Extensibility | 08e18876-6177-487e-b8b5-cf950c1e598c | FALSE | $tokens = Invoke-Auth -ClientID '08e18876-6177-487e-b8b5-cf950c1e598c' -RedirectUrl 'https://onedrive.cloud.microsoft/_forms/spfxsinglesignon.aspx' -Origin 'https://doesnotmatter' |
| Microsoft Teams Web Client | 5e3ce6c0-2b1f-4285-8d4b-75ee78787346 | FALSE | $tokens = Invoke-Auth -ClientID '5e3ce6c0-2b1f-4285-8d4b-75ee78787346' -RedirectUrl 'https://teams.cloud.microsoft/convene/townhall' -Origin 'https://doesnotmatter' |
| Portfolios | f53895d3-095d-408f-8e93-8f94b391404e | FALSE | $tokens = Invoke-Auth -ClientID 'f53895d3-095d-408f-8e93-8f94b391404e' -RedirectUrl 'https://project.microsoft.com/msal-redirect2' -Origin 'https://doesnotmatter' |
| Microsoft Remote Assist | fca5a20d-55aa-4395-9c2f-c6147f3c9ffa | FALSE | $tokens = Invoke-Auth -ClientID 'fca5a20d-55aa-4395-9c2f-c6147f3c9ffa' -RedirectUrl 'http://localhost:13824' |
| ProcessSimpleGCC | 38a893b6-d74c-4786-8fe7-bc3b4318e881 | FALSE | $tokens = Invoke-Auth -ClientID '38a893b6-d74c-4786-8fe7-bc3b4318e881' -RedirectUrl 'https://make.gov.powerautomate.us/auth-redirect.html' -Origin 'https://doesnotmatter' |
| WindowsShareExperienceProd | a8759234-4b8b-4d94-8c0a-ee1ab73af270 | FALSE | $tokens = Invoke-Auth -ClientID 'a8759234-4b8b-4d94-8c0a-ee1ab73af270' -RedirectUrl 'ms-appx-web://Microsoft.AAD.BrokerPlugin/a8759234-4b8b-4d94-8c0a-ee1ab73af270' |
| Office voice transcript generator AAD | d2eb9fef-f34c-40ec-b6a3-4bf524065158 | FALSE | $tokens = Invoke-Auth -ClientID 'd2eb9fef-f34c-40ec-b6a3-4bf524065158' -RedirectUrl 'msauth.com.microsoft.Office.TestVoice.TestVoice2://auth' |
| Azure OpenAI Studio | dc807dec-d211-4b3f-bc8a-43b3443c4874 | FALSE | $tokens = Invoke-Auth -ClientID 'dc807dec-d211-4b3f-bc8a-43b3443c4874' -RedirectUrl 'https://dev.oai.azure.com' -Origin 'https://doesnotmatter' |
| Azure AI Studio App | cb2ff863-7f30-4ced-ab89-a00194bcf6d9 | FALSE | $tokens = Invoke-Auth -ClientID 'cb2ff863-7f30-4ced-ab89-a00194bcf6d9' -RedirectUrl 'https://int.ai.azure.com/agents' -Origin 'https://doesnotmatter' |
| Azure Machine Learning Workbench Web App | d7304df8-741f-47d3-9bc2-df0e24e2071f | FALSE | $tokens = Invoke-Auth -ClientID 'd7304df8-741f-47d3-9bc2-df0e24e2071f' -RedirectUrl 'https://dev.ml.azure.com/redirect' -Origin 'https://doesnotmatter' |
| M365ChatClient | c0ab8ce9-e9a0-42e7-b064-33d422df41f1 | FALSE | $tokens = Invoke-Auth -ClientID 'c0ab8ce9-e9a0-42e7-b064-33d422df41f1' -RedirectUrl 'https://fa000000128.resources.office.net/f7024bdc-7caf-4ca8-807d-2908f09640d6/1.0.2412.19011/en-us_web/login.html' -Origin 'https://doesnotmatter' |
| Microsoft Loop App | a187e399-0c36-4b98-8f04-1edc167a0996 | FALSE | $tokens = Invoke-Auth -ClientID 'a187e399-0c36-4b98-8f04-1edc167a0996' -RedirectUrl 'https://hosted.loop.cloud.dev.microsoft/authLanding.html' -Origin 'https://doesnotmatter' |
| Viva Goals | c8423563-e8f6-49f2-924b-90d9f664378a | FALSE | $tokens = Invoke-Auth -ClientID 'c8423563-e8f6-49f2-924b-90d9f664378a' -RedirectUrl 'https://goals-ppe.microsoft.com/aad/consume' -Origin 'https://doesnotmatter' |
| Microsoft Mesh | eea619ad-603a-4b03-a386-860fcc7410d1 | FALSE | $tokens = Invoke-Auth -ClientID 'eea619ad-603a-4b03-a386-860fcc7410d1' -RedirectUrl 'http://localhost:13824' |
| 参数 | 必需 | 类型 | 描述 |
|---|
AccessToken | 是 | String | OAuth2 访问令牌。工具内部不执行认证。 |
OutputFolder | 否 | String | 转储目录。默认值:"."。在 -Resume 模式下,必须指向一个已存在的前一次转储文件夹。 |
UserAgent | 否 | String | 所有 HTTP 请求的自定义 UserAgent。默认值:SharePointDumper |
Proxy | 否 | String | 可选的 HTTP 代理(例如 http://127.0.0.1:8080)。 |
IncludeExtensions | 否 | String[] | 仅下载这些扩展名的文件。 |
ExcludeExtensions | 否 | String[] | 跳过这些扩展名的文件(如果使用了 IncludeExtensions 则忽略)。 |
IncludeSites | 否 | String[] | 仅处理匹配其中任何一个值的站点。 |
ExcludeSites | 否 | String[] | 跳过匹配其中任何一个值的站点。 |
DisableIpLookup | 否 | Switch | 不向 ifconfig.me 查询公网 IP。 |
RequestDelaySeconds | 否 | Double | 每次 HTTP 请求前的基本延迟。 |
Variation | 否 | Double | 添加到基本延迟的随机抖动。 |
MaxFiles | 否 | Int | 最大下载文件数。默认值:无限制。 |
MaxTotalSizeMB | 否 | Double | 最大总下载大小。默认值:无限制。 |
Resume | 否 | Switch | 跳过已下载的文件。需要 -OutputFolder。 |
ApiLogFormat | 否 | String | Csv(默认)、Json 或 None。 |
ApiLogPath | 否 | String | API 日志文件的自定义输出路径。 |
FileLogFormat | 否 | String | Csv(默认)、Json 或 None。 |
FileLogPath | 否 | String | 文件日志文件的自定义输出路径。 |
LogDownloadTokens | 否 | Switch | 记录完整的 SharePoint 下载 URL,包括 tempauth 令牌(不安全)。默认值:令牌会被脱敏。 |
RefreshToken | 否 | String | OAuth2 刷新令牌,用于在 HTTP 401 时自动续订访问令牌。 |
RefreshClientId | 否 | String | 与 -RefreshToken 一起使用的客户端 ID。 |
RefreshTenant | 否 | String | 刷新端点的租户 authority(默认值:common)。 |