Jenkins Credentials Flood
2024-10-06This is a story about input validation and why it should be implemented at every stage where user data is processed, as recommended by OWASP. Let me explain why relying solely on the UI for validation is not sufficient.
I will guide you through two issues with the Jenkins credentials plugin that were discovered earlier this year, and I will also provide a working Python script for you to test it yourself. The first issue is related to credentials with the same IDs—something that, in theory, should not be possible (and has already been fixed by Jenkins). The second issue is related to the length of credentials' descriptions and how it affects users' web browsers, making them unresponsive and disrupting Jenkins resources.
Credential ID duplicaticates
In January, while adding and editing some credentials in Jenkins with a colleague of mine (Nelson Ferreira), we discovered an odd behavior that allowed any authenticated user to create multiple credentials with the same ID. This issue was reported to the Jenkins team (Cloudbees) and properly addressed JENKINS-72611. However, it still affects any Jenkins installation using the Credentials Plugin prior to version 1337.v60b_d7b_c7b_c9f.
This is possible in older versions of the Credentials Plugin due to issues with input validation when editing a credential. If a user attempts to create a credential with an existing ID, the server will return an error message, as expected.
However, when the user attempts to edit an existing ID, the only validation occurs on the UI, meaning the server will override the ID with any value the user provides.
1st step: Create a secret with a random ID
2nd step: Edit the description of the newly created credential and capture the HTTP request (you can use the Network tab in your browser's developer tools)
3rd step: Now, select the updateSubmit request, hit edit, and replay it, or use an external tool such as Postman to modify the ID parameter and resend the request. The ID parameter should be updated to one that already exists in the credentials store (in this case, harckade-1).
While the server's response indicates that the page was not found, in reality, Jenkins now contains two credentials with the same ID. You might try to delete the credential that just overwrote the original one, but you can't. If you attempt to delete the newly created credential, the original one will be removed instead.
4th step: Confirm that there are two credentials with the same ID. If you return to the main credentials page, you will notice both credentials with the same ID listed.
As an alternative, you can use the Jenkins Credentials Flood tool to exploit this bug.
Crash user's browser and spike Jenkins' CPU usage via credential description
Another bug related to credentials is that there is no limit to the number of characters that the username, password, and description can contain. However, we'll focus on the description, as this parameter is always embedded in the HTML when the user visits the credential store.
NOTE: Providing extremely long usernames or passwords will cause pipeline failures due to Java's maximum string size exceptions, but it will not result in any DoS impacts.
Adding a single credential with more than 1,000,000,000 characters may crash the user's browser, making it painful to remove this credential from the system. As an alternative, you can add multiple credentials with shorter description lengths. However, adding multiple credentials with smaller descriptions may also impact the loading time of that particular credential store. It is worth mentioning that while the user attempts to load the credentials page, the server may experience a spike in CPU usage. However, once the user's connection is lost, the CPU returns to normal.
If you wish to test this yourself, you can use the Python tool that allows you to easily add as many credentials as you want, with any length you desire.
Github: Jenkins Credentials Flood repository.