fofa 0.3.13 → 0.4.20

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 46230a00b448e0d6fa729755b2d1b3c03c5450c5
4
- data.tar.gz: 7841106b219d240133f9741f4618df11349dcede
2
+ SHA256:
3
+ metadata.gz: d545f5e3f2e72200759bf4f2f113cf4ae3933cacc79e7436db2948fca942f092
4
+ data.tar.gz: e72a5f234fdd0d8ffc0319140dd1e9a5493f53da7c0d212c19807be4a516f0b9
5
5
  SHA512:
6
- metadata.gz: d758ac844158fb49512e24c36587c4ff22562c5ddf33d7f5fa028d383b2dcc8d79262937917cdafe56b6481273857d98129a8ede3335072dadf04e0e494127da
7
- data.tar.gz: 935ca8c4e45adf3835057f0a6bda9050e9049686ec7971de51b90e9a5e76e95207b529d299c5177b282268695c6a9b8baf97013c8a1052b4bf2183224d8dd72f
6
+ metadata.gz: 0f610a997d2fc71c76c2d960426d1fc80346a19ef306d808c8e7a09175cd4e625105a108d4534a4dc01e49546b4f730cc05014c28ffed22e87ac5bdf364fabda
7
+ data.tar.gz: c768c528f1ba58e8e5823df16e4b2ea533800057c24411f0d47989ef3f0ef117e162073e60348ac4eb31840b0e03ba49ec349d4c4b09e67e892459e0f84c740b
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fofa (0.3.12)
4
+ fofa (0.3.19)
5
5
  colorize
6
6
  concurrent-ruby
7
7
 
@@ -38,4 +38,4 @@ DEPENDENCIES
38
38
  rspec (~> 3.0)
39
39
 
40
40
  BUNDLED WITH
41
- 1.14.6
41
+ 1.16.4
@@ -18,7 +18,11 @@ options = {
18
18
  fields: 'host',
19
19
  post: false,
20
20
  query: nil,
21
- format: 'csv'
21
+ format: 'csv',
22
+ check_app_category: nil,
23
+ check_app_application: nil,
24
+ check_app_all: false,
25
+ task_id: nil
22
26
  }
23
27
 
24
28
  ARGV.options do |opts|
@@ -39,12 +43,16 @@ ARGV.options do |opts|
39
43
  options[:page] = val.to_i
40
44
  end
41
45
 
42
- opts.on('-m', '--mode=MODE', String, 'Mode, default to [search], -m should be specified when [import_service, query_ip_list] ') do |val|
46
+ opts.on('-m', '--mode=MODE', String, 'Mode, default to [search], -m should be specified when [import_service, query_ip_list, check_app, ip_tags] ') do |val|
43
47
  options[:mode] = val.to_sym
44
48
  end
45
49
 
46
- opts.on('-f', '--file=FILE', String, 'Used at [import_service] mode') do |val|
50
+ opts.on('-f', '--file=FILE', String, 'Used at [import_service, check_app, ip_tags] mode') do |val|
47
51
  options[:file] = val
52
+ end
53
+
54
+ opts.on('-t', '--task_id=ID', Integer, 'Used at [ip_tags] mode') do |val|
55
+ options[:task_id] = val.to_i
48
56
  end
49
57
 
50
58
  opts.on('-s', '--limit=SIZE', Integer, "Limit size to fetch, default to #{options[:limit]}") do |val|
@@ -67,7 +75,17 @@ ARGV.options do |opts|
67
75
  raise "File not exist of #{val}" unless File.exists? val
68
76
  options[:query] = File.read(val).strip
69
77
  options[:post] = true
70
- end
78
+ end
79
+
80
+ opts.on('-l', "--application=APPLICATION", String, "Application to check, only used in check_app mode." ) do |val|
81
+ options[:check_app_application] = val
82
+ options[:mode] = :check_app
83
+ end
84
+
85
+ opts.on('-g', "--category=CATEGORY", String, "Category to check, only used in check_app mode." ) do |val|
86
+ options[:check_app_category] = val
87
+ options[:mode] = :check_app
88
+ end
71
89
 
72
90
  opts.separator "Common Options:"
73
91
 
@@ -84,6 +102,17 @@ ARGV.options do |opts|
84
102
  options[:verbose] = true
