
Ferramenta de extração e auditoria do SharePoint em PowerShell para equipes red/blue/purple. Enumera todos os sites/unidades do SharePoint que um usuário pode acessar via Microsoft Graph, baixa arquivos recursivamente e registra todas as requisições HTTP do Graph + SharePoint para correlação com SIEM, engenharia de detecção e testes de IR.
O SharePointDumper é um utilitário de extração e auditoria baseado em PowerShell que enumera sites do SharePoint que um usuário pode acessar via Microsoft Graph e baixa arquivos via SharePoint.
Ele é projetado para testes de SOC / DLP, purple teaming e avaliações de red team não sofisticadas, e portanto produz relatórios detalhados incluindo arquivos baixados e cada requisição HTTP (Graph + SharePoint) para correlação com SIEM.
A ferramenta não realiza autenticação. Em vez disso, ela requer um token de acesso OAuth2 já obtido com as permissões apropriadas do Microsoft Graph (Sites.Read.All ou Sites.ReadWrite.All).
Se você precisar de ajuda para obter tal token, pode usar o EntraTokenAid (exemplos incluídos abaixo), que simplifica a geração de tokens de acesso utilizáveis.
Execução:

Exemplo de Log de API CSV (pode ser CSV ou JSON):

Exemplo de Log de Download de Arquivos (pode ser CSV ou JSON)

git clone https://github.com/zh54321/SharePointDumper.git
cd SharePointDumper
O SharePointDumper requer um token de acesso válido do Microsoft Graph com permissões delegadas para enumerar sites e arquivos:
Sites.Read.All ouSites.ReadWrite.AllAlém disso, o cliente OAuth deve ter permissão para chamar a API do SharePoint.
Mais de 23 aplicativos próprios da Microsoft já possuem permissões Sites.Read… pré-consentidas. Eles podem baixar arquivos do SharePoint e podem ser usados para obter um token válido sem configuração adicional do tenant.
Se possível, use um token de acesso habilitado para CAE, que permanece válido por até 24 horas e reduz interrupções durante despejos de longa duração.
Você pode usar o EntraTokenAid para obter um token de acesso adequado via PowerShell
(tokens CAE são solicitados por padrão):
# Clone the module
git clone https://github.com/zh54321/EntraTokenAid.git
Import-Module EntraTokenAid/EntraTokenAid.psm1
# Get the the tokens
$tokens = Invoke-Auth -ClientID 'b26aadf8-566f-4478-926f-589f601d9c74' -RedirectUrl 'urn:ietf:wg:oauth:2.0:oob'
# Optional: Store in variable which is compatible with the examples below
$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
Com jitter:
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -RequestDelaySeconds 2 -Variation 3
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -Resume -OutputFolder .\20251121_1551_MyTenant
No modo de retomada, -OutputFolder deve apontar para a pasta da execução anterior.
O SharePointDumper pode atualizar automaticamente um token de acesso expirado (HTTP 401) usando um token de atualização e o EntraTokenAid.
# Mandatory: The module must be imported so the tool can use the Invoke-Refresh command
Import-Module .\EntraTokenAid\EntraTokenAid.psm1
# Optional: Obtain tokens using EntraTokenAid (other methods are also possible)
$tokens = Invoke-Auth -ClientId 'b26aadf8-566f-4478-926f-589f601d9c74' -RedirectUrl 'urn:ietf:wg:oauth:2.0:oob'
# Run SharePointDumper with refresh support
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -RefreshToken $tokens.refresh_token -RefreshClientId 'b26aadf8-566f-4478-926f-589f601d9c74'
Nota: As tentativas de atualização de token NÃO são registradas no log da 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 ou .json)SharePointDumper_ReportResume_*SharePointDumper_ApiLogResume_*Token de acesso inválido ou expirado.
Token de acesso válido, mas faltam permissões necessárias do Microsoft Graph ou SharePoint.
As atividades do SharePointDumper são registradas em:
/organization, /sites, /drives).Exemplo de UAL:

Exemplo de Log de Atividade do Graph:

Lançado sob a Licença MIT.
| Nome do Aplicativo | Client ID | FOCI | Comando de Autenticação do 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' |
| Parâmetro | Obrigatório | Tipo | Descrição |
|---|
AccessToken | Sim | String | Token de acesso OAuth2. Nenhuma autenticação é realizada dentro da ferramenta. |
OutputFolder | Não | String | Diretório para o despejo. Padrão: ".". No modo -Resume, deve apontar para uma pasta de despejo existente da execução anterior. |
UserAgent | Não | String | UserAgent personalizado para todas as requisições HTTP. Padrão: SharePointDumper |
Proxy | Não | String | Proxy HTTP opcional (ex.: http://127.0.0.1:8080). |
IncludeExtensions | Não | String[] | Baixar apenas estas extensões. |
ExcludeExtensions | Não | String[] | Pular estas extensões (ignorado se IncludeExtensions for usado). |
IncludeSites | Não | String[] | Processar apenas sites que correspondam a qualquer um desses valores. |
ExcludeSites | Não | String[] | Pular sites que correspondam a qualquer um desses valores. |
DisableIpLookup | Não | Switch | Não consultar ifconfig.me para IP público. |
RequestDelaySeconds | Não | Double | Atraso base antes de cada requisição HTTP. |
Variation | Não | Double | Jitter aleatório adicionado ao atraso base. |
MaxFiles | Não | Int | Número máximo de arquivos para baixar. Padrão: sem limite. |
MaxTotalSizeMB | Não | Double | Tamanho total máximo de download. Padrão: sem limite. |
Resume | Não | Switch | Pula arquivos já baixados. Requer -OutputFolder. |
ApiLogFormat | Não | String | Csv (padrão), Json ou None. |
ApiLogPath | Não | String | Caminho de saída personalizado para o arquivo de log da API. |
FileLogFormat | Não | String | Csv (padrão), Json ou None. |
FileLogPath | Não | String | Caminho de saída personalizado para o arquivo de log de arquivos. |
LogDownloadTokens | Não | Switch | Registrar URLs completas de download do SharePoint incluindo tokens tempauth (inseguro). Padrão: tokens são ofuscados. |
RefreshToken | Não | String | Token de atualização OAuth2 usado para renovação automática do token de acesso em HTTP 401. |
RefreshClientId | Não | String | Client ID usado junto com -RefreshToken. |
RefreshTenant | Não | String | Autoridade do tenant para o endpoint de atualização (padrão: common). |