@@ -36,6 +36,7 @@ def initialize(info = {})
3636 [
3737 OptString . new ( 'SHODAN_APIKEY' , [ true , 'The SHODAN API key' ] ) ,
3838 OptString . new ( 'QUERY' , [ true , 'Keywords you want to search for' ] ) ,
39+ OptString . new ( 'FACETS' , [ true , 'List of facets' ] ) ,
3940 OptString . new ( 'OUTFILE' , [ false , 'A filename to store the list of IPs' ] ) ,
4041 OptBool . new ( 'DATABASE' , [ false , 'Add search results to the database' , false ] ) ,
4142 OptInt . new ( 'MAXPAGE' , [ true , 'Max amount of pages to collect' , 1 ] ) ,
@@ -55,7 +56,7 @@ def initialize(info = {})
5556 end
5657
5758 # create our Shodan query function that performs the actual web request
58- def shodan_query ( apikey , query , page )
59+ def shodan_query ( apikey , query , facets , page )
5960 # send our query to Shodan
6061 res = send_request_cgi ( {
6162 'method' => 'GET' ,
@@ -66,6 +67,7 @@ def shodan_query(apikey, query, page)
6667 'vars_get' => {
6768 'key' => apikey ,
6869 'query' => query ,
70+ 'facets' => facets ,
6971 'page' => page . to_s
7072 }
7173 } )
@@ -117,12 +119,13 @@ def run
117119
118120 # create our Shodan request parameters
119121 query = datastore [ 'QUERY' ]
122+ facets = datastore [ 'FACETS' ]
120123 apikey = datastore [ 'SHODAN_APIKEY' ]
121124 maxpage = datastore [ 'MAXPAGE' ]
122125
123126 # results gets our results from shodan_query
124127 results = [ ]
125- results [ 0 ] = shodan_query ( apikey , query , 1 )
128+ results [ 0 ] = shodan_query ( apikey , query , facets , 1 )
126129
127130 if results [ 0 ] [ 'total' ] . nil? || results [ 0 ] [ 'total' ] == 0
128131 msg = "No results."
@@ -141,68 +144,87 @@ def run
141144 end
142145 maxpage = tpages if datastore [ 'MAXPAGE' ] > tpages
143146
144- # start printing out our query statistics
145- print_status ( "Total: #{ results [ 0 ] [ 'total' ] } on #{ tpages } " +
146- "pages. Showing: #{ maxpage } page(s)" )
147-
148- # If search results greater than 100, loop & get all results
149- print_status ( 'Collecting data, please wait...' )
150-
151- if results [ 0 ] [ 'total' ] > 100
152- page = 1
153- while page < maxpage
154- page_result = shodan_query ( apikey , query , page +1 )
155- if page_result [ 'matches' ] . nil?
156- next
147+ if facets
148+ facets_tbl = Rex ::Text ::Table . new (
149+ 'Header' => 'Facets' ,
150+ 'Indent' => 1 ,
151+ 'Columns' => [ 'Facet' , 'Name' , 'Count' ]
152+ )
153+ print_status ( "Total: #{ results [ 0 ] [ 'total' ] } on #{ tpages } " \
154+ 'pages. Showing facets' )
155+ facet = results [ 0 ] [ 'facets' ]
156+ facet . each do |name , list |
157+ list . each do |f |
158+ facets_tbl << [ name . to_s , ( f [ 'value' ] ) . to_s , ( f [ 'count' ] ) . to_s ]
157159 end
158- results [ page ] = page_result
159- page += 1
160160 end
161- end
162-
163- # Save the results to this table
164- tbl = Rex ::Text ::Table . new (
165- 'Header' => 'Search Results' ,
166- 'Indent' => 1 ,
167- 'Columns' => [ 'IP:Port' , 'City' , 'Country' , 'Hostname' ]
168- )
161+ else
162+ # start printing out our query statistics
163+ print_status ( "Total: #{ results [ 0 ] [ 'total' ] } on #{ tpages } " +
164+ "pages. Showing: #{ maxpage } page(s)" )
165+
166+ # If search results greater than 100, loop & get all results
167+ print_status ( 'Collecting data, please wait...' )
168+
169+ if results [ 0 ] [ 'total' ] > 100
170+ page = 1
171+ while page < maxpage
172+ page_result = shodan_query ( apikey , query , facets , page +1 )
173+ if page_result [ 'matches' ] . nil?
174+ next
175+ end
176+ results [ page ] = page_result
177+ page += 1
178+ end
179+ end
180+ # Save the results to this table
181+ tbl = Rex ::Text ::Table . new (
182+ 'Header' => 'Search Results' ,
183+ 'Indent' => 1 ,
184+ 'Columns' => [ 'IP:Port' , 'City' , 'Country' , 'Hostname' ]
185+ )
169186
170- # Organize results and put them into the table and database
171- regex = datastore [ 'REGEX' ] if datastore [ 'REGEX' ]
172- results . each do |page |
173- page [ 'matches' ] . each do |host |
174- city = host [ 'location' ] [ 'city' ] || 'N/A'
175- ip = host [ 'ip_str' ] || 'N/A'
176- port = host [ 'port' ] || ''
177- country = host [ 'location' ] [ 'country_name' ] || 'N/A'
178- hostname = host [ 'hostnames' ] [ 0 ]
179- data = host [ 'data' ]
180-
181- report_host ( :host => ip ,
182- :name => hostname ,
183- :comments => 'Added from Shodan' ,
184- :info => host [ 'info' ]
185- ) if datastore [ 'DATABASE' ]
186-
187- report_service ( :host => ip ,
188- :port => port ,
189- :info => 'Added from Shodan'
190- ) if datastore [ 'DATABASE' ]
191-
192- if ip =~ regex ||
193- city =~ regex ||
194- country =~ regex ||
195- hostname =~ regex ||
196- data =~ regex
197- # Unfortunately we cannot display the banner properly,
198- # because it messes with our output format
199- tbl << [ "#{ ip } :#{ port } " , city , country , hostname ]
187+ # Organize results and put them into the table and database
188+ regex = datastore [ 'REGEX' ] if datastore [ 'REGEX' ]
189+ results . each do |page |
190+ page [ 'matches' ] . each do |host |
191+ city = host [ 'location' ] [ 'city' ] || 'N/A'
192+ ip = host [ 'ip_str' ] || 'N/A'
193+ port = host [ 'port' ] || ''
194+ country = host [ 'location' ] [ 'country_name' ] || 'N/A'
195+ hostname = host [ 'hostnames' ] [ 0 ]
196+ data = host [ 'data' ]
197+
198+ report_host ( :host => ip ,
199+ :name => hostname ,
200+ :comments => 'Added from Shodan' ,
201+ :info => host [ 'info' ]
202+ ) if datastore [ 'DATABASE' ]
203+
204+ report_service ( :host => ip ,
205+ :port => port ,
206+ :info => 'Added from Shodan'
207+ ) if datastore [ 'DATABASE' ]
208+
209+ if ip =~ regex ||
210+ city =~ regex ||
211+ country =~ regex ||
212+ hostname =~ regex ||
213+ data =~ regex
214+ # Unfortunately we cannot display the banner properly,
215+ # because it messes with our output format
216+ tbl << [ "#{ ip } :#{ port } " , city , country , hostname ]
217+ end
200218 end
201219 end
220+ #Show data and maybe save it if needed
221+ print_line ( )
222+ print_line ( "#{ tbl } " )
223+ save_output ( tbl ) if datastore [ 'OUTFILE' ]
224+ end
225+ if datastore [ 'FACETS' ]
226+ print_line ( facets_tbl . to_s )
227+ save_output ( facets_tbl ) if datastore [ 'OUTFILE' ]
202228 end
203- #Show data and maybe save it if needed
204- print_line ( )
205- print_line ( "#{ tbl } " )
206- save_output ( tbl ) if datastore [ 'OUTFILE' ]
207229 end
208230end
0 commit comments