85
103
  end
86
104
 
105
+ opts.on( "-V", "--version", "Display version" ) do
106
+ puts "Version: #{Fofa::VERSION}"
107
+ exit(0)
108
+ end
109
+
110
+ opts.on( nil, "--check_app_all", "Check all applications, only used in check_app mode." ) do
111
+ options[:check_app_all] = true
112
+ end
113
+
114
+
115
+
87
116
  opts.separator ""
88
117
  opts.separator "For example:"
89
118
  opts.separator "\t fofacli -e aaa@bbb.com -a xxx domain=\"baidu.com\""
@@ -91,7 +120,10 @@ ARGV.options do |opts|
91
120
  opts.separator "\t fofacli -e aaa@bbb.com -a xxx --query_file /tmp/fofaquery"
92
121
  opts.separator "\t fofacli -e aaa@bbb.com -a xxx -d ip,domain,title,port,protocol -m query_ip_list -f ip.txt"
93
122
  opts.separator %Q@\t cat vapps.txt | xargs -I{} -n 1 sh -c 'fofacli "app=$1" -d host,ip,port,country,province,city -s 1000 -o json -v > "$1.txt"' -- {}@
94
-
123
+ opts.separator "\t fofacli -m check_app --app \"Coremail\" mail.tsinghua.edu.cn"
124
+ opts.separator "\t fofacli -e aaa@bbb.com -a xxx -m ip_tags -f ./ip.txt"
125
+ opts.separator "\t fofacli -e aaa@bbb.com -a xxx -m ip_tags -t 1"
126
+
95
127
  begin
96
128
  opts.parse!
97
129
  rescue OptionParser::InvalidOption => e
@@ -227,5 +259,86 @@ case options[:mode]
227
259
  } #File
228
260
  pool.shutdown
229
261
  pool.wait_for_termination
262
+ when :check_app
263
+ query = options[:query] || ARGV.join(' ')
264
+ fofa = Fofa::API.new(options[:email], options[:apikey], {debug:options[:verbose]})
265
+ if options[:file]
266
+ File.open(options[:file]){|f|
267
+ f.each_line{|line|
268
+ query = line.strip
269
+ res = fofa.check_app(query, {
270
+ category:options[:check_app_category],
271
+ application:options[:check_app_application],
272
+ all:options[:all],
273
+ })
274
+
275
+ if res && res.size>0
276
+ res.each{|r|
277
+ log_record(options, [query, r])
278
+ }
279
+ else
280
+ log_record(options, [query, nil])
281
+ end
282
+
283
+ }
284
+ }
285
+ else
286
+ res = fofa.check_app(query, {
287
+ category:options[:check_app_category],
288
+ application:options[:check_app_application],
289
+ all:options[:all],
290
+ })
291
+
292
+ if res && res.size>0
293
+ res.each{|r|
294
+ log_record(options, r)
295
+ }
296
+ else
297
+ $stderr.puts "[WARNING] No result!"
298
+ end
299
+
300
+ end
301
+ when :ip_tags
302
+ fofa = Fofa::API.new(options[:email], options[:apikey], {debug:options[:verbose]})
303
+ if options[:task_id]
304
+ task_id = options[:task_id]
305
+ else
306
+ unless options[:file]
307
+ puts "File not specified.".red
308
+ puts ARGV.options
309
+ exit -1
310
+ end
311
+ puts "Import ip and get tags from '#{options[:file]}'"
312
+ result = fofa.ip_tags(options[:file])
313
+ if result['error']
314
+ puts result
315
+ exit -1
316
+ end
317
+ puts result
318
+ task_id = result['task_id']
319
+ end
320
+
321
+ if task_id
322
+ get_info = -> (fofa, id) { fofa.tag_info(id) }
323
+ puts "Checking progress!"
324
+ sleep(2)
325
+
326
+ loop do
327
+ info = get_info.call(fofa, task_id)
328
+ if info['error']
329
+ puts info
330
+ break
331
+ elsif info['progress'].to_i == 100
332
+ puts "state: #{info['state']}; progress: #{info['progress']}."
333
+ puts info['download_url']
334
+ break
335
+ else
336
+ puts "state: #{info['state']}; progress: #{info['progress']}."
337
+ sleep(10)
338
+ end
339
+ end
340
+
341
+ end
342
+
230
343
  end
