shodan 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. data/lib/shodan/api.rb +204 -203
  2. data/lib/shodan/version.rb +3 -3
  3. metadata +6 -6
@@ -1,203 +1,204 @@
1
- require 'rubygems'
2
- require 'cgi'
3
- require 'json'
4
- require 'net/http'
5
-
6
- module Shodan
7
-
8
- # The WebAPI class interfaces with the shodanhq.com/api
9
- # It currently supports 2 methods:
10
- # 1. search (query)
11
- # 2. host (ip)
12
- #
13
- # Author:: achillean (mailto:jmath at surtri.com)
14
- #
15
- # :title:Shodan::WebAPI
16
- class WebAPI
17
- attr_accessor :api_key
18
- attr_accessor :base_url
19
- attr_accessor :dataloss
20
- attr_accessor :exploitdb
21
- attr_accessor :msf
22
-
23
- def initialize(api_key)
24
- @api_key = api_key
25
- @base_url = "http://www.shodanhq.com/api/"
26
- @dataloss = DatalossDB.new(self)
27
- @exploitdb = ExploitDB.new(self)
28
- @msf = Msf.new(self)
29
- end
30
-
31
- # Internal method that sends out the HTTP request.
32
- # Expects a webservice function (ex. 'search') name and a hash of arguments.
33
- def request(func, args)
34
- # Convert the argument hash into a string
35
- args_string = args.map{|k, v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v)}"}.join("&")
36
-
37
- # Craft the final request URL
38
- url = "#{@base_url}#{func}?key=#{@api_key}&#{args_string}"
39
-
40
- # Send the request
41
- response = Net::HTTP.get_response(URI.parse(url))
42
-
43
- # Convert the JSON data into a native Ruby hash
44
- data = JSON.parse(response.body)
45
-
46
- # Raise an error if something went wrong
47
- if data.has_key? 'error'
48
- raise data['error']
49
- end
50
-
51
- return data
52
- end
53
-
54
- # Get all available information on an IP.
55
- #
56
- # Arguments:
57
- # ip - host IP (string)
58
- #
59
- # Returns a hash containing the host information
60
- def host(ip)
61
- return request('host', {:ip => ip})
62
- end
63
-
64
- # Perform a search on Shodan.
65
- #
66
- # Arguments:
67
- # query - search query; same format as the website (string)
68
- #
69
- # Returns a hash containing the search results
70
- def search(query)
71
- return request('search', {:q => query})
72
- end
73
- end
74
-
75
- # The DatalossDB class shouldn't be used independently,
76
- # as it depends on the WebAPI class.
77
- #
78
- # Author:: achillean (mailto:jmath at surtri.com)
79
- #
80
- # :title:Shodan::DatalossDB
81
- class DatalossDB
82
- attr_accessor :api
83
-
84
- def initialize(api)
85
- @api = api
86
- end
87
-
88
- # Search the Dataloss DB archive.
89
- #
90
- # Arguments:
91
- # name -- Name of the affected company/ organisation
92
- #
93
- # arrest -- whether the incident resulted in an arrest
94
- # breaches -- the type of breach that occurred (Hack, MissingLaptop etc.)
95
- # country -- country where the incident took place
96
- # ext -- whether an external, third party was affected
97
- # ext_names -- the name of the third party company that was affected
98
- # lawsuit -- whether the incident resulted in a lawsuit
99
- # records -- the number of records that were lost/ stolen
100
- # recovered -- whether the affected items were recovered
101
- # sub_types -- the sub-categorization of the affected company/ organization
102
- # source -- whether the incident occurred from inside or outside the organization
103
- # stocks -- stock symbol of the affected company
104
- # types -- the basic type of organization (government, business, educational)
105
- # uid -- unique ID for the incident
106
- def search(params={})
107
- return @api.request('datalossdb/search', params)
108
- end
109
-
110
- end
111
-
112
- # The ExploitDB class shouldn't be used independently,
113
- # as it depends on the WebAPI class.
114
- #
115
- # Author:: achillean (mailto:jmath at surtri.com)
116
- #
117
- # :title:Shodan::ExploitDB
118
- class ExploitDB
119
- attr_accessor :api
120
-
121
- def initialize(api)
122
- @api = api
123
- end
124
-
125
- # Download the exploit code from the ExploitDB archive.
126
- #
127
- # Arguments:
128
- # id -- ID of the ExploitDB entry
129
- #
130
- # Returns:
131
- # A hash with the following fields:
132
- # filename -- Name of the file
133
- # content-type -- Mimetype
134
- # data -- Contents of the file
135
- def download(id)
136
- return @api.request('exploitdb/download', {:id => "#{id}"})
137
- end
138
-
139
- # Search the ExploitDB archive.
140
- #
141
- # Arguments:
142
- # query -- Search terms
143
- #
144
- # Optional arguments:
145
- # author -- Name of the exploit submitter
146
- # platform -- Target platform (e.g. windows, linux, hardware etc.)
147
- # port -- Service port number
148
- # type -- Any, dos, local, papers, remote, shellcode and webapps
149
- #
150
- # Returns:
151
- # A dictionary with 2 main items: matches (list) and total (int).
152
- # Each item in 'matches' is a dictionary with the following elements:
153
- #
154
- # id
155
- # author
156
- # date
157
- # description
158
- # platform
159
- # port
160
- # type
161
- def search(query, params={})
162
- params[:q] = query
163
- return @api.request('exploitdb/search', params)
164
- end
165
-
166
- end
167
-
168
- # The Msf class shouldn't be used independently,
169
- # as it depends on the WebAPI class.
170
- #
171
- # Author:: achillean (mailto:jmath at surtri.com)
172
- #
173
- # :title:Shodan::Msf
174
- class Msf
175
- attr_accessor :api
176
-
177
- def initialize(api)
178
- @api = api
179
- end
180
-
181
- # Download a metasploit module given the fullname (id) of it.
182
- #
183
- # Arguments:
184
- # id -- fullname of the module (ex. auxiliary/admin/backupexec/dump)
185
- #
186
- # Returns:
187
- # A dictionary with the following fields:
188
- # # filename -- Name of the file
189
- # content-type -- Mimetype
190
- # data -- File content
191
- def download(id)
192
- return @api.request('msf/download', {:id => "#{id}"})
193
- end
194
-
195
- # Search for a metasploit module
196
- def search(query, params={})
197
- params[:q] = query
198
- return @api.request('msf/search', params)
199
- end
200
-
201
- end
202
-
203
- end
1
+ require 'rubygems'
2
+ require 'cgi'
3
+ require 'json'
4
+ require 'net/http'
5
+
6
+ module Shodan
7
+
8
+ # The WebAPI class interfaces with the shodanhq.com/api
9
+ # It currently supports 2 methods:
10
+ # 1. search (query)
11
+ # 2. host (ip)
12
+ #
13
+ # Author:: achillean (mailto:jmath at surtri.com)
14
+ #
15
+ # :title:Shodan::WebAPI
16
+ class WebAPI
17
+ attr_accessor :api_key
18
+ attr_accessor :base_url
19
+ attr_accessor :dataloss
20
+ attr_accessor :exploitdb
21
+ attr_accessor :msf
22
+
23
+ def initialize(api_key)
24
+ @api_key = api_key
25
+ @base_url = "http://www.shodanhq.com/api/"
26
+ @dataloss = DatalossDB.new(self)
27
+ @exploitdb = ExploitDB.new(self)
28
+ @msf = Msf.new(self)
29
+ end
30
+
31
+ # Internal method that sends out the HTTP request.
32
+ # Expects a webservice function (ex. 'search') name and a hash of arguments.
33
+ def request(func, args)
34
+ # Convert the argument hash into a string
35
+ args_string = args.map{|k, v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}"}.join("&")
36
+
37
+ # Craft the final request URL
38
+ url = "#{@base_url}#{func}?key=#{@api_key}&#{args_string}"
39
+
40
+ # Send the request
41
+ response = Net::HTTP.get_response(URI.parse(url))
42
+
43
+ # Convert the JSON data into a native Ruby hash
44
+ data = JSON.parse(response.body)
45
+
46
+ # Raise an error if something went wrong
47
+ if data.has_key? 'error'
48
+ raise data['error']
49
+ end
50
+
51
+ return data
52
+ end
53
+
54
+ # Get all available information on an IP.
55
+ #
56
+ # Arguments:
57
+ # ip - host IP (string)
58
+ #
59
+ # Returns a hash containing the host information
60
+ def host(ip)
61
+ return request('host', {:ip => ip})
62
+ end
63
+
64
+ # Perform a search on Shodan.
65
+ #
66
+ # Arguments:
67
+ # query - search query; same format as the website (string)
68
+ #
69
+ # Returns a hash containing the search results
70
+ def search(query, params={})
71
+ params[:q] = query
72
+ return request('search', params)
73
+ end
74
+ end
75
+
76
+ # The DatalossDB class shouldn't be used independently,
77
+ # as it depends on the WebAPI class.
78
+ #
79
+ # Author:: achillean (mailto:jmath at surtri.com)
80
+ #
81
+ # :title:Shodan::DatalossDB
82
+ class DatalossDB
83
+ attr_accessor :api
84
+
85
+ def initialize(api)
86
+ @api = api
87
+ end
88
+
89
+ # Search the Dataloss DB archive.
90
+ #
91
+ # Arguments:
92
+ # name -- Name of the affected company/ organisation
93
+ #
94
+ # arrest -- whether the incident resulted in an arrest
95
+ # breaches -- the type of breach that occurred (Hack, MissingLaptop etc.)
96
+ # country -- country where the incident took place
97
+ # ext -- whether an external, third party was affected
98
+ # ext_names -- the name of the third party company that was affected
99
+ # lawsuit -- whether the incident resulted in a lawsuit
100
+ # records -- the number of records that were lost/ stolen
101
+ # recovered -- whether the affected items were recovered
102
+ # sub_types -- the sub-categorization of the affected company/ organization
103
+ # source -- whether the incident occurred from inside or outside the organization
104
+ # stocks -- stock symbol of the affected company
105
+ # types -- the basic type of organization (government, business, educational)
106
+ # uid -- unique ID for the incident
107
+ def search(params={})
108
+ return @api.request('datalossdb/search', params)
109
+ end
110
+
111
+ end
112
+
113
+ # The ExploitDB class shouldn't be used independently,
114
+ # as it depends on the WebAPI class.
115
+ #
116
+ # Author:: achillean (mailto:jmath at surtri.com)
117
+ #
118
+ # :title:Shodan::ExploitDB
119
+ class ExploitDB
120
+ attr_accessor :api
121
+
122
+ def initialize(api)
123
+ @api = api
124
+ end
125
+
126
+ # Download the exploit code from the ExploitDB archive.
127
+ #
128
+ # Arguments:
129
+ # id -- ID of the ExploitDB entry
130
+ #
131
+ # Returns:
132
+ # A hash with the following fields:
133
+ # filename -- Name of the file
134
+ # content-type -- Mimetype
135
+ # data -- Contents of the file
136
+ def download(id)
137
+ return @api.request('exploitdb/download', {:id => "#{id}"})
138
+ end
139
+
140
+ # Search the ExploitDB archive.
141
+ #
142
+ # Arguments:
143
+ # query -- Search terms
144
+ #
145
+ # Optional arguments:
146
+ # author -- Name of the exploit submitter
147
+ # platform -- Target platform (e.g. windows, linux, hardware etc.)
148
+ # port -- Service port number
149
+ # type -- Any, dos, local, papers, remote, shellcode and webapps
150
+ #
151
+ # Returns:
152
+ # A dictionary with 2 main items: matches (list) and total (int).
153
+ # Each item in 'matches' is a dictionary with the following elements:
154
+ #
155
+ # id
156
+ # author
157
+ # date
158
+ # description
159
+ # platform
160
+ # port
161
+ # type
162
+ def search(query, params={})
163
+ params[:q] = query
164
+ return @api.request('exploitdb/search', params)
165
+ end
166
+
167
+ end
168
+
169
+ # The Msf class shouldn't be used independently,
170
+ # as it depends on the WebAPI class.
171
+ #
172
+ # Author:: achillean (mailto:jmath at surtri.com)
173
+ #
174
+ # :title:Shodan::Msf
175
+ class Msf
176
+ attr_accessor :api
177
+
178
+ def initialize(api)
179
+ @api = api
180
+ end
181
+
182
+ # Download a metasploit module given the fullname (id) of it.
183
+ #
184
+ # Arguments:
185
+ # id -- fullname of the module (ex. auxiliary/admin/backupexec/dump)
186
+ #
187
+ # Returns:
188
+ # A dictionary with the following fields:
189
+ # # filename -- Name of the file
190
+ # content-type -- Mimetype
191
+ # data -- File content
192
+ def download(id)
193
+ return @api.request('msf/download', {:id => "#{id}"})
194
+ end
195
+
196
+ # Search for a metasploit module
197
+ def search(query, params={})
198
+ params[:q] = query
199
+ return @api.request('msf/search', params)
200
+ end
201
+
202
+ end
203
+
204
+ end
@@ -1,3 +1,3 @@
1
- module Shodan
2
- Version = VERSION = '0.5.0'
3
- end
1
+ module Shodan
2
+ Version = VERSION = '0.6.0'
3
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shodan
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 7
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 5
8
+ - 6
9
9
  - 0
10
- version: 0.5.0
10
+ version: 0.6.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - John Matherly
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-12 00:00:00 -07:00
18
+ date: 2012-08-23 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -24,7 +24,7 @@ dependencies:
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - ~>
27
+ - - ">="
28
28
  - !ruby/object:Gem::Version
29
29
  hash: 11
30
30
  segments:
@@ -47,9 +47,9 @@ files:
47
47
  - README.md
48
48
  - LICENSE
49
49
  - HISTORY.md
50
- - lib/shodan.rb
51
50
  - lib/shodan/version.rb
52
51
  - lib/shodan/api.rb
52
+ - lib/shodan.rb
53
53
  has_rdoc: true
54
54
  homepage: http://github.com/achillean/shodan-ruby
55
55
  licenses: []