VYPR
Critical severity9.8NVD Advisory· Published Jan 12, 2017· Updated May 13, 2026

CVE-2016-9299

CVE-2016-9299

Description

The remoting module in Jenkins before 2.32 and LTS before 2.19.3 allows remote attackers to execute arbitrary code via a crafted serialized Java object, which triggers an LDAP query to a third-party server.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.jenkins-ci.main:jenkins-coreMaven
>= 2.20, < 2.322.32
org.jenkins-ci.main:jenkins-coreMaven
< 2.19.32.19.3

Patches

5
ce8a2d51a5ee

Merge pull request #73 from jenkinsci-cert/20161116-for-1.625

https://github.com/jenkinsci/jenkinsJesse GlickNov 13, 2016via ghsa
4 files changed · +38 4
  • pom.xml+1 1 modified
    @@ -179,7 +179,7 @@ THE SOFTWARE.
           <dependency>
             <groupId>org.jenkins-ci.main</groupId>
             <artifactId>remoting</artifactId>
    -        <version>2.53.3</version>
    +        <version>2.53.4</version>
           </dependency>
     
           <dependency>
    
  • test/src/test/java/jenkins/security/Security218CliTest.java+9 0 modified
    @@ -161,6 +161,15 @@ public void probeSpring2() throws Exception {
             probe(Payload.Spring2, -1);
         }
         
    +    @PresetData(PresetData.DataSet.ANONYMOUS_READONLY)
    +    @Test
    +    @Issue("SECURITY-360")
    +    public void ldap() throws Exception {
    +        // with a proper fix, this should fail with EXIT_CODE_REJECTED
    +        // otherwise this will fail with -1 exit code
    +        probe(Payload.Ldap, PayloadCaller.EXIT_CODE_REJECTED);
    +    }
    +
         private void probe(Payload payload, int expectedResultCode) throws Exception {
             File file = File.createTempFile("security-218", payload + "-payload");
             File moved = new File(file.getAbsolutePath() + "-moved");
    
  • test/src/test/java/jenkins/security/security218/Payload.java+4 3 modified
    @@ -24,7 +24,6 @@
     package jenkins.security.security218;
     
     import jenkins.security.security218.ysoserial.payloads.*;
    -import net.sf.json.JSON;
     
     
     /**
    @@ -46,8 +45,10 @@ public enum Payload {
         JRMPListener(JRMPListener.class),
         JSON1(JSON1.class),
         Spring1(Spring1.class),
    -    Spring2(Spring2.class);
    -    
    +    Spring2(Spring2.class),
    +    Ldap(Ldap.class),
    +    ;
    +
         private final Class<? extends ObjectPayload> payloadClass;
         
         private Payload(Class<? extends ObjectPayload> payloadClass) {
    
  • test/src/test/java/jenkins/security/security218/ysoserial/payloads/Ldap.java+24 0 added
    @@ -0,0 +1,24 @@
    +package jenkins.security.security218.ysoserial.payloads;
    +
    +import jenkins.security.security218.ysoserial.util.PayloadRunner;
    +
    +import java.lang.reflect.Constructor;
    +
    +/**
    + * @author Kohsuke Kawaguchi
    + */
    +public class Ldap extends PayloadRunner implements ObjectPayload<Object> {
    +
    +	public Object getObject(final String command) throws Exception {
    +	    // this is not a fully exploit, so we cannot honor the command,
    +        // but we want to check that we are blocking LdapAttribute
    +        Class<?> c = Class.forName("com.sun.jndi.ldap.LdapAttribute");
    +        Constructor<?> ctr = c.getDeclaredConstructor(String.class);
    +        ctr.setAccessible(true);
    +        return ctr.newInstance("foo");
    +	}
    +
    +	public static void main(final String[] args) throws Exception {
    +		PayloadRunner.run(Ldap.class, args);
    +	}
    +}
    
d84d9a2ad382

Preparing the integration commit for Nov 16th release

https://github.com/jenkinsci/jenkinsKohsuke KawaguchiNov 12, 2016via ghsa
4 files changed · +38 4
  • pom.xml+1 1 modified
    @@ -179,7 +179,7 @@ THE SOFTWARE.
           <dependency>
             <groupId>org.jenkins-ci.main</groupId>
             <artifactId>remoting</artifactId>
    -        <version>2.53.3</version>
    +        <version>2.53.4-20161112.024902-1</version>
           </dependency>
     
           <dependency>
    
  • test/src/test/java/jenkins/security/Security218CliTest.java+9 0 modified
    @@ -161,6 +161,15 @@ public void probeSpring2() throws Exception {
             probe(Payload.Spring2, -1);
         }
         
    +    @PresetData(PresetData.DataSet.ANONYMOUS_READONLY)
    +    @Test
    +    @Issue("SECURITY-360")
    +    public void ldap() throws Exception {
    +        // with a proper fix, this should fail with EXIT_CODE_REJECTED
    +        // otherwise this will fail with -1 exit code
    +        probe(Payload.Ldap, PayloadCaller.EXIT_CODE_REJECTED);
    +    }
    +
         private void probe(Payload payload, int expectedResultCode) throws Exception {
             File file = File.createTempFile("security-218", payload + "-payload");
             File moved = new File(file.getAbsolutePath() + "-moved");
    
  • test/src/test/java/jenkins/security/security218/Payload.java+4 3 modified
    @@ -24,7 +24,6 @@
     package jenkins.security.security218;
     
     import jenkins.security.security218.ysoserial.payloads.*;
    -import net.sf.json.JSON;
     
     
     /**
    @@ -46,8 +45,10 @@ public enum Payload {
         JRMPListener(JRMPListener.class),
         JSON1(JSON1.class),
         Spring1(Spring1.class),
    -    Spring2(Spring2.class);
    -    
    +    Spring2(Spring2.class),
    +    Ldap(Ldap.class),
    +    ;
    +
         private final Class<? extends ObjectPayload> payloadClass;
         
         private Payload(Class<? extends ObjectPayload> payloadClass) {
    
  • test/src/test/java/jenkins/security/security218/ysoserial/payloads/Ldap.java+24 0 added
    @@ -0,0 +1,24 @@
    +package jenkins.security.security218.ysoserial.payloads;
    +
    +import jenkins.security.security218.ysoserial.util.PayloadRunner;
    +
    +import java.lang.reflect.Constructor;
    +
    +/**
    + * @author Kohsuke Kawaguchi
    + */
    +public class Ldap extends PayloadRunner implements ObjectPayload<Object> {
    +
    +	public Object getObject(final String command) throws Exception {
    +	    // this is not a fully exploit, so we cannot honor the command,
    +        // but we want to check that we are blocking LdapAttribute
    +        Class<?> c = Class.forName("com.sun.jndi.ldap.LdapAttribute");
    +        Constructor<?> ctr = c.getDeclaredConstructor(String.class);
    +        ctr.setAccessible(true);
    +        return ctr.newInstance("foo");
    +	}
    +
    +	public static void main(final String[] args) throws Exception {
    +		PayloadRunner.run(Ldap.class, args);
    +	}
    +}
    
6078dd7aa097

[SECURITY-360] integration test

https://github.com/jenkinsci/jenkinsKohsuke KawaguchiNov 12, 2016via ghsa
4 files changed · +38 4
  • pom.xml+1 1 modified
    @@ -179,7 +179,7 @@ THE SOFTWARE.
           <dependency>
             <groupId>org.jenkins-ci.main</groupId>
             <artifactId>remoting</artifactId>
    -        <version>2.53.3-20160211.162333-3</version>
    +        <version>2.53.2</version>
           </dependency>
     
           <dependency>
    
  • test/src/test/java/jenkins/security/Security218CliTest.java+9 0 modified
    @@ -161,6 +161,15 @@ public void probeSpring2() throws Exception {
             probe(Payload.Spring2, -1);
         }
         
    +    @PresetData(PresetData.DataSet.ANONYMOUS_READONLY)
    +    @Test
    +    @Issue("SECURITY-360")
    +    public void ldap() throws Exception {
    +        // with a proper fix, this should fail with EXIT_CODE_REJECTED
    +        // otherwise this will fail with -1 exit code
    +        probe(Payload.Ldap, PayloadCaller.EXIT_CODE_REJECTED);
    +    }
    +
         private void probe(Payload payload, int expectedResultCode) throws Exception {
             File file = File.createTempFile("security-218", payload + "-payload");
             File moved = new File(file.getAbsolutePath() + "-moved");
    
  • test/src/test/java/jenkins/security/security218/Payload.java+4 3 modified
    @@ -24,7 +24,6 @@
     package jenkins.security.security218;
     
     import jenkins.security.security218.ysoserial.payloads.*;
    -import net.sf.json.JSON;
     
     
     /**
    @@ -46,8 +45,10 @@ public enum Payload {
         JRMPListener(JRMPListener.class),
         JSON1(JSON1.class),
         Spring1(Spring1.class),
    -    Spring2(Spring2.class);
    -    
    +    Spring2(Spring2.class),
    +    Ldap(Ldap.class),
    +    ;
    +
         private final Class<? extends ObjectPayload> payloadClass;
         
         private Payload(Class<? extends ObjectPayload> payloadClass) {
    
  • test/src/test/java/jenkins/security/security218/ysoserial/payloads/Ldap.java+24 0 added
    @@ -0,0 +1,24 @@
    +package jenkins.security.security218.ysoserial.payloads;
    +
    +import jenkins.security.security218.ysoserial.util.PayloadRunner;
    +
    +import java.lang.reflect.Constructor;
    +
    +/**
    + * @author Kohsuke Kawaguchi
    + */
    +public class Ldap extends PayloadRunner implements ObjectPayload<Object> {
    +
    +	public Object getObject(final String command) throws Exception {
    +	    // this is not a fully exploit, so we cannot honor the command,
    +        // but we want to check that we are blocking LdapAttribute
    +        Class<?> c = Class.forName("com.sun.jndi.ldap.LdapAttribute");
    +        Constructor<?> ctr = c.getDeclaredConstructor(String.class);
    +        ctr.setAccessible(true);
    +        return ctr.newInstance("foo");
    +	}
    +
    +	public static void main(final String[] args) throws Exception {
    +		PayloadRunner.run(Ldap.class, args);
    +	}
    +}
    
f574224cae5f

Merge pull request #71 from jenkinsci-cert/SECURITY-360

https://github.com/jenkinsci/jenkinsKohsuke KawaguchiNov 12, 2016via ghsa
6 files changed · +86 5
  • core/src/main/java/hudson/cli/CLIAction.java+1 2 modified
    @@ -62,12 +62,11 @@ public String getIconFileName() {
         }
     
         public String getDisplayName() {
    -
             return "Jenkins CLI";
         }
     
         public String getUrlName() {
    -        return "cli";
    +        return jenkins.CLI.DISABLED ? null : "cli";
         }
     
         public void doCommand(StaplerRequest req, StaplerResponse rsp) throws ServletException, IOException {
    
  • core/src/main/java/hudson/cli/CliProtocol2.java+1 1 modified
    @@ -24,7 +24,7 @@
     public class CliProtocol2 extends CliProtocol {
         @Override
         public String getName() {
    -        return "CLI2-connect";
    +        return jenkins.CLI.DISABLED ? null : "CLI2-connect";
         }
     
         @Override
    
  • core/src/main/java/hudson/cli/CliProtocol.java+1 1 modified
    @@ -32,7 +32,7 @@ public class CliProtocol extends AgentProtocol {
     
         @Override
         public String getName() {
    -        return "CLI-connect";
    +        return jenkins.CLI.DISABLED ? null : "CLI-connect";
         }
     
         @Override
    
  • core/src/main/java/jenkins/CLI.java+17 0 added
    @@ -0,0 +1,17 @@
    +package jenkins;
    +
    +import org.kohsuke.accmod.Restricted;
    +import org.kohsuke.accmod.restrictions.NoExternalUse;
    +
    +/**
    + * Kill switch to disable the entire Jenkins CLI system.
    + *
    + * Marked as no external use because the CLI subsystem is nearing EOL.
    + *
    + * @author Kohsuke Kawaguchi
    + */
    +@Restricted(NoExternalUse.class)
    +public class CLI {
    +    // non-final to allow setting from $JENKINS_HOME/init.groovy.d
    +    public static boolean DISABLED = Boolean.getBoolean(CLI.class.getName()+".disabled");
    +}
    
  • pom.xml+1 1 modified
    @@ -179,7 +179,7 @@ THE SOFTWARE.
           <dependency>
             <groupId>org.jenkins-ci.main</groupId>
             <artifactId>remoting</artifactId>
    -        <version>2.53.3-20160211.162333-3</version>
    +        <version>2.53.3</version>
           </dependency>
     
           <dependency>
    
  • test/src/test/java/jenkins/CLITest.java+65 0 added
    @@ -0,0 +1,65 @@
    +package jenkins;
    +
    +import hudson.cli.FullDuplexHttpStream;
    +import hudson.model.Computer;
    +import hudson.model.Failure;
    +import hudson.remoting.Channel;
    +import org.junit.Rule;
    +import org.junit.Test;
    +import org.jvnet.hudson.test.JenkinsRule;
    +
    +import java.io.FileNotFoundException;
    +import java.net.URL;
    +
    +import static org.junit.Assert.*;
    +
    +/**
    + * @author Kohsuke Kawaguchi
    + */
    +public class CLITest {
    +    @Rule
    +    public JenkinsRule j = new JenkinsRule();
    +
    +    /**
    +     * Checks if the kill switch works correctly
    +     */
    +    @Test
    +    public void killSwitch() throws Exception {
    +        // this should succeed, as a control case
    +        makeHttpCall();
    +        makeJnlpCall();
    +
    +        CLI.DISABLED = true;
    +        try {
    +            try {
    +                makeHttpCall();
    +                fail("Should have been rejected");
    +            } catch (FileNotFoundException e) {
    +                // attempt to make a call should fail
    +            }
    +            try {
    +                makeJnlpCall();
    +                fail("Should have been rejected");
    +            } catch (Exception e) {
    +                // attempt to make a call should fail
    +                e.printStackTrace();
    +
    +                // the current expected failure mode is EOFException, though we don't really care how it fails
    +            }
    +        } finally {
    +            CLI.DISABLED = false;
    +        }
    +    }
    +
    +    private void makeHttpCall() throws Exception {
    +        FullDuplexHttpStream con = new FullDuplexHttpStream(new URL(j.getURL(), "cli"));
    +        Channel ch = new Channel("test connection", Computer.threadPoolForRemoting, con.getInputStream(), con.getOutputStream());
    +        ch.close();
    +    }
    +
    +    private void makeJnlpCall() throws Exception {
    +        int r = hudson.cli.CLI._main(new String[]{"-s",j.getURL().toString(), "version"});
    +        if (r!=0)
    +            throw new Failure("CLI failed");
    +    }
    +}
    
fde9c42fe05a

[SECURITY-360] introduce a system switch to kill CLI

https://github.com/jenkinsci/jenkinsKohsuke KawaguchiNov 11, 2016via ghsa
5 files changed · +85 4
  • core/src/main/java/hudson/cli/CLIAction.java+1 2 modified
    @@ -62,12 +62,11 @@ public String getIconFileName() {
         }
     
         public String getDisplayName() {
    -
             return "Jenkins CLI";
         }
     
         public String getUrlName() {
    -        return "cli";
    +        return jenkins.CLI.DISABLED ? null : "cli";
         }
     
         public void doCommand(StaplerRequest req, StaplerResponse rsp) throws ServletException, IOException {
    
  • core/src/main/java/hudson/cli/CliProtocol2.java+1 1 modified
    @@ -24,7 +24,7 @@
     public class CliProtocol2 extends CliProtocol {
         @Override
         public String getName() {
    -        return "CLI2-connect";
    +        return jenkins.CLI.DISABLED ? null : "CLI2-connect";
         }
     
         @Override
    
  • core/src/main/java/hudson/cli/CliProtocol.java+1 1 modified
    @@ -32,7 +32,7 @@ public class CliProtocol extends AgentProtocol {
     
         @Override
         public String getName() {
    -        return "CLI-connect";
    +        return jenkins.CLI.DISABLED ? null : "CLI-connect";
         }
     
         @Override
    
  • core/src/main/java/jenkins/CLI.java+17 0 added
    @@ -0,0 +1,17 @@
    +package jenkins;
    +
    +import org.kohsuke.accmod.Restricted;
    +import org.kohsuke.accmod.restrictions.NoExternalUse;
    +
    +/**
    + * Kill switch to disable the entire Jenkins CLI system.
    + *
    + * Marked as no external use because the CLI subsystem is nearing EOL.
    + *
    + * @author Kohsuke Kawaguchi
    + */
    +@Restricted(NoExternalUse.class)
    +public class CLI {
    +    // non-final to allow setting from $JENKINS_HOME/init.groovy.d
    +    public static boolean DISABLED = Boolean.getBoolean(CLI.class.getName()+".disabled");
    +}
    
  • test/src/test/java/jenkins/CLITest.java+65 0 added
    @@ -0,0 +1,65 @@
    +package jenkins;
    +
    +import hudson.cli.FullDuplexHttpStream;
    +import hudson.model.Computer;
    +import hudson.model.Failure;
    +import hudson.remoting.Channel;
    +import org.junit.Rule;
    +import org.junit.Test;
    +import org.jvnet.hudson.test.JenkinsRule;
    +
    +import java.io.FileNotFoundException;
    +import java.net.URL;
    +
    +import static org.junit.Assert.*;
    +
    +/**
    + * @author Kohsuke Kawaguchi
    + */
    +public class CLITest {
    +    @Rule
    +    public JenkinsRule j = new JenkinsRule();
    +
    +    /**
    +     * Checks if the kill switch works correctly
    +     */
    +    @Test
    +    public void killSwitch() throws Exception {
    +        // this should succeed, as a control case
    +        makeHttpCall();
    +        makeJnlpCall();
    +
    +        CLI.DISABLED = true;
    +        try {
    +            try {
    +                makeHttpCall();
    +                fail("Should have been rejected");
    +            } catch (FileNotFoundException e) {
    +                // attempt to make a call should fail
    +            }
    +            try {
    +                makeJnlpCall();
    +                fail("Should have been rejected");
    +            } catch (Exception e) {
    +                // attempt to make a call should fail
    +                e.printStackTrace();
    +
    +                // the current expected failure mode is EOFException, though we don't really care how it fails
    +            }
    +        } finally {
    +            CLI.DISABLED = false;
    +        }
    +    }
    +
    +    private void makeHttpCall() throws Exception {
    +        FullDuplexHttpStream con = new FullDuplexHttpStream(new URL(j.getURL(), "cli"));
    +        Channel ch = new Channel("test connection", Computer.threadPoolForRemoting, con.getInputStream(), con.getOutputStream());
    +        ch.close();
    +    }
    +
    +    private void makeJnlpCall() throws Exception {
    +        int r = hudson.cli.CLI._main(new String[]{"-s",j.getURL().toString(), "version"});
    +        if (r!=0)
    +            throw new Failure("CLI failed");
    +    }
    +}
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

21

News mentions

0

No linked articles in our index yet.