fofa 0.3.17 → 0.4.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile.lock +2 -2
  3. data/bin/fofacli +103 -22
  4. data/lib/fofa/version.rb +13 -1
  5. data/lib/fofa.rb +59 -23
  6. metadata +7 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: c547727d9ed816e3d644f0416cc146bf6e856914
4
- data.tar.gz: 4b972ee2dc95eefadfe1233d4ab01cd912c790d1
2
+ SHA256:
3
+ metadata.gz: 4ba6286e4654e1e55b8b07ba1996edfb64b61139eb9957f03a7e73a35ae93e4a
4
+ data.tar.gz: 0b0c0daa6a59f9c602b5e72c19cf35f539cef73d0a0609d8090d73dd9ecc1676
5
5
  SHA512:
6
- metadata.gz: e3650e6c08280779282fd7865c912d9e2ec152ca3b8aea318e43f7a6e70014ca32308b7a38de9a45edb2b9e27434dc74fba6c9d2811f05648aea9ba7acff7863
7
- data.tar.gz: 2e919a75409e0c1a6fc7ee1eba8f9c094f630c061eaabbfa2d84e56519efe98c9583040177503eb48a701f9bf18c913c0419c5d77908c4249a28a05cba5a79b3
6
+ metadata.gz: 137d9c7252fd91dff2f6ac7d61f01fa43bca086bb716912c8e694aebaca9817970051708e29726f8c0c16920b7bf11e9b4b66334758ee826b24f5d907b2008fa
7
+ data.tar.gz: 0716e3e28ce190378a25aae007308d395ee651fa4ac02dd1ba29d36482f084f69b1a298d362dd4180bc7d6d34b7618db49efc2f598c683287977f45ccc9cad27
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fofa (0.3.16)
4
+ fofa (0.4.20)
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.15.1
41
+ 1.16.4
data/bin/fofacli CHANGED
@@ -21,7 +21,8 @@ options = {
21
21
  format: 'csv',
22
22
  check_app_category: nil,
23
23
  check_app_application: nil,
24
- check_app_all: false
24
+ check_app_all: false,
25
+ task_id: nil
25
26
  }
26
27
 
27
28
  ARGV.options do |opts|
@@ -42,12 +43,16 @@ ARGV.options do |opts|
42
43
  options[:page] = val.to_i
43
44
  end
44
45
 
45
- opts.on('-m', '--mode=MODE', String, 'Mode, default to [search], -m should be specified when [import_service, query_ip_list, check_app] ') 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|
46
47
  options[:mode] = val.to_sym
47
48
  end
48
49
 
49
- 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|
50
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
51
56
  end
52
57
 
53
58
  opts.on('-s', '--limit=SIZE', Integer, "Limit size to fetch, default to #{options[:limit]}") do |val|
@@ -80,7 +85,7 @@ ARGV.options do |opts|
80
85
  opts.on('-g', "--category=CATEGORY", String, "Category to check, only used in check_app mode." ) do |val|
81
86
  options[:check_app_category] = val
82
87
  options[:mode] = :check_app
83
- end
88
+ end
84
89
 
85
90
  opts.separator "Common Options:"
86
91
 
@@ -97,9 +102,14 @@ ARGV.options do |opts|
97
102
  options[:verbose] = true
98
103
  end
99
104
 
105
+ opts.on( "-V", "--version", "Display version" ) do
106
+ puts "Version: #{Fofa::VERSION}"
107
+ exit(0)
108
+ end
109
+
100
110
  opts.on( nil, "--check_app_all", "Check all applications, only used in check_app mode." ) do
101
111
  options[:check_app_all] = true
102
- end
112
+ end
103
113
 
104
114
 
105
115
 
@@ -110,6 +120,9 @@ ARGV.options do |opts|
110
120
  opts.separator "\t fofacli -e aaa@bbb.com -a xxx --query_file /tmp/fofaquery"
111
121
  opts.separator "\t fofacli -e aaa@bbb.com -a xxx -d ip,domain,title,port,protocol -m query_ip_list -f ip.txt"
112
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"' -- {}@
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"
113
126
 
114
127
  begin
115
128
  opts.parse!
@@ -139,17 +152,17 @@ def log_record(options, r)
139
152
  case options[:format]
140
153
  when 'json'
141
154
  if r.kind_of?(Array)
142
- puts Hash[options[:fields].split(',').zip r].to_json
155
+ STDOUT.puts Hash[options[:fields].split(',').zip r].to_json
143
156
  elsif r.kind_of?(Hash)
