Skip to content
Snippets Groups Projects
Commit 9201ee38 authored by Pavel Břoušek's avatar Pavel Břoušek
Browse files

feat: SP-initiated login using discovery response endpoint

parent 62549ed4
No related branches found
No related tags found
No related merge requests found
...@@ -123,15 +123,16 @@ where ...@@ -123,15 +123,16 @@ where
Peforming SP-initiated login is more difficult than the IdP-initiated login used in previous templates. Peforming SP-initiated login is more difficult than the IdP-initiated login used in previous templates.
You can use the included [nuclei workflow](https://docs.projectdiscovery.io/templates/workflows/overview) You can use the included [nuclei workflows](https://docs.projectdiscovery.io/templates/workflows/overview)
to scan a server for available endpoints and perform SP-initiated login if possible: to scan a server for available endpoints and perform SP-initiated login if possible.
```sh ```sh
nuclei -w workflow/saml-sp-workflow.yaml -u https://sp.example.com/ -code -sf secret-file.yaml nuclei -w workflow/<workflow_name>.yaml -u https://sp.example.com/ -code -sf secret-file.yaml -c 1
``` ```
where where
* `<workflow_name>` is either `saml-request-init` for request initiation endpoint or `saml-discovery-response` for discovery response endpoint
* `https://sp.example.com/` is the address of a (potential) SP server (only the domain is relevant) * `https://sp.example.com/` is the address of a (potential) SP server (only the domain is relevant)
## Current limitations ## Current limitations
...@@ -143,3 +144,4 @@ where ...@@ -143,3 +144,4 @@ where
* only SPs which accept unsolicited logins (IdP-initiated) * only SPs which accept unsolicited logins (IdP-initiated)
or with a [Request Initiation](https://docs.oasis-open.org/security/saml/Post2.0/sstc-request-initiation.html) endpoint can be tested or with a [Request Initiation](https://docs.oasis-open.org/security/saml/Post2.0/sstc-request-initiation.html) endpoint can be tested
* headless browser test behaves differently than raw HTTP test (nuclei limitation) * headless browser test behaves differently than raw HTTP test (nuclei limitation)
* custom `returnIDParam` is not supported in discovery response endpoint detection
id: saml-detect-discovery-response-endpoint
info:
name: SAML discovery response endpoint detection
author: T&I Incubator, GÉANT
severity: info
tags: saml,detect,tech
variables:
CONFORMANCE_IDP_ENTITY_ID: "urn:x-simplesamlphp:geant:incubator:conformance-idp"
http:
- method: GET
path:
- "{{RootURL}}{{discoresponseendpoint}}?entityID={{url_encode(CONFORMANCE_IDP_ENTITY_ID)}}"
redirects: false
attack: batteringram
payloads:
discoresponseendpoint:
- ""
- "/"
- "/AccountSaml/SignIn/"
- "/account/shibboleth/Login"
- "/adfs/ls/IdpInitiatedSignon.aspx"
- "/api/login/sso"
- "/auth/saml/meta"
- "/auth/saml/meta.xml"
- "/auth-saml/saml/login"
- "/auth/shibboleth.sso/ds"
- "/auth/shibexternal/Shibboleth.sso/DS"
- "/auth/shibexternal/Shibboleth.sso/Login"
- "/controls/login/AssertionConsumerService.aspx"
- "/edugain/disco"
- "/Edugain/disco"
- "/edugainlogin/Shibboleth.sso/Login"
- "/edugain/Shibboleth.sso/Login"
- "/eduid/Shibboleth.sso/Login"
- "/fastUnit/jsp/echo.do/Shibboleth.sso/Login"
- "/fastUnit/jsp/fast2.do/Shibboleth.sso/Login"
- "/FedAuth/Shibboleth/AssertionService"
- "/federation-manager/Shibboleth.sso/Login"
- "/fedreg/auth/login"
- "/grouper/grouperExternal/Shibboleth.sso/Login"
- "/hcc/Shibboleth.sso/Login"
- "/identity/self-service/bay/autologin.jsf/Shibboleth.sso/Login"
- "/idp/module.php/saml/disco.php"
- "/incommon/disco"
- "/linking/Shibboleth.sso/Login"
- "/lists/Shibboleth.sso/Login"
- "/login"
- "/login/saml/discovery"
- "/module.php/saml/sp/discoresp.php"
- "/oa/disco-ret"
- "/oidc/Shibboleth.sso/Login"
- "/otptokens/Shibboleth.sso/Login"
- "/ready/saml/meta.xml"
- "/research-and-scholarship/Shibboleth.sso/Login"
- "/research-and-scholarship/Shibboleth.sso/SeamlessAccess"
- "/research-and-scholarship/Shibboleth.sso/Wayfinder"
- "/SAML/AssertionConsumerService.aspx"
- "/saml/disco"
- "/saml/discover"
- "/saml/discovered"
- "/saml/login"
- "/SAML/Login"
- "/saml/module.php/saml/sp/discoresp.php"
- "/saml/2/auth"
- "/saml2/disco"
- "/Saml2/disco"
- "/Saml2_idps/disco"
- "/saml2/login"
- "/saml2sp/disco"
- "/Saml2SP/disco"
- "/secureSpace/jsp/fast2.do/Shibboleth.sso/Login"
- "/shibboleth"
- "/shibboleth/assert"
- "/shibboleth/Shibboleth.sso/Login"
- "/shibboleth-sp/Shibboleth.sso/DS"
- "/shibboleth-sp/Shibboleth.sso/Login"
- "/Shibboleth.sso/discovery"
- "/Shibboleth.sso/Discovery"
- "/shibboleth.sso/DS"
- "/Shibboleth.sso/DS"
- "/Shibboleth.sso/DS/Login"
- "/Shibboleth.sso/DS/seamless-access"
- "/Shibboleth.sso/DS/thiss.io"
- "/Shibboleth.sso/EDS"
- "/Shibboleth.sso/edugain"
- "/Shibboleth.sso/eduGAIN"
- "/Shibboleth.sso/EduGain"
- "/Shibboleth.sso/geant"
- "/-shibboleth.sso/Login"
- "/shibboleth.sso/Login"
- "/Shibboleth.sso/Login"
- "/Shibboleth.sso/login/shibboleth"
- "/Shibboleth.sso/MFA"
- "/Shibboleth.sso/SAML/POST"
- "/Shibboleth.sso/SeamlessAccess"
- "/Shibboleth.sso/SeamlessLogin"
- "/Shibboleth.sso/WAYF"
- "/Shibboleth.sso/Wayfinder"
- "/shib/sp/Login"
- "/simplesaml/module.php/saml/disco.php"
- "/simplesaml/module.php/saml/sp/discoresp.php"
- "/simplesamlphp/module.php/saml/sp/discoresp.php"
- "/sp/disco"
- "/sso/login"
- "/sso/module.php/saml/sp/discoresp.php"
- "/wayf/acs/post/disco"
stop-at-first-match: true
matchers:
- type: dsl
name: hasdiscoresponseendpoint
condition: and
dsl:
- "status_code == 302 || status_code == 303 || status_code == 307"
- "contains(location, 'SAMLRequest=')"
extractors:
- type: dsl
name: discoresponseendpoint
dsl:
- "discoresponseendpoint"
code:
- engine:
- python3
- python
- py
source: |
import base64
import zlib
import os
import re
from urllib.parse import unquote
saml_request = unquote(re.sub(r'^.*SAMLRequest=(.*?)(&|$).*', r'\1', os.getenv("http_location")))
saml_request = zlib.decompress(base64.b64decode(saml_request), -zlib.MAX_WBITS).decode()
SP_ENTITY_ID = re.sub(r'^.*>(.*?)</\w+:Issuer.*$', r'\1', saml_request)
print(SP_ENTITY_ID)
extractors:
- type: dsl
name: SP_ENTITY_ID
dsl:
- response
# digest: 4b0a00483046022100fe212de6b150396eef2dfbbca59589d70d206703594a8bb409aeea11138f678f022100a7f081c73485c4ff94a2a95f7d0f91d86e3c2ca62b252b7899295be1ff097b08:16ea744faf4d9956cf0107f1f3cb7c4c
\ No newline at end of file
id: saml-detect-endpoints id: saml-detect-request-init-endpoint
info: info:
name: SAML endpoints detection name: SAML request initiation endpoint detection
author: T&I Incubator, GÉANT author: T&I Incubator, GÉANT
severity: info severity: info
tags: saml,detect,tech tags: saml,detect,tech
...@@ -104,4 +104,4 @@ code: ...@@ -104,4 +104,4 @@ code:
name: SP_ENTITY_ID name: SP_ENTITY_ID
dsl: dsl:
- response - response
# digest: 4a0a0047304502205ecec927cfdf45f5d2711393ed7e8321517f98a969858659a1aa75db26d0b23b022100a390a5522fef78825412f4b60c38abb0f7f41d6f5ac970b24bb5b4c0308887ad:16ea744faf4d9956cf0107f1f3cb7c4c # digest: 4a0a00473045022065227d49bc58bd1a4583141f1568931f48e2add5a3fa2d2409624400040933b6022100e1fb29bd4bc84c2c353e214e2f13cdd8521d35a3d4f685d50045b11addfa8189:16ea744faf4d9956cf0107f1f3cb7c4c
\ No newline at end of file \ No newline at end of file
id: saml-discovery-response
info:
name: SAML signature check using discovery response endpoint
author: T&I Incubator
description: Scan SAML SPs for SAML signature validation problems and vulnerabilities
severity: high
workflows:
- template: workflow/saml-detect-discovery-response-endpoint.yaml
subtemplates:
- template: workflow/saml-signature-discovery-response-raw.yaml
id: saml-sp-workflow id: saml-request-init
info: info:
name: SAML signature checks name: SAML signature check using request initiation endpoint
author: T&I Incubator author: T&I Incubator
description: Scan SAML SPs for SAML signature validation problems and vulnerabilities description: Scan SAML SPs for SAML signature validation problems and vulnerabilities
severity: high severity: high
workflows: workflows:
- template: workflow/saml-detect-endpoints.yaml - template: workflow/saml-detect-request-init-endpoint.yaml
subtemplates: subtemplates:
- template: workflow/saml-signature-request-init-raw.yaml - template: workflow/saml-signature-request-init-raw.yaml
# unfortunatelly it seems that is not possible to combine matchers and shared execution context like this: # unfortunatelly it seems that is not possible to combine matchers and shared execution context like this:
...@@ -15,5 +15,3 @@ workflows: ...@@ -15,5 +15,3 @@ workflows:
#- template: nuclei-templates/saml-signature-request-init-raw.yaml #- template: nuclei-templates/saml-signature-request-init-raw.yaml
#subtemplates: #subtemplates:
# - template: nuclei-templates/saml-signature-request-init-invalid-signatures.yaml # - template: nuclei-templates/saml-signature-request-init-invalid-signatures.yaml
#- tags: ssl,tls,dns,tech,detect
- tags: ssl,tls,dns,tech,detect
id: saml-signature-discovery-response-raw
info:
name: SP initiated SAML authentication endpoint check
author: T&I Incubator, GÉANT
severity: high
tags: saml,signature,raw
variables:
CONFORMANCE_IDP_BASE_URL: https://conformance-idp.maiv1.incubator.geant.org/
CONFORMANCE_IDP_HOSTNAME: '{{replace_regex(CONFORMANCE_IDP_BASE_URL, "^https?://|/.*$", "")}}'
CONFORMANCE_IDP_ENTITY_ID: "urn:x-simplesamlphp:geant:incubator:conformance-idp"
TEST_CASES:
- noSignature
- invalidSignature
flow: |
set("TEST_CASE", "standardResponse");
http();
for (let testcase of iterate(template["TEST_CASES"])) {
set("TEST_CASE", testcase);
http();
}
http:
- raw:
- |
@Host: https://{{CONFORMANCE_IDP_HOSTNAME}}
POST /module.php/conformance/test/setup?testId={{url_encode(TEST_CASE)}}&spEntityId={{url_encode(SP_ENTITY_ID)}} HTTP/1.1
Host: {{CONFORMANCE_IDP_HOSTNAME}}
- |
GET {{discoresponseendpoint}}?entityID={{url_encode(CONFORMANCE_IDP_ENTITY_ID)}} HTTP/1.1
Host: {{Hostname}}
# HTTP-POST binding
- |
@Host: {{replace_regex(trim(acs,"[]"), "^https?://|/.*$", "")}}
POST {{trim(acs,"[]")}} HTTP/1.1
Host: {{replace_regex(trim(acs,"[]"), "^https?://|/.*$", "")}}
Content-Type: application/x-www-form-urlencoded
SAMLResponse={{url_encode(trim(samlresponse,"[]"))}}
disable-path-automerge: true
redirects: true
extractors:
- type: xpath
name: acs
internal: true
attribute: action
xpath:
- '/html/body/form'
- type: xpath
name: samlresponse
internal: true
attribute: value
xpath:
- '/html/body/form/input[2]'
# breaks the template :(
#- type: dsl
# dsl:
# - 'TEST_CASE'
matchers-condition: and
matchers:
- type: status
condition: or
status:
- 200
- 302
- 303
- type: word
words:
- Welcome
- Hello
- Logged in
condition: or
part: body
- type: dsl
dsl:
# ignore the happy case
- '!contains(TEST_CASE, "standardResponse")'
condition: and
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment