Secure your Jenkins instance or hackers will force you to! (Snapchat’s $5,000 Vulnerability)

After presenting “Doing Recon Like a Boss” at levelUp and releasing a blog post on HackerOne about the same topic, I decided to start looking for a few vulnerabilities on public programs to see if that methodology is still applicable to public programs. As a part of this I decided to look at Slack and Snapchat’s bug bounty programs and preforming my recon exactly as described in the talk.

Step #1 – Brute forcing for subdomains
Brute forcing for sub domains is typically a good place to start for a big bug bounty program, but unfortunately for me the subdomains I had found weren’t really interesting and wanted to find something more “fun”. Moving on to phase 2.

Step #2 – Amazon Web Services
Amazon would’ve been a great place to start, but from the looks of it Snapchat is heavily dependent on Google and they have mentioned they host their app on google in their HackerOne bug bounty program. Let’s not waste anymore time on s3 buckets and see what else is out there.

Step #3  – Snapchat’s disclosed reports on HackerOne
As a part of my recon, I typically like to look for known or disclosed vulnerabilities. I took a quick glance at their Hacktivity and found the following:
– render.bitstrips.com
– blog.snapchat.com
– accounts.snapchat.com
– fastly.sc-cdn.net
– sc-corp.net (Thanks, Shubs)

“sc-cdn.net” and “sc-corp.net” both caught my attention. First reaction was to do a subdomain brute force, but who are we kidding.. These are corp/cdn domains and more than likely most of the juicy sub domains would more than likely be in a unique pattern. Now the question is how do I find them?

Step #4: Censys/Shodan
A great place to start is usually looking for certificates on Censys.io. My usual go-to query on censys looks similar to something like this: 443.https.tls.certificate.parsed.extensions.subject_alt_name.dns_names:domain.com
That was enough to find some interesting subdomains that I wouldn’t have been able to find by brute forcing. Going through the results, there was a subdomain: REDACTED-jenkins-Environment.sc-corp.net that pointed the user to login in order to see what’s on that site. At this point, I wondered if there’s a prod environment, there’s got to be more so let’s look for them. To speed up my process I used script that would look for different permutations of REDACTED-jenkins-$env.sc-corp.net with the following list: “dev, alpha, stage, prod, beta, local, test”. As expected a few of those returned with 302 as their response code, which hinted that they may be behind a login.

Step #5: WTF to do from here?
My initial thought was to obviously try and go to the prod instance and try to login, however that didn’t work (Thanks, preben_ve). So let’s move down the list and try the same method on the other instances. Now this is where all the fun began. Lucky for me, one of the instances I had found allowed me to login to the Jenkins instance using a gmail account. Now that I was authenticated to their Jenkins instance, I thought it may have minimal permissions that didn’t allow me to do much, let alone allow me to access the “Script Console”. At this point I ran a script that allowed me to read a file on the server and immediately stopped further testing and reported it to the Snapchat team. There’s no need to execute more scripts to demonstrate impact since I could already read any file on the system. In order to demonstrate RCE, I included the script that allows command execution and asked them to try it at their own risk. We’ll talk about these scripts later.

Step #6: Exploiting Jenkins
I didn’t just write this blog to talk about my report to Snapchat, since most of this information could’ve been guessed by reading my limited public disclosure on HackerOne and doing some basic recon. I wrote this blog post to dive into exploiting Jenkins a bit more and discuss if it’s really worth $20,000. To do so I am using my own Jenkins instance to demonstrate different attack scenarios (Screenshots are not related to my report to Snapchat):

Example #1: Known vulnerabilities (Just to highlight a few)
CVE-2016-9299 – Jenkins ‘Java Deserialization’ Remote Code Execution Vulnerability.
CVE-2015-8103 – Jenkins CLI – RMI Java Deserialization (Exploit)

Example #2: Access to build information:
Usually having access to builds on Jenkins could possibly give you access to credentials, api_keys/secrets, and obviously the source code:

Example #3: Plugins
Jenkins allows you to setup different plugins such as Github OAuth where you are able to allow users to login using your organization which could expose your Github token:

which can be used to access more data using the Github API. For example: https://api.github.com/orgs/ORG_NAME/repos?access_token=XXXXX

Example #4: Groovy Scripts
As I mentioned before the script console allows you to read files using one line of code:

You can also execute a command on the server by doing the following:

def sout = new StringBuilder(), serr = new StringBuilder()
def proc = 'ls /etc/'.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println "out> $sout err> $serr"

Key takeaways: 
1. Jenkins allows you to have different user permissions. That means just because you have authenticated to the Jenkins instance, it doesn’t guarantee you with Remote Command Execution.
2. Don’t let it scare you away if it requires authentication via Github or Google OAuth.
3. You may have limited access (no script, build info, etc), but you may be able to the list of users under “People”. Which may grant you access to the Jenkins instance by brute forcing for credentials (I wouldn’t go to that extreme).
4. Typically Jenkins is used for deployment, so look for IPs, hostnames, etc. If you do compromise the Jenkins and need to go a step further (avoid this in bug bounty, you don’t need to and will be against most program rules), but it’s good to note that the Jenkins server most likely has access to a lot of production or internal servers. Look for private keys and hosts on the server for pivoting
5. Don’t spam programs with “publicly accessible Jenkins” reports unless you can possibly exploit one or more of the above examples.
6. Snapchat removed the instance immediately and rewarded me shortly. They were also kind enough to let me write about this!

Thanks for reading and happy hacking!