144
- puts r.to_json
157
+ STDOUT.puts r.to_json
145
158
  else
146
- puts %Q|{"id":"#{r}"}|
159
+ STDOUT.puts %Q|{"id":"#{r}"}|
147
160
  end
148
161
  when 'csv'
149
162
  if r.kind_of?(Array)
150
- puts r.map{|v| v}.join("\t")
163
+ STDOUT.puts r.map{|v| v}.join("\t")
151
164
  else
152
- puts r
165
+ STDOUT.puts r
153
166
  end
154
167
 
155
168
  end
@@ -163,7 +176,7 @@ case options[:mode]
163
176
  exit -1
164
177
  end
165
178
  query = options[:query] || ARGV.join(' ')
166
- puts "Query: '#{query}'"
179
+ STDERR.puts "Query: '#{query}'"
167
180
  if options[:page] #search one page
168
181
  Fofa::API.new(options[:email], options[:apikey], {debug:options[:verbose]})
169
182
  .search(query, {
@@ -205,7 +218,7 @@ case options[:mode]
205
218
  require 'concurrent'
206
219
  semaphore = Concurrent::Semaphore.new(1)
207
220
  pool = Concurrent::FixedThreadPool.new(10)
208
- $stdout.sync = true
221
+ $STDOUT.sync = true
209
222
  File.open(options[:file]){|f|
210
223
  fields = options[:fields].split(',')
211
224
  f.each_line{|line|
@@ -248,16 +261,84 @@ case options[:mode]
248
261
  pool.wait_for_termination
249
262
  when :check_app
250
263
  query = options[:query] || ARGV.join(' ')
251
- res = Fofa::API.new(options[:email], options[:apikey], {debug:options[:verbose]})
252
- .check_app(query, {
253
- category:options[:check_app_category],
254
- application:options[:check_app_application],
255
- all:options[:all],
256
- })
257
-
258
- res.each{|r|
259
- log_record(options, r)
260
- }
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
261
342
 
262
343
  end
263
344
 
data/lib/fofa/version.rb CHANGED
@@ -1,3 +1,15 @@
1
+ # 0.4.21
2
+ # split result to stdout
3
+ #
4
+ # 0.4.20
5
+ # add -V option, and ip_tags method need to upgrade major version
6
+ #
7
+ # 0.3.19
8
+ # add feature: ip_tags, tag_info
9
+ #
10
+ # 0.3.18
11
+ # add feature: check applications from file
12
+ #
1
13
  # 0.3.17
2
14
  # add checkapp api call
3
15
  #
@@ -28,5 +40,5 @@
28
40
  # 0.3.6
29
41
  # add fields
30
42
  module Fofa
31
- VERSION = "0.3.17"
43
+ VERSION = "0.4.21"
32
44
  end
data/lib/fofa.rb CHANGED
@@ -153,31 +153,67 @@ module Fofa
153
153
  req = Net::HTTP::Get.new(uri.request_uri)
154
154
  resp = http.request(req)
155
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)
156
212
 
157
- # File.open(file) do |f|
158
- # results = []
159
- # f.each_line.lazy.each_with_index do |line, i|
160
- #
161
- # line = line.strip
162
- # if m = /Discovered open port (?<port>.*?)\/tcp on (?<host>.*?)$/.match(line)
163
- # hostinfo = "#{m[:host]}:#{m[:port]}"
164
- # elsif line.include?(':')
165
- # hostinfo = line
166
- # else
167
- # hostinfo = "#{line}:#{options[:port]}"
168
- # end
169
- #
170
- # results << line
171
- # if i % split_size == 0
172
- # req = Net::HTTP::Post.new(uri.request_uri)
173
- # req.body = results.join("\n")
174
- # resp = http.request(req)
175
- # puts resp if @options[:debug]
176
- # results = []
177
- # end
178
- # end
179
- # end
213
+ resp = http.request(req)
214
+ JSON.parse(resp.body)
180
215
  rescue => e
216
+ $stderr.puts "[WARNING]: #{e.to_s}"
181
217
  {"error"=>"Error: #{e.to_s}"}
182
218
  end
183
219
 
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.17
4
+ version: 0.4.21
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-09-08 00:00:00.000000000 Z
11
+ date: 2021-09-18 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,9 @@ 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.12
126
- signing_key:
124
+ rubyforge_project:
125
+ rubygems_version: 2.7.7
126
+ signing_key:
127
127
  specification_version: 4
128
128
  summary: A Ruby library to interact with the FOFA API. https://fofa.so
129
129
  test_files: []