├── .gitignore ├── README.md ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | gs 3 | logs 4 | *.log 5 | npm-debug.log* 6 | 7 | # Runtime data 8 | pids 9 | *.pid 10 | *.seed 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 19 | .grunt 20 | 21 | # node-waf configuration 22 | .lock-wscript 23 | 24 | # Compiled binary addons (http://nodejs.org/api/addons.html) 25 | build/Release 26 | 27 | # Dependency directories 28 | node_modules 29 | jspm_packages 30 | 31 | # Optional npm cache directory 32 | .npm 33 | 34 | # Optional REPL history 35 | .node_repl_history 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## CSRecon - Censys and Shodan Reconnasiance Tool 2 | 3 | _Censys + Shodan = A Good Time :)_ 4 | 5 | [Shodan](https://www.shodan.io/) and [Censys](https://censys.io/) are two services that are known to provide a wealth of information about a specific target. This is a useful passive reconnaissance tool that leverages both of their APIs to grab useful network-related information about a target. Of course both of these APIs are capable of much more, however this is a fairly specific use case. As of now it retrieves the following without ever touching the actual network: 6 | 7 | - IP addresses that were found to have an association with target 8 | - open ports and protocols per IP (Saves some nmap time) 9 | - os detection (if possible) 10 | - geolocation of each IP 11 | - hostnames and domains associated with IP 12 | - related ISP 13 | - banner grabbing (if possible) 14 | - Hosting (Rackspace? Amazon?) 15 | 16 | It's pretty useful because all of this information can be discovered, in about 15 seconds, by simply providing the target/organization name. 17 | 18 | ### Prerequisites 19 | It should work on any Linux/Unix/OSX platform with [node.js](https://nodejs.org/) and [npm](https://www.npmjs.com/) installed. 20 | 21 | Also, you'll need to **get API keys from both Censys and Shodan.** Include these into the following appropriate fields. 22 | 23 | ``` 24 | /* inside censysSearchIpv4() function */ 25 | username: "", 26 | password: "", 27 | 28 | /* inside shodan() function */ 29 | query: {key: ""} 30 | ``` 31 | 32 | ### Usage 33 | Clone this repository && cd into project directory 34 | ``` 35 | git clone https://github.com/markclayton/csrecon 36 | cd recon 37 | ``` 38 | Install dependency packages 39 | ``` 40 | npm install 41 | ``` 42 | CSRecon takes one parameter, which is the target name. It should be the same value you would use via the Censys website. It's often a good idea to try it out there first to see the results you would initially get. Run the following command: 43 | ``` 44 | node . [target-name] 45 | ``` 46 | or 47 | ``` 48 | node index.js [target-name] | tee output.txt 49 | ``` 50 | It's recommended this be piped to a file (shown above) to analyze the details. Also, since this tool makes several API request to Shodan, you may bounce against the API limits and get some error codes (502 Bad Gateway). If this happens give it a few minutes and try again. 51 | 52 | ### Additional 53 | - There is a function called censysViewSearch() provided that will pull more detailed information that Censys gathered about each IP. You can uncomment and work into the code if you'd like. 54 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var rest = require('restler') 2 | var util = require('util') 3 | 4 | function censysSearchIpv4(query, cb) { 5 | rest.post('https://www.censys.io/api/v1/search/ipv4', { 6 | username:"", 7 | password:"", 8 | data: JSON.stringify({ 9 | query: query 10 | }), 11 | }).on('complete', function(data, response) { 12 | if (response.statusCode !== 200) { 13 | console.log(response.statusCode); 14 | } else { 15 | cb(data) 16 | } 17 | }); 18 | } 19 | 20 | /* 21 | Performs the Censys View API call on given query, pulls the data censys has on the host. 22 | Right now it's not in use however it can be easily included by modifying the code a bit :) 23 | More information can be found here: https://censys.io/api/v1/docs/view 24 | */ 25 | /* 26 | function censysViewIpv4(query, cb){ 27 | rest.get('https://www.censys.io/api/v1/view/ipv4/' + query, { 28 | username:"", 29 | password:"", 30 | // data: JSON.stringify({query: query}), 31 | }).on('complete', function(data, response){ 32 | if(response.statusCode !== 200){ 33 | console.log('API Error', response.statusCode); 34 | }else{ 35 | cb(data) 36 | } 37 | }); 38 | }*/ 39 | 40 | function shodan(input, cb){ 41 | rest.get('https://api.shodan.io/shodan/host/' + input, { 42 | query: {key: ""} 43 | }).on('complete', function(data, response){ 44 | if(response.statusCode !== 200){ 45 | var err = "Shodan API Error (Status Code): " + response.statusCode 46 | cb(err) 47 | }else{ 48 | cb(null, data) 49 | } 50 | }) 51 | } 52 | 53 | function viewShodanJSON(result) { 54 | result.forEach(function(item) { 55 | if(item){ 56 | console.log("\n[*] *************************************"); 57 | console.log("[*] Shodan Result Found: %s", item.data[0].ip_str); 58 | console.log("[*] *************************************"); 59 | console.log(util.inspect(item, false, null)); 60 | } 61 | }) 62 | } 63 | 64 | function viewCensys(data) { 65 | console.log("--------------------------------------"); 66 | console.log("*** Censys found the associated IP ***"); 67 | console.log("--------------------------------------\n"); 68 | data.results.forEach(function(item) { 69 | console.log("[*] IP: %s \t Ports: %s", item.ip, item.protocols); 70 | }) 71 | } 72 | 73 | /* 74 | This makes a censys search ipv4 api call using the given query, and filters only the IP of each 75 | finding to an array. Afterwards, each IP is in turn used as the parameter for the shodan API to pull 76 | it's information. 77 | */ 78 | var query = process.argv[2] 79 | censysSearchIpv4(query, function(data) { 80 | viewCensys(data); 81 | var ipArray = data.results.map(function(item) { 82 | return item.ip 83 | }) 84 | var shodanResult = [] 85 | var itemsProcessed = 0 86 | console.log("--------------------------------------"); 87 | console.log("*** HANG ON: Bouncing each IP against Shodan ***"); 88 | console.log("--------------------------------------"); 89 | console.log("As of now the data is JSON, we will leave it up to you to sort through.\nIt's recommended this output is piped to a file for analysis.\n"); 90 | ipArray.forEach(function(ip) { 91 | shodan(ip, function(err, result) { 92 | shodanResult.push(result) 93 | itemsProcessed++ 94 | if (itemsProcessed === ipArray.length) { 95 | var shodanNoNull = shodanResult.filter(function(item) { 96 | return JSON.stringify(item) !== '{"matches":[],"facets":{"port":[]},"total":0}' 97 | }) 98 | viewShodanJSON(shodanNoNull) 99 | } 100 | }) 101 | }) 102 | }) 103 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "csrecon", 3 | "version": "1.0.0", 4 | "description": "Open source tool that uses censys and shodan for passive recon. ", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/markclayton/csrecon.git" 12 | }, 13 | "keywords": [ 14 | "passive", 15 | "recon", 16 | "censys", 17 | "shodan" 18 | ], 19 | "author": "Mark Clayton", 20 | "license": "ISC", 21 | "bugs": { 22 | "url": "https://github.com/markclayton/csrecon/issues" 23 | }, 24 | "homepage": "https://github.com/markclayton/csrecon#readme", 25 | "dependencies": { 26 | "async": "^1.5.2", 27 | "restler": "^3.4.0", 28 | "util": "^0.10.3" 29 | } 30 | } 31 | --------------------------------------------------------------------------------