231
344
 
@@ -1,6 +1,7 @@
1
1
  require "fofa/version"
2
2
  require 'net/http'
3
3
  require 'json'
4
+ require 'base64'
4
5
 
5
6
  module Fofa
6
7
  class API
@@ -29,13 +30,10 @@ module Fofa
29
30
  options = {page:1, size:100, fields:'host'}.merge(options)
30
31
 
31
32
  url = "#{@api_server}/api/v1/search/all?key=#{@apikey}&email=#{@email}&page=#{options[:page]}&size=#{options[:size]}&fields=#{options[:fields]}"
32
- url += "&q=#{URI.escape(query)}" unless options[:post]
33
+ url += "&qbase64=#{Base64.encode64(query)}" unless options[:post]
33
34
  puts url if @options[:debug]
34
35
  uri = URI.parse(url)
35
- http = Net::HTTP.new(uri.host, uri.port)
36
- if uri.scheme == 'https'
37
- http.use_ssl = true
38
- end
36
+ http = http_new(uri)
39
37
 
40
38
  if options[:post]
41
39
  req = Net::HTTP::Post.new(uri.request_uri)
@@ -47,6 +45,7 @@ module Fofa
47
45
  resp = http.request(req)
48
46
  JSON.parse(resp.body)
49
47
  rescue => e
48
+ $stderr.puts "[WARNING]: #{e.to_s}"
50
49
  {"error"=>"Error: #{e.to_s}"}
51
50
  end
52
51
 
@@ -104,11 +103,7 @@ module Fofa
104
103
  url = "#{@api_server}/api/v1/import/services?key=#{@apikey}&email=#{@email}&port=#{options[:port]}"
105
104
  puts url if @options[:debug]
106
105
  uri = URI.parse(url)
107
- http = Net::HTTP.new(uri.host, uri.port)
108
- if uri.scheme == 'https'
109
- http.use_ssl = true
110
- end
111
- http.set_debug_output $stderr if @options[:debug]
106
+ http = http_new(uri)
112
107
 
113
108
  File.open(file) do |f|
114
109
  results = []
@@ -137,5 +132,99 @@ module Fofa
137
132
  {"error"=>"Error: #{e.to_s}"}
138
133
  end
139
134
 
