Amplification/Reflection attacks: Jenkins CVE-2020-2100

Jenkins

Jenkins (https://jenkins.io) is an open-source tool which can be used to automatically perform tasks such as automatic building and testing of software (continuous deployment/integration). Here in the Department of Chemistry we host some Jenkins instances used by some of our theoretical chemistry research groups, in support of their software engineering workflows.

Whilst debugging an issue with the configuration of one of our Jenkins servers, I stumbled across a documentation page on the Jenkins website: https://wiki.jenkins.io/display/JENKINS/Auto-discovering+Jenkins+on+the+network . One part in particular caught my eye:

Jenkins listens on UDP port 33848. You can either send an UDP broadcast packet (targeted to 255.255.255.255) to this port, or you can send an UDP multicast packet (targeted to 239.77.124.213) to this port. When a packet is received (the payload doesn’t matter), Jenkins will send an XML response to the sending UDP port as a datagram.

The purpose of that feature in Jenkins is to allow easy discovery of Jenkins instances on one’s network. However, there is a definite potential downside to having this feature enabled…

Distributed amplification/reflection Denial of Service attacks

In a Denial of Service attack (DoS), the attacker attempts to overwhelm one or more targets by sending them an excessive amount of network traffic. One strategy that is often used is to perform a “reflected DoS” attack. This relies on the fact that UDP is designed to be a connectionless network protocol and so it is easy to send a network packet to the target system with a faked source IP address. This obscures the IP address of the attacker.

A reflected DoS attack becomes more powerful if it’s possible to also leverage a network service which leads to traffic amplification. This occurs when the size of the network response of the reflector is significantly larger than the size of the packet needed to trigger the reflection. One of the most well-known services that can be abused in this way is NTP (network time protocol): https://www.cvedetails.com/cve/CVE-2013-5211/ . One should generally ensure that network services that could be used for a reflected amplification attack are either disabled if not needed, or only accessible to trusted network ranges rather than exposed to the internet.

CVE-2020-2100

As mentioned earlier, Jenkins will respond with an XML payload if any UDP packet is sent to port 33848. Thus, even a UDP packet consisting solely of UDP/IP/Ethernet headers but zero-length payload can trigger a response. The exact response size depends on factors such as the hostname of the Jenkins instance and the version of Jenkins being run, but is around 150 bytes: for example,

<hudson><version>2.215</version><url>https://jenkins.example.com/</url><server-id>37892b29a81b0d283ba29232452ae314</server-id></hudson>

A commonly-used measure of the size of the amplification is the bandwidth amplification factor (BAF), defined as the ratio of the size of the reflected payload to the size of the original network request. Given that Jenkins responds to a zero-length payload sent to UDP port 33848, the BAF is thus infinite! In practice that’s a slightly misleading characterisation given that the attacker must still send the layer 2/3/4 headers, but it’s still possible to have Jenkins reflect significantly more traffic than is sent to it.

As of October 2019, the Shodan search engine (https://www.shodan.io) identified about 81,000 Jenkins instances that are visible on the internet. Many of them will not respond to a packet sent to UDP port 33848, either due to firewall rules or having disabled Jenkins’ auto-discovery feature. Nonetheless, a quick network scan suggested there were about 10,000 Jenkins instances at that time which did respond and could therefore be used as part of a distributed amplification/reflection DoS attack.

This behaviour also provides a possible DoS vector against a pair of Jenkins instances. An attacker can send a spoofed UDP packet to port 33848 on Jenkins instance A, with a spoofed source address of Jenkins instance B and source port also set to 33848. Jenkins instance A will thus send the ~150 byte XML response to UDP port 33848 of Jenkins instance B, in turn triggering a response which is sent to UDP port 33848 of Jenkins instance A. The subsequent infinite loop could potentially lead to resource exhaustion on either or both of the target Jenkins instances.

This security vulnerability is now listed in the CVE database under CVE-2020-2100.

Jenkins SECURITY-1641

The Jenkins project released a security advisory on 2020-01-29, when Jenkins 2.219 / 2.204.2LTS was released. As of those versions, Jenkins no longer listens on UDP port 33848 by default. According to the Jenkins documentation, it is also possible to explicitly disable the feature by setting the hudson.udp system property to -1.

Anyone running a Jenkins instance should check if their instance is listening on UDP 33848, and…

  • upgrade to the latest version of Jenkins
  • ensure the UDP autodiscovery feature is disabled if not needed
  • ensure that access to UDP port 33848 is only allowed from trusted networks via suitable firewall rules

…all of which is generally good practice when running any network-facing service, of course!

This entry was posted in security, technical. Bookmark the permalink.