Finding Hosts Using SSL Certificate Organization And Censys

Finding hosts or domain names associated with a company where the domain name does not include the name of the company can sometimes be difficult. There are common ways to do it such as ASN or scope information (e.g. bug bounty ToE or IP block).

One technique that I use (and I am guessing others do as well) is through an Organization field in a SSL Certificate that is shared by multiple domains. For example, a certificate from https://www.facebook.com and https://parse.com are signed by the same organization.

This is an easy example. Parse is listed on the Facebook Mergers or Acquisitions page (https://en.wikipedia.org/wiki/List_of_mergers_and_acquisitions_by_Facebook) and the FB bug bounty terms (https://www.facebook.com/whitehat).

However, consider a more complex example like “HackerOne: Subdomain takeover on https://fastly.sc-cdn.net/”.

First, if you aren’t familiar with sub-domain take over this and this are awesome.

In the case above, the subdomain fastly.sc-cdn.net is owned by Snapchat which is not obvious from the domain name. Personally, I do not know how ebrietas found that domain. DNS Bruteforcing would work. It could also be done by shared SSL Certificates on the Organization name.

A few months back I wrote a script that uses the Censys API to look for domains with the same Organization field in the SSL certificate.

For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ruby censys_cert_search.rb 'Snapchat Inc.'


Page: 1
{"parsed.extensions.subject_alt_name.dns_names"=>["se.snap-dev.net"], "parsed.subject.common_name"=>["se.snap-dev.net"]}
|+| Checking se.snap-dev.net
se.snap-dev.net.  300 IN  A   107.178.248.183
se.snap-dev.net.  300 IN  A   107.178.248.183
|+| Checking se.snap-dev.net
se.snap-dev.net.  300 IN  A   107.178.248.183
se.snap-dev.net.  300 IN  A   107.178.248.183
{"parsed.extensions.subject_alt_name.dns_names"=>["spectre.sc-corp.net"], "parsed.subject.common_name"=>["spectre.sc-corp.net"]}
|+| Checking spectre.sc-corp.net
spectre.sc-corp.net.  300 IN  A   130.211.14.254
spectre.sc-corp.net.  300 IN  A   130.211.14.254
|+| Checking spectre.sc-corp.net
spectre.sc-corp.net.  300 IN  A   130.211.14.254
spectre.sc-corp.net.  300 IN  A   130.211.14.254
...

If you checkout the code, the script is:

1. Using the Censys Certificate API to search on the Organization string matching ‘Snapchat Inc.’ (i.e. O=Snapchat Inc.*)

2. Parsing out the Common Name and Alternate Names from the SSL Certificate response

3. Performing a DNS lookup for each name found

You can also run the script to skip over common names that could’ve been easily found in other ways (e.g. dev.snapchat.com). This focuses the effort on hard to find systems. Adding a third argument skips DNS lookup.

1
2
3
4
5
6
7
8
9
10
11
12
13
ruby censys_cert_search.rb 'Snapchat Inc.' '*snapchat.com' false

Page: 1
{"parsed.extensions.subject_alt_name.dns_names"=>["se.snap-dev.net"], "parsed.subject.common_name"=>["se.snap-dev.net"]}
{"parsed.extensions.subject_alt_name.dns_names"=>["spectre.sc-corp.net"], "parsed.subject.common_name"=>["spectre.sc-corp.net"]}
{"parsed.extensions.subject_alt_name.dns_names"=>["*.targeting.snapads.com", "targeting.snapads.com"], "parsed.subject.common_name"=>["*.targeting.snapads.com"]}
{"parsed.extensions.subject_alt_name.dns_names"=>["*.snapchat.com", "snapchat.com"], "parsed.subject.common_name"=>["*.snapchat.com"]}
{"parsed.extensions.subject_alt_name.dns_names"=>["rest-escluster.hydrasearch.sc-prod.net"], "parsed.subject.common_name"=>["rest-escluster.hydrasearch.sc-prod.net"]}
{"parsed.extensions.subject_alt_name.dns_names"=>["*.snapchat.com", "snapchat.com"], "parsed.subject.common_name"=>["*.snapchat.com"]}
{"parsed.extensions.subject_alt_name.dns_names"=>["restfulgit.sc-corp.net"], "parsed.subject.common_name"=>["restfulgit.sc-corp.net"]}
{"parsed.extensions.subject_alt_name.dns_names"=>["attribution.snapads.com"], "parsed.subject.common_name"=>["attribution.snapads.com"]}
{"parsed.extensions.subject_alt_name.dns_names"=>["*.snapchat.com", "snapchat.com", "mail.support.snapchat.com"], "parsed.subject.common_name"=>["*.snapchat.com"]}
....

As you can see not perfect but I’ve found it really useful in the past. It was hack for something else and I’ll update as time permits.