135
+ # Check applications of asset
136
+ #
137
+ # Example:
138
+ # >> Fofa::API.new(email,apikey).checkapp("mail.tsinghua.edu.cn", category:"邮件系统")
139
+ # => ["Coremail"]
140
+ #
141
+ # Arguments:
142
+ # host: (String) Category name
143
+ # options: (Hash) category: Category name, application: Application name, all: return all applications or break when match first
144
+ def check_app(host, options={})
145
+ options = {all:false}.merge(options)
146
+ url = "#{@api_server}/api/v1/search/checkapp?key=#{@apikey}&email=#{@email}&host=#{host}"
147
+ url += "&all=#{options[:all]}" if options[:all]
148
+ url += "&application=#{URI.escape(options[:application])}" if options[:application]
149
+ url += "&category=#{URI.escape(options[:category])}" if options[:category]
150
+ puts url if @options[:debug]
151
+ uri = URI.parse(url)
152
+ http = http_new(uri)
153
+ req = Net::HTTP::Get.new(uri.request_uri)
154
+ resp = http.request(req)
155
+ JSON.parse(resp.body)
156
+ rescue => e
157
+ {"error"=>"Error: #{e.to_s}"}
158
+ end
159
+
160
+ # Import ip and get tags
161
+ #
162
+ # Example:
163
+ # >> Fofa::API.new(email,apikey).ip_tags('./ips.txt')
164
+ # => {"task_id"=>1}
165
+ #
166
+ # Arguments:
167
+ # file: (String) ip file
168
+ def ip_tags(file)
169
+ url = "#{@api_server}/api/v1/ip_tags?key=#{@apikey}&email=#{@email}"
170
+ puts url if @options[:debug]
171
+
172
+ # Token used to terminate the file in the post body. Make sure it is not
173
+ # present in the file you're uploading.
174
+ # You might want to use `SecureRandom` class to generate this random strings
175
+ boundary = "AaB03x"
176
+ uri = URI.parse(url)
177
+
178
+ post_body = []
179
+ post_body << "--#{boundary}\r\n"
180
+ post_body << "Content-Disposition: form-data; name=\"file\"; filename=\"#{File.basename(file)}\"\r\n"
181
+ post_body << "Content-Type: text/plain\r\n"
182
+ post_body << "\r\n"
183
+ post_body << File.read(file)
184
+ post_body << "\r\n--#{boundary}--\r\n"
185
+
186
+ http = http_new(uri)
187
+ req = Net::HTTP::Post.new(uri.request_uri)
188
+ req.body = post_body.join
189
+ req["Content-Type"] = "multipart/form-data, boundary=#{boundary}"
190
+
191
+ resp = http.request(req)
192
+ puts resp if @options[:debug]
193
+ JSON.parse(resp.body)
194
+ rescue => e
195
+ {"error"=>"Error: #{e.to_s}"}
196
+ end
197
+
198
+ # Check ip_tags's task state, progress, and download_url
199
+ #
200
+ # Example:
201
+ # >> Fofa::API.new(email,apikey).tag_info(1)
202
+ # => {"state"=>"success", "progress"=>100, "download_url"=>"https://host/xxx/56af409c1c55762a7b9e9a39a801f80d.json"}
203
+ #
204
+ # Arguments:
205
+ # task_id: (Integer) task id
206
+ def tag_info(task_id)
207
+ url = "#{@api_server}/api/v1/ip_tags/info?key=#{@apikey}&email=#{@email}&task_id=#{task_id}"
208
+ puts url if @options[:debug]
209
+ uri = URI.parse(url)
210
+ http = http_new(uri)
211
+ req = Net::HTTP::Get.new(uri.request_uri)
212
+
213
+ resp = http.request(req)
214
+ JSON.parse(resp.body)
215
+ rescue => e
216
+ $stderr.puts "[WARNING]: #{e.to_s}"
217
+ {"error"=>"Error: #{e.to_s}"}
218
+ end
219
+
220
+ private
221
+ def http_new(uri)
222
+ http = Net::HTTP.new(uri.host, uri.port)
223
+ if uri.scheme == 'https'
224
+ http.use_ssl = true
225
+ end
226
+ http.set_debug_output $stderr if @options[:debug]
227
+ http
228
+ end
140
229
  end
141
230
  end
@@ -1,3 +1,21 @@
1
+ # 0.4.20
2
+ # add -V option, and ip_tags method need to upgrade major version
3
+ #
4
+ # 0.3.19
5
+ # add feature: ip_tags, tag_info
6
+ #
7
+ # 0.3.18
8
+ # add feature: check applications from file
9
+ #
10
+ # 0.3.17
11
+ # add checkapp api call
12
+ #
13
+ # 0.3.15
14
+ # fixed query encode bug of '&&'
15
+ #
16
+ # 0.3.14
17
+ # fixed bug of search_all yield when size reached
18
+ #
1
19
  # 0.3.13
2
20
  # search_all yield with all size
3
21
  #
@@ -19,5 +37,5 @@
19
37
  # 0.3.6
20
38
  # add fields
21
39
  module Fofa
22
- VERSION = "0.3.13"
40
+ VERSION = "0.4.20"
23
41
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fofa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.13
4
+ version: 0.4.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - fofa
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-16 00:00:00.000000000 Z
11
+ date: 2020-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -106,7 +106,7 @@ homepage: https://fofa.so
106
106
  licenses:
107
107
  - MIT
108
108
  metadata: {}
109
- post_install_message:
109
+ post_install_message:
110
110
  rdoc_options: []
111
111
  require_paths:
112
112
  - lib
@@ -121,9 +121,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
121
  - !ruby/object:Gem::Version
122
122
  version: '0'
123
123
  requirements: []
124
- rubyforge_project:
125
- rubygems_version: 2.6.3
126
- signing_key:
124
+ rubygems_version: 3.0.6
125
+ signing_key:
127
126
  specification_version: 4
128
127
  summary: A Ruby library to interact with the FOFA API. https://fofa.so
129
128
  test_files: []