Skip to content

Commit d13bf14

Browse files
1 parent ac7aa76 commit d13bf14

4 files changed

Lines changed: 238 additions & 0 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-3jp4-mhh4-gcgr",
4+
"modified": "2026-04-14T01:06:06Z",
5+
"published": "2026-04-14T01:06:06Z",
6+
"aliases": [],
7+
"summary": "Kimai has an Open Redirect via Unvalidated RelayState in SAML ACS Handler",
8+
"details": "### Summary\n\nThe SAML authentication success handler in Kimai returns the `RelayState` POST parameter as a redirect destination without validating the host or scheme. After a user successfully authenticates via SAML, they are redirected to an attacker-controlled URL if the IdP includes a malicious `RelayState` value. This enables phishing attacks that steal credentials or session tokens post-SSO.\n\n*Requires SAML to be enabled (non-default configuration).*\n\n### Details\n\nVulnerable file: `src/Saml/Security/SamlAuthenticationSuccessHandler.php`\n\n```php\n// Line 27-33\n$relayState = $request->request->get('RelayState', $request->query->get('RelayState'));\nif (\\is_scalar($relayState)) {\n $relayState = (string) $relayState;\n if ($relayState !== $this->httpUtils->generateUri($request, (string) $this->options['login_path'])) {\n return $relayState; // No host/scheme validation — any URL accepted\n }\n}\n```\n\nThe only check is that `RelayState` does not equal the configured `login_path`. Any external URL (e.g., `https://attacker.com`) passes this check and is returned as the redirect destination.\n\nThe existing unit test `SamlAuthenticationSuccessHandlerTest::testRelayState()` confirms this behavior — an absolute URL in `RelayState` results in a redirect to that URL with no restriction.\n\n### Steps to Reproduce\n\n```\n1. Enable SAML authentication in Kimai\n2. Configure a SAML IdP (e.g., SimpleSAMLphp)\n3. Initiate IdP-initiated SSO with RelayState=https://attacker.com\n — or intercept the ACS POST and modify RelayState to https://attacker.com\n4. Complete SAML authentication at the IdP\n5. Observe: after the SAMLResponse POST to /saml/acs, Kimai issues:\n HTTP/1.1 302 Found\n Location: https://attacker.com\n```\n\nCode-confirmed via unit test (`testRelayState`): `onAuthenticationSuccess` with `RelayState=http://localhost/relayed` redirects directly to that URL. External URLs follow the same code path.\n\n### Impact\n\nWhile this bug exists it has low practical possibilities and the attacker needs to be able to create a SAML request, meaning either admin access to an IdP supporting such an action OR access to the private SAML keys / certificates.\n\nIn other words: only exploitable in IdP-initiated SSO flows where the IdP includes a `RelayState` value supplied by the attacker (e.g., via a malicious link to the IdP).\n\n### Fix\n\nThe `RelayState` is validated before redirecting, see #5878\n\n- It may not contain a host or port and cannot start with `//`. \n- If it contains a host, it must match the current host.",
9+
"severity": [
10+
{
11+
"type": "CVSS_V3",
12+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:N/I:N/A:N"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "Packagist",
19+
"name": "kimai/kimai"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "0"
27+
},
28+
{
29+
"fixed": "2.53.0"
30+
}
31+
]
32+
}
33+
],
34+
"database_specific": {
35+
"last_known_affected_version_range": "<= 2.52.0"
36+
}
37+
}
38+
],
39+
"references": [
40+
{
41+
"type": "WEB",
42+
"url": "https://github.com/kimai/kimai/security/advisories/GHSA-3jp4-mhh4-gcgr"
43+
},
44+
{
45+
"type": "WEB",
46+
"url": "https://github.com/kimai/kimai/pull/5878"
47+
},
48+
{
49+
"type": "PACKAGE",
50+
"url": "https://github.com/kimai/kimai"
51+
}
52+
],
53+
"database_specific": {
54+
"cwe_ids": [
55+
"CWE-601"
56+
],
57+
"severity": "LOW",
58+
"github_reviewed": true,
59+
"github_reviewed_at": "2026-04-14T01:06:06Z",
60+
"nvd_published_at": null
61+
}
62+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-9pm8-vwc5-w2hm",
4+
"modified": "2026-04-14T01:07:01Z",
5+
"published": "2026-04-14T01:07:01Z",
6+
"aliases": [],
7+
"summary": "Fat Free CRM has BOLA in DELETE /emails/:id - Any authenticated user can hit this endpoint and delete emails by ID",
8+
"details": "### Impact\n\nAuthenticated users can delete emails imported into the system assigned to another user; where the [Email Dropbox](https://github.com/fatfreecrm/fat_free_crm/wiki/Email-Dropbox) is in use.\n\n### Patches\n\nFixed in v0.26.0\n\n### Workarounds\n\nDisable use of email dropbox.",
9+
"severity": [
10+
{
11+
"type": "CVSS_V4",
12+
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:P/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "RubyGems",
19+
"name": "fat_free_crm"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "0"
27+
},
28+
{
29+
"fixed": "0.26.0"
30+
}
31+
]
32+
}
33+
]
34+
}
35+
],
36+
"references": [
37+
{
38+
"type": "WEB",
39+
"url": "https://github.com/fatfreecrm/fat_free_crm/security/advisories/GHSA-9pm8-vwc5-w2hm"
40+
},
41+
{
42+
"type": "PACKAGE",
43+
"url": "https://github.com/fatfreecrm/fat_free_crm"
44+
}
45+
],
46+
"database_specific": {
47+
"cwe_ids": [
48+
"CWE-639"
49+
],
50+
"severity": "LOW",
51+
"github_reviewed": true,
52+
"github_reviewed_at": "2026-04-14T01:07:01Z",
53+
"nvd_published_at": null
54+
}
55+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-cmxv-58fp-fm3g",
4+
"modified": "2026-04-14T01:07:42Z",
5+
"published": "2026-04-14T01:07:42Z",
6+
"aliases": [],
7+
"summary": "AsyncHttpClient leaks authorization credentialsto untrusted domains on cross-origin redirects",
8+
"details": "### Impact\nWhen redirect following is enabled (followRedirect(true)), AsyncHttpClient forwards Authorization and Proxy-Authorization headers along with Realm credentials to arbitrary redirect targets regardless of domain, scheme, or port changes. This leaks credentials on cross-domain redirects and HTTPS-to-HTTP downgrades.\n\nAdditionally, even when stripAuthorizationOnRedirect is set to true, the Realm object containing plaintext credentials is still propagated to the redirect request, causing credential re-generation for Basic and Digest authentication schemes via NettyRequestFactory.\n\nAn attacker who controls a redirect target (via open redirect, DNS rebinding, or MITM on HTTP) can capture Bearer tokens, Basic auth credentials, or any other Authorization header value.\n\n### Patches\nFixed in version 3.0.9. Users should upgrade immediately.\n\nThe fix automatically strips Authorization and Proxy-Authorization headers and clears Realm credentials whenever a redirect crosses origin boundaries (different scheme, host, or port) or downgrades from HTTPS to HTTP.\n\n### Workarounds\nFor users unable to upgrade, set (stripAuthorizationOnRedirect(true)) in the client config and avoid using Realm-based authentication with redirect following enabled. Note that (stripAuthorizationOnRedirect(true)) alone is insufficient on versions prior to 3.0.9 because the Realm bypass still re-generates credentials.\n\nAlternatively, disable redirect following (followRedirect(false)) and handle redirects manually with origin validation.",
9+
"severity": [
10+
{
11+
"type": "CVSS_V3",
12+
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "Maven",
19+
"name": "org.asynchttpclient:async-http-client"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "0"
27+
},
28+
{
29+
"fixed": "3.0.9"
30+
}
31+
]
32+
}
33+
]
34+
}
35+
],
36+
"references": [
37+
{
38+
"type": "WEB",
39+
"url": "https://github.com/AsyncHttpClient/async-http-client/security/advisories/GHSA-cmxv-58fp-fm3g"
40+
},
41+
{
42+
"type": "WEB",
43+
"url": "https://github.com/AsyncHttpClient/async-http-client/commit/6b2fbb7f8"
44+
},
45+
{
46+
"type": "PACKAGE",
47+
"url": "https://github.com/AsyncHttpClient/async-http-client"
48+
}
49+
],
50+
"database_specific": {
51+
"cwe_ids": [
52+
"CWE-200"
53+
],
54+
"severity": "MODERATE",
55+
"github_reviewed": true,
56+
"github_reviewed_at": "2026-04-14T01:07:42Z",
57+
"nvd_published_at": null
58+
}
59+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-rh42-6rj2-xwmc",
4+
"modified": "2026-04-14T01:06:25Z",
5+
"published": "2026-04-14T01:06:25Z",
6+
"aliases": [],
7+
"summary": "Kimai leaks API Token Hash via Invoice Twig Template",
8+
"details": "## Summary\n\nThe Twig sandbox used for invoice templates blocks certain sensitive `User` methods (password, TOTP secret, etc.) via a blocklist in `StrictPolicy::checkMethodAllowed()`. However, `getApiToken()` and `getPlainApiToken()` are not on the blocklist. An admin who creates an invoice template can embed calls to these methods, causing the bcrypt or sodium hashed API password of any user who generates an invoice using that template to be included in the rendered output.\n\nOnly relevant for OnPremise installations with template upload activated.\n\n## Background\n\nKimai allows admins (`ROLE_ADMIN` and above) with the `manage_invoice_template` permission to create Twig-based invoice templates. These templates are rendered in a sandboxed Twig environment with `StrictPolicy` controlling which methods and properties are accessible.\n\n`StrictPolicy` explicitly blocks:\n\n```php\n// src/Twig/SecurityPolicy/StrictPolicy.php:156\nif (\\in_array($lcm, [\n 'getpassword',\n 'gettotpsecret',\n 'getplainpassword',\n 'getconfirmationtoken',\n 'gettotpauthenticationconfiguration'\n], true)) {\n throw new SecurityNotAllowedMethodError(...);\n}\n```\n\n`getApiToken()` and `getPlainApiToken()` are **not** in this list and are freely callable.\n\n## Vulnerable Code\n\n`StrictPolicy.php` — missing entries in the User method blocklist:\n\n```php\n// Current\n['getpassword', 'gettotpsecret', 'getplainpassword', 'getconfirmationtoken', 'gettotpauthenticationconfiguration']\n\n// Should also include:\n'getapitoken', 'getplainapitoken'\n```\n\nThe invoice model passes a `User` object through `model.user`, accessible in any twig invoice template.\n\n## Steps to Reproduce\n\n1. Log in as an admin with the `manage_invoice_template` permission.\n2. Create a new Twig invoice template (HTML or PDF) containing:\n\n```twig\nAPI Token: {{ model.user.getApiToken() }}\nPlain Token: {{ model.user.getPlainApiToken() }}\n```\n\n3. Save the template and set it as the default for a customer.\n4. Log in as a regular user assigned to that customer and generate an invoice.\n5. Observe that the rendered invoice contains the user's API token in plaintext.\n\n## Impact\n\nAn admin can silently embed token-exfiltration code in a shared invoice template. Every user who subsequently generates an invoice using that template will have their hashed API token leaked into the invoice output. \n\n- API passwords are [deprecated since April 2024](https://www.kimai.org/en/changelog/2024/cloud-update-104) and not in wide use anymore (especially by new users)\n- The function `getPlainApiToken()` does NEVER return any data\n- The function `getApiToken()` might return a bcrypt or sodium hashed API password, if the user (who created the invoice) has configured one - this cannot be used, but needs to be cracked using rainbow tables\n- The cloud does not allow Twig template upload, this is only relevant for OnPremise installations with template upload activated\n\n## Fix\n\nThe SecurityPolicy was changed to exclude methods that contains certain trigger words instead of using the hard-coded list, see https://github.com/kimai/kimai/pull/5878 \n\nThis disables access to both the `getApiToken()` and `getPlainApiToken()` function.",
9+
"severity": [
10+
{
11+
"type": "CVSS_V3",
12+
"score": "CVSS:3.1/AV:N/AC:H/PR:H/UI:R/S:U/C:L/I:N/A:N"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "Packagist",
19+
"name": "kimai/kimai"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "0"
27+
},
28+
{
29+
"fixed": "2.53.0"
30+
}
31+
]
32+
}
33+
],
34+
"database_specific": {
35+
"last_known_affected_version_range": "<= 2.52.0"
36+
}
37+
}
38+
],
39+
"references": [
40+
{
41+
"type": "WEB",
42+
"url": "https://github.com/kimai/kimai/security/advisories/GHSA-rh42-6rj2-xwmc"
43+
},
44+
{
45+
"type": "WEB",
46+
"url": "https://github.com/kimai/kimai/pull/5878"
47+
},
48+
{
49+
"type": "PACKAGE",
50+
"url": "https://github.com/kimai/kimai"
51+
}
52+
],
53+
"database_specific": {
54+
"cwe_ids": [
55+
"CWE-184"
56+
],
57+
"severity": "LOW",
58+
"github_reviewed": true,
59+
"github_reviewed_at": "2026-04-14T01:06:25Z",
60+
"nvd_published_at": null
61+
}
62+
}

0 commit comments

Comments
 (0)