[JIRA] (JENKINS-56217) allow to hide version number

0 views
Skip to first unread message

thomas.wabner@siemens.com (JIRA)

unread,
Feb 20, 2019, 10:36:02 AM2/20/19
to jenkinsc...@googlegroups.com
Thomas Wabner created an issue
 
Jenkins / Improvement JENKINS-56217
allow to hide version number
Issue Type: Improvement Improvement
Assignee: Unassigned
Components: jenkinsfile-runner
Created: 2019-02-20 15:35
Environment: LTS
Priority: Trivial Trivial
Reporter: Thomas Wabner

It would be nice to have a option (-D or something similar) to hide the version information of the running jenkins master instance.

This would avoid (make it harder) for hackers to attack a jenkins instance which has known vulnerabilities. 

Currently the website shows in the footer the current running jenkins version.

I would like to hide this information or overwrite it with "-1" or similar. Such option can be set a java system property.

We are running jenkins master as WAR archive inside a tomcat container. So the java system property would be the best way to solve this.

 

PS: feel free to change the component .. there seems to be no component for jenkins master or the general UI available.

Add Comment Add Comment
 
This message was sent by Atlassian Jira (v7.11.2#711002-sha1:fdc329d)

o.v.nenashev@gmail.com (JIRA)

unread,
Feb 20, 2019, 5:28:01 PM2/20/19
to jenkinsc...@googlegroups.com
Oleg Nenashev updated an issue
Change By: Oleg Nenashev
Component/s: core
Component/s: jenkinsfile-runner

o.v.nenashev@gmail.com (JIRA)

unread,
Feb 20, 2019, 5:28:02 PM2/20/19
to jenkinsc...@googlegroups.com
Oleg Nenashev updated an issue
Change By: Oleg Nenashev
Labels: security-hardening

o.v.nenashev@gmail.com (JIRA)

unread,
Feb 20, 2019, 5:29:02 PM2/20/19
to jenkinsc...@googlegroups.com

dbeck@cloudbees.com (JIRA)

unread,
Feb 20, 2019, 5:42:01 PM2/20/19
to jenkinsc...@googlegroups.com

The regular UI footer won't do it, as the X-Jenkins header will do that, even with no permissions, on the login screen.

It would certainly be feasible to limit the version information to users with Overall/Read, or perhaps Overall/Administer permission. Something like that seems nicer than a hidden switch nobody knows about anyway – IF we manage to properly implement it (and these kinds of ideas typically fail at this stage).

boards@gmail.com (JIRA)

unread,
Aug 14, 2019, 3:21:02 PM8/14/19
to jenkinsc...@googlegroups.com

Could we add that permission check in Jenkins.getVersion() and return null when unauthorized? I'm going to try that out and see what breaks.

boards@gmail.com (JIRA)

unread,
Aug 14, 2019, 3:23:02 PM8/14/19
to jenkinsc...@googlegroups.com

Too many things directly access the static field, nevermind.

boards@gmail.com (JIRA)

unread,
Aug 14, 2019, 4:27:02 PM8/14/19
to jenkinsc...@googlegroups.com

Ok, time for some fun. I've done some digging in Jenkins and found several places where the version number is exposed in situations with no permission checks.

  • HudsonAuthenticationEntryPoint exposes the version in a header. This class is used for handling permission errors to redirect the user to login in the first place, so clearly there are no permission checks involved.
  • TcpSlaveAgentListener exposes that header when you send a "GET /" request to it.
  • UDPBroadcastThread exposes the version number as an XML tag in the metadata included in the multicast packet sent for autodiscovery. I'm not sure how important the version number is to include here, though it might be required.
  • VersionCommand only requires Overall/Read to execute.
  • Api instances include setting the version header, though typically, these objects are already guarded by other permission checks. However, if even a single API endpoint is unsecured, this would leak the version number.
  • AbstractBuild tracks the version of Jenkins that build was executed in.
  • DownloadService adds a script to the footer of any page that includes the version number in the body of an Ajax request as long as the user has Overall/Read permissions.
  • IncompatibleVMDetected shows information about the running JVM as well, but no Jenkins version other than the footer that's not specific to this error page.
  • l:layout and l:html both include the version number as a header, and l:layout includes the version number in the footer itself.
  • Jenkins/login.jelly exposes the version in headers.

boards@gmail.com (JIRA)

unread,
Aug 14, 2019, 4:32:02 PM8/14/19
to jenkinsc...@googlegroups.com

Some initial searches for Jenkins.VERSION in jenkinsci has found some interesting places:

  • blueocean-plugin seems to include it in its REST API
  • Numerous other plugins access this value, though I'm not sure if it exposes it as a header or in the response in general.

boards@gmail.com (JIRA)

unread,
Aug 14, 2019, 5:04:02 PM8/14/19
to jenkinsc...@googlegroups.com

Some plugins use Functions.advertiseHeaders():

  • warnings-ng-plugin: issues/layout.jelly
  • kerberos-sso-plugin, negotiatesso-plugin: servlet filters add the header.

I don't see any other calls to advertiseHeaders() in any jenkinsci repo. Search was done with up to date copies of all repos as of a few minutes ago. Now that I have an updated set of working copies, I'll perform additional searches for use of Jenkins.VERSION.

boards@gmail.com (JIRA)

unread,
Aug 14, 2019, 5:08:02 PM8/14/19
to jenkinsc...@googlegroups.com

A complete list of files that refer to Jenkins.VERSION along with the number of occurrences:

metrics-plugin/src/main/java/jenkins/metrics/impl/JenkinsVersionsProviderImpl.java:1
artifactory-plugin/src/main/java/org/jfrog/hudson/util/ExtractorUtils.java:1
artifactory-plugin/src/main/java/org/jfrog/hudson/AbstractBuildInfoDeployer.java:1
anchore-container-scanner-plugin/src/main/java/com/anchore/jenkins/plugins/anchore/BuildWorker.java:1
qtest-plugin/src/main/java/com/qasymphony/ci/plugin/action/PushingResultAction.java:1
qtest-plugin/src/main/java/com/qasymphony/ci/plugin/action/SubmitJUnitStep.java:1
maven-plugin/src/main/java/hudson/maven/reporters/BuildInfoRecorder.java:2
custom-build-properties-plugin/src/main/java/org/jenkinsci/plugins/custombuildproperties/CustomBuildPropertiesAction.java:1
blueocean-plugin/blueocean-config/src/main/java/io/jenkins/blueocean/config/BlueOceanConfigStatePreloader.java:1
blueocean-plugin/blueocean-commons/src/main/java/io/jenkins/blueocean/commons/stapler/Export.java:1
support-core-plugin/src/main/java/com/cloudbees/jenkins/support/impl/AboutJenkins.java:2
support-core-plugin/src/main/java/com/cloudbees/jenkins/support/filter/ContentMappings.java:3
swamp-plugin/src/main/java/org/continuousassurance/swamp/jenkins/SwampPostBuild.java:1
compuware-topaz-for-total-test-plugin/src/main/java/com/compuware/jenkins/totaltest/TotalTestCTRunner.java:1
compuware-topaz-for-total-test-plugin/src/main/java/com/compuware/jenkins/totaltest/TotalTestRunner.java:1
bearychat-plugin/src/main/java/jenkins/plugins/bearychat/StandardBearyChatService.java:1
browserstack-integration-plugin/src/main/java/com/browserstack/automate/ci/common/analytics/Analytics.java:1
jenkins/core/src/main/java/hudson/Functions.java:2
jenkins/core/src/main/java/hudson/PluginManager.java:2
jenkins/core/src/main/java/hudson/cli/VersionCommand.java:1
jenkins/core/src/main/java/hudson/Plugin.java:1
jenkins/core/src/main/java/hudson/UDPBroadcastThread.java:1
jenkins/core/src/main/java/hudson/TcpSlaveAgentListener.java:1
jenkins/core/src/main/java/hudson/model/UsageStatistics.java:1
jenkins/core/src/main/java/hudson/model/DownloadService.java:2
jenkins/core/src/main/java/hudson/model/UpdateSite.java:3
jenkins/core/src/main/java/hudson/model/Api.java:1
jenkins/core/src/main/java/hudson/model/AbstractBuild.java:1
jenkins/core/src/main/java/jenkins/install/InstallUtil.java:6
jenkins/core/src/main/java/jenkins/model/AssetManager.java:1
practitest-integration-plugin/src/main/java/org/jenkinsci/plugins/practitest/PractitestApi.java:1
hpe-application-automation-tools-plugin/src/main/java/com/microfocus/application/automation/tools/octane/CIJenkinsServicesImpl.java:1
oracle-cloud-infrastructure-compute-plugin/src/main/java/com/oracle/cloud/baremetal/jenkins/client/SDKBaremetalCloudClient.java:1
sauce-ondemand-plugin/src/main/java/hudson/plugins/sauce_ondemand/SauceOnDemandProjectAction.java:1
sauce-ondemand-plugin/src/main/java/hudson/plugins/sauce_ondemand/JenkinsSauceREST.java:1
sauce-ondemand-plugin/src/main/java/hudson/plugins/sauce_ondemand/SauceOnDemandBuildWrapper.java:1
sauce-ondemand-plugin/src/main/java/hudson/plugins/sauce_ondemand/credentials/SauceCredentials.java:1
sysdig-secure-plugin/src/main/java/com/sysdig/jenkins/plugins/sysdig/BuildWorker.java:1

dbeck@cloudbees.com (JIRA)

unread,
Aug 14, 2019, 5:32:03 PM8/14/19
to jenkinsc...@googlegroups.com

Search was done with up to date copies of all repos as of a few minutes ago.

This should have been done with usage-in-plugins instead.

boards@gmail.com (JIRA)

unread,
Aug 15, 2019, 3:22:02 PM8/15/19
to jenkinsc...@googlegroups.com

I don't see how that's going to help finding method calls in Jelly. I could look into that for checking what references Jenkins.VERSION to see if I missed anything, though.

If we go the route of requiring Overall/Read to view a version number, then this will decrease the surface area of what needs to be updated somewhat significantly.

  • HudsonAuthenticationEntryPoint
  • TcpSlaveAgentListener
  • UDPBroadcastThread
  • IncompatibleVMDetected
  • l:layout and l:html
  • Other plugins TBD

boards@gmail.com (JIRA)

unread,
Aug 15, 2019, 3:26:04 PM8/15/19
to jenkinsc...@googlegroups.com

I'm not finding any direct references to AbstractBuild.getHudsonVersion() other than in various plugins. Some of those plugins use it to display, though permissions involved are unknown.

boards@gmail.com (JIRA)

unread,
Aug 15, 2019, 3:32:02 PM8/15/19
to jenkinsc...@googlegroups.com
Matt Sicker edited a comment on Improvement JENKINS-56217
I don't see how that's going to help finding method calls in Jelly. I could look into that for checking what references Jenkins.VERSION to see if I missed anything, though.

If we go the route of requiring Overall/Read to view a version number, then this will decrease the surface area of what needs to be updated somewhat significantly.

* HudsonAuthenticationEntryPoint
* TcpSlaveAgentListener
* UDPBroadcastThread
*
IncompatibleVMDetected
*
l:layout and l:html
* Other plugins TBD

boards@gmail.com (JIRA)

unread,
Aug 15, 2019, 3:41:04 PM8/15/19
to jenkinsc...@googlegroups.com

I'm running some experiments on this to see what (if anything) breaks by removing the version number when lacking the Overall/Read permission in those files. I do not know what the version number is used for in each of these, so they may require some additional changes to avoid unauthorized leaking of the version number. Both TcpSlaveAgentListener and UDPBroadcastThread seem like they need to provide the Jenkins version, though perhaps that's not necessary anymore with remoting? Jeff Thompson

jthompson@cloudbees.com (JIRA)

unread,
Aug 15, 2019, 4:17:03 PM8/15/19
to jenkinsc...@googlegroups.com

TcpSlaveAgentListener provides the version but I'm pretty confident it doesn't actually need to. That particular response, https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/TcpSlaveAgentListener.java#L306 , provides a little bit of troubleshooting info. Very little. We should have a flag to disable that whole response and make that the default.

There is already a system property to disable UDPBroadcastThread. Auto-discovery of Jenkins on the network is hardly a necessary feature and should probably be disabled by anyone who is paranoid enough about security to hide the version elsewhere. We could ignore this one in favor of the existing property or we could include version suppression here.

Inbound TCP agents use a different header here, https://github.com/jenkinsci/remoting/blob/master/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpointResolver.java#L208 , which contains the minimum supported Remoting version but not the Jenkins version. It may at times be possible to extract some Jenkins version info from this but we haven't updated that in well over two years so it's not very useful. I wouldn't bother with this one.

boards@gmail.com (JIRA)

unread,
Aug 15, 2019, 4:22:02 PM8/15/19
to jenkinsc...@googlegroups.com

That's good news!

Now for more things I've found: Jenkins.getApi() has no permission check. Several other getApi() methods likely also don't do this. I think that Api.setHeaders() can also do a permission check before adding that as a header.

boards@gmail.com (JIRA)

unread,
Aug 15, 2019, 4:56:02 PM8/15/19
to jenkinsc...@googlegroups.com

Still running tests, but as long as nothing relies on programmatic access to the version number without authentication, this shouldn't be an incompatible change.

boards@gmail.com (JIRA)

unread,
Aug 15, 2019, 6:33:02 PM8/15/19
to jenkinsc...@googlegroups.com

Using some fairly wide-reaching changes, the following test failures will need to be investigated:

  • hudson.PluginTest.doDynamic
  • hudson.cli.CLITest.interrupt
  • hudson.cli.CLITest.strictHostKey
  • hudson.model.AbstractProjectTest.configDotXmlSubmissionToDifferentType
  • hudson.model.UsageStatisticsTest.roundtrip
  • jenkins.I18nTest.test_baseName_plugin

There were also some test errors in UDPBroadcastThreadTest, but that randomly happens to me anyways.

jnord@cloudbees.com (JIRA)

unread,
Aug 16, 2019, 10:18:03 AM8/16/19
to jenkinsc...@googlegroups.com

This is nothing more than security through obscurity.

There are plenty of ways to work out the Jenkins version with READ only access and you are not going to get them all. 

The most trivial is that every footer of every HTML page and yes you can get several of those without any permissions whatsoever - but there are plenty more ways that are a little more involved.

jnord@cloudbees.com (JIRA)

unread,
Aug 16, 2019, 10:34:02 AM8/16/19
to jenkinsc...@googlegroups.com

To comment on these and say why it is silly.

 

Jenkins uses a standard `Last-Modified` header on all static content.
Jenkins allows access to static content without authentication (because many pages are served that do not need authentication by design (UnprotectedRootAction))

The last modified of the static content will be when the war was last unpacked (which will not tell you the version but tell you it is at least X days/months old (you can not unpack a version of Jenkins before it exists!)
You also can look at the hashes of all the static content and compare them to what is in every release.  The static content does not change with every release but it does change.
Using that information you can then fudge a version for between X and Y.

 

The reason people want to hide this is to avoid "targeted attacks" and scanners report this as "advertising a version".
But most attacks are not targeted they just try the attack regardless.  How many people have looked at server access logs for a Linux http server and seen windows only attacks.   
You also see attacks for Jenkins regardless of if you are patched or not.

The only way to be safe is to upgrade your software when you are notified of security issues.

infact having a version number exposed can help you do this by easily finding systems that have not upgraded on your network and so you can take steps to get them upgraded or made safe (such as switching off a port on a switch if you can not identify an owner)

jnord@cloudbees.com (JIRA)

unread,
Aug 16, 2019, 10:53:01 AM8/16/19
to jenkinsc...@googlegroups.com
James Nord edited a comment on Improvement JENKINS-56217
To comment on these and say why it is silly not providing any security .

boards@gmail.com (JIRA)

unread,
Aug 19, 2019, 2:10:04 PM8/19/19
to jenkinsc...@googlegroups.com

New approach I'm testing out: refactor Jenkins.VERSION into a static getter and setter named Jenkins.getJenkinsVersion() and Jenkins.setJenkinsVersion() respectively. The former implements a check to ensure that there is a Jenkins instance as well as checking for Overall/Read permissions on the principal; when this check fails, null is returned for the version. I also added an @AdaptField for backward compatibility, though all the direct references to this field in Jenkins were refactored to use the getter.

I'm running through the unit tests now, though some manual exploration showed that this approach seems to work. There are likely some tests that need to be updated that make assumptions about the presence of the X-Jenkins header or the Jenkins version being in the response body somewhere. As of writing, the tests are still running, though I should have a better idea about any test failures soon.

boards@gmail.com (JIRA)

unread,
Aug 19, 2019, 2:13:01 PM8/19/19
to jenkinsc...@googlegroups.com

Update: only test failures I found were from UDPBroadcastThreadTest which is a known flaky test on my machine currently. I'll open a draft PR in order to run some more tests.

boards@gmail.com (JIRA)

unread,
Aug 19, 2019, 2:18:02 PM8/19/19
to jenkinsc...@googlegroups.com

boards@gmail.com (JIRA)

unread,
Aug 21, 2019, 3:01:03 PM8/21/19
to jenkinsc...@googlegroups.com
Matt Sicker started work on Improvement JENKINS-56217
 
Change By: Matt Sicker
Status: Open In Progress

boards@gmail.com (JIRA)

unread,
Aug 21, 2019, 3:01:03 PM8/21/19
to jenkinsc...@googlegroups.com
Matt Sicker assigned an issue to Matt Sicker
 
Change By: Matt Sicker
Assignee: Matt Sicker

boards@gmail.com (JIRA)

unread,
Aug 21, 2019, 3:01:03 PM8/21/19
to jenkinsc...@googlegroups.com
 
Re: allow to hide version number

New approach: https://github.com/jenkinsci/jenkins/pull/4164

I'll have a follow up PR for extended-security-settings-plugin which implements the actual permission check to complete this feature.

boards@gmail.com (JIRA)

unread,
Aug 21, 2019, 3:02:01 PM8/21/19
to jenkinsc...@googlegroups.com
Matt Sicker updated an issue
 
Change By: Matt Sicker
Component/s: extended-security-settings-plugin

boards@gmail.com (JIRA)

unread,
Aug 22, 2019, 10:52:02 AM8/22/19
to jenkinsc...@googlegroups.com
Matt Sicker stopped work on Improvement JENKINS-56217
 
Change By: Matt Sicker
Status: In Progress Open

boards@gmail.com (JIRA)

unread,
Aug 22, 2019, 10:53:02 AM8/22/19
to jenkinsc...@googlegroups.com
 
Re: allow to hide version number

We've discovered several more areas where the Jenkins version is present that would be non-trivial to remove. For example, jenkins-cli.jar is available through an unprotected URL, and inside that jar contains both the MANIFEST.MF and pom.xml that contain the Jenkins version.

boards@gmail.com (JIRA)

unread,
Aug 26, 2019, 12:49:02 PM8/26/19
to jenkinsc...@googlegroups.com
Matt Sicker started work on Improvement JENKINS-56217
 
Change By: Matt Sicker
Status: Open In Progress

boards@gmail.com (JIRA)

unread,
Aug 26, 2019, 12:49:03 PM8/26/19
to jenkinsc...@googlegroups.com
Matt Sicker updated an issue
Change By: Matt Sicker
Component/s: core

boards@gmail.com (JIRA)

unread,
Aug 26, 2019, 12:50:04 PM8/26/19
to jenkinsc...@googlegroups.com
 
Re: allow to hide version number

After discussion with some colleagues, we've decided that adding a servlet filter to ESS would work well enough to implement this feature as requested even though it can't remove the version number from other places.

boards@gmail.com (JIRA)

unread,
Aug 26, 2019, 12:53:02 PM8/26/19
to jenkinsc...@googlegroups.com

boards@gmail.com (JIRA)

unread,
Aug 26, 2019, 12:53:02 PM8/26/19
to jenkinsc...@googlegroups.com

boards@gmail.com (JIRA)

unread,
Sep 5, 2019, 2:50:02 PM9/5/19
to jenkinsc...@googlegroups.com
 

Merged to master. Will be released in 1.2.

Change By: Matt Sicker
Status: In Review Fixed but Unreleased
Resolution: Fixed
Reply all
Reply to author
Forward
0 new messages