scopes_extractor 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 694da3bb3d2fd3ed580db8d5afa0da7bac2c2326037ed4218b57d87eca7ca174
4
- data.tar.gz: 100836692c414cd682653231a65a5937dc8b201560bbf10fa95e96e38d9b39a8
3
+ metadata.gz: 2720124a1d479958f99a1e40d303f5a8fa1fb45727b7c575197561522245cd3f
4
+ data.tar.gz: bc579dc76168344ac983876d54db4b55977099e6488fbe26a0971bf85488af35
5
5
  SHA512:
6
- metadata.gz: 1a3f2040079e8e05cfd2157b259f95b8912813f8f7ec2e867fd0ce9f7802a05a3b46c63027b5493a0d79a2b28f536b67686b9fb3b5d71926e70de31b846764ca
7
- data.tar.gz: 53e92c8b6bcf0608c6c14d6e4f4733e29a8c86a930b7a25de1b6d5242c45d8e7eb38df8d0ebbf50a4c4d49d50e2c5c6286d0609d0140fc44d2d72ba21132466a
6
+ metadata.gz: 9b5387a228e502be7cd36c5ea4e67151ece0a046406931619c159c17d4345069b0885b5de27683a63190b5ac0a108023dc7524e406e836179eb12cf820c6be41
7
+ data.tar.gz: 784560b6ed8def4699d7c3e03a34ee02ef5db707183acc7d702e3c058cf0bb0df0c38ceca648609f24cb79941d10dd78bc1f64b8dd4583098bef70dcb19c6f78
@@ -8,14 +8,13 @@ class HttpClient
8
8
  }
9
9
 
10
10
  def self.headers(url, authentication)
11
- case
12
- when url.include?('yeswehack')
11
+ if url.include?('yeswehack')
13
12
  { 'Content-Type' => 'application/json', Authorization: "Bearer #{authentication}" }
14
- when url.include?('intigriti')
13
+ elsif url.include?('intigriti')
15
14
  { Authorization: "Bearer #{authentication}" }
16
- when url.include?('bugcrowd')
15
+ elsif url.include?('bugcrowd')
17
16
  { 'Cookie' => authentication }
18
- when url.include?('hackerone')
17
+ elsif url.include?('hackerone')
19
18
  @request_options[:userpwd] = "#{ENV.fetch('H1_USERNAME', nil)}:#{ENV.fetch('H1_API_KEY', nil)}"
20
19
  { 'Accept' => 'application/json' }
21
20
  else
@@ -35,4 +34,4 @@ class HttpClient
35
34
 
36
35
  Typhoeus.post(url, @request_options)
37
36
  end
38
- end
37
+ end
@@ -39,4 +39,4 @@ class Bugcrowd
39
39
  match[0]
40
40
  end
41
41
  end
42
- end
42
+ end
@@ -6,7 +6,9 @@ class Bugcrowd
6
6
  # Bugcrowd Sync Programs
7
7
  class Programs
8
8
  def self.sync(results, options, cookie, page_id = 1)
9
- response = HttpClient.get("https://bugcrowd.com/programs.json?page[]=#{page_id}&waitlistable[]=false&joinable[]=false", cookie)
9
+ response = HttpClient.get(
10
+ "https://bugcrowd.com/programs.json?page[]=#{page_id}&waitlistable[]=false&joinable[]=false", cookie
11
+ )
10
12
  return unless response&.code == 200
11
13
 
12
14
  body = JSON.parse(response.body)
@@ -33,4 +35,4 @@ class Bugcrowd
33
35
  }
34
36
  end
35
37
  end
36
- end
38
+ end
@@ -21,7 +21,7 @@ class Bugcrowd
21
21
  in_scopes = JSON.parse(response.body)['targets']
22
22
  scopes['in'] = parse_scopes(in_scopes)
23
23
 
24
- scopes['out'] = { } # TODO
24
+ scopes['out'] = {} # TODO
25
25
 
26
26
  scopes
27
27
  end
@@ -40,4 +40,4 @@ class Hackerone
40
40
  { next_page: json_body['links']['next'], programs: json_body['data'] }
41
41
  end
42
42
  end
43
- end
43
+ end
@@ -5,13 +5,13 @@ class Hackerone
5
5
  class Scopes
6
6
  def self.sync(program)
7
7
  scopes = {}
8
- response = HttpClient.get( "https://api.hackerone.com/v1/hackers/programs/#{program[:slug]}")
8
+ response = HttpClient.get("https://api.hackerone.com/v1/hackers/programs/#{program[:slug]}")
9
9
  return scopes unless response&.code == 200
10
10
 
11
11
  in_scopes = JSON.parse(response.body)['relationships']['structured_scopes']['data']
12
12
  scopes['in'] = parse_scopes(in_scopes)
13
13
 
14
- scopes['out'] = { } # TODO
14
+ scopes['out'] = {} # TODO
15
15
 
16
16
  scopes
17
17
  end
@@ -47,4 +47,4 @@ class Hackerone
47
47
  normalized
48
48
  end
49
49
  end
50
- end
50
+ end
@@ -19,7 +19,8 @@ class Intigriti
19
19
  next if program['status'] == 4 # Suspended
20
20
 
21
21
  results[program['name']] = program_info(program)
22
- results[program['name']]['scopes'] = Scopes.sync({ handle: program['handle'], company: program['companyHandle'] }, token)
22
+ results[program['name']]['scopes'] =
23
+ Scopes.sync({ handle: program['handle'], company: program['companyHandle'] }, token)
23
24
  end
24
25
  end
25
26
 
@@ -30,7 +30,7 @@ class Intigriti
30
30
  end
31
31
 
32
32
  def self.submit_otp(mechanize)
33
- return if ENV['INTIGRITI_OTP']&.empty?
33
+ return if ENV['INTIGRITI_OTP'] && ENV['INTIGRITI_OTP'].empty?
34
34
 
35
35
  totp_page = mechanize.get('https://login.intigriti.com/account/loginwith2fa')
36
36
  totp_code = ROTP::TOTP.new(ENV.fetch('INTI_OTP', nil))
@@ -51,4 +51,4 @@ class Intigriti
51
51
  token_page.body&.undump
52
52
  end
53
53
  end
54
- end
54
+ end
@@ -4,7 +4,7 @@ class YesWeHack
4
4
  # YesWeHack Auth Class
5
5
  class Auth
6
6
  def self.jwt
7
- totp_token = get_totp_token
7
+ totp_token = extract_totp_token
8
8
  return unless totp_token
9
9
 
10
10
  response = send_totp(totp_token)
@@ -16,7 +16,7 @@ class YesWeHack
16
16
  jwt
17
17
  end
18
18
 
19
- def self.get_totp_token
19
+ def self.extract_totp_token
20
20
  data = { email: ENV.fetch('YWH_EMAIL', nil), password: ENV.fetch('YWH_PASSWORD', nil) }.to_json
21
21
  response = HttpClient.post('https://api.yeswehack.com/login', data)
22
22
  return unless response&.code == 200
@@ -32,4 +32,4 @@ class YesWeHack
32
32
  response
33
33
  end
34
34
  end
35
- end
35
+ end
@@ -39,4 +39,4 @@ class YesWeHack
39
39
  }
40
40
  end
41
41
  end
42
- end
42
+ end
@@ -25,6 +25,8 @@ class YesWeHack
25
25
 
26
26
  normalized = normalize(infos['scope'])
27
27
  normalized.each do |asset|
28
+ next unless asset.include?('.')
29
+
28
30
  scopes_normalized << asset
29
31
  end
30
32
  end
@@ -32,25 +34,25 @@ class YesWeHack
32
34
  scopes_normalized
33
35
  end
34
36
 
35
- # rubocop:disable Metrics/AbcSize
36
- # rubocop:disable Metrics/MethodLength
37
- # rubocop:disable Metrics/PerceivedComplexity
38
- # rubocop:disable Metrics/CyclomaticComplexity
39
37
  def self.normalize(scope)
40
38
  # Remove (+++) & When end with '*'
41
39
  scope = scope.gsub(/\(?\+\)?/, '').sub(/\*$/, '').strip
42
40
  return [] if scope.include?('<') # <yourdomain>-yeswehack.domain.tld
43
41
 
42
+ scope = scope.split[0] # When spaces
43
+
44
44
  normalized = []
45
45
 
46
- match = scope.match(/^(.*)\((.*)\)$/) # Ex: *.lazada.(sg|vn|co.id|co.th|com|com.ph|com.my)
47
- if match && match[1] && match[2]
48
- tlds = match[2].split('|')
49
- tlds.each { |tld| normalized << "#{match[1]}#{tld}" }
50
- elsif scope.include?(' ')
51
- normalized << scope.split(' ')[0]
46
+ multi_subs = scope.match(/^\((.*)\)(.*)/) # Ex: (online|portal|agents|agentuat|surinameuat|surinameopsuat|suriname|thailandevoa).vfsevisa.com
47
+ multi_tld = scope.match(/^(.*)\((.*)\)$/) # Ex: *.lazada.(sg|vn|co.id|co.th|com|com.ph|com.my)
48
+ if multi_tld && multi_tld[1] && multi_tld[2]
49
+ tlds = multi_tld[2].split('|')
50
+ tlds.each { |tld| normalized << "#{multi_tld[1]}#{tld}" }
52
51
  elsif scope.match?(%r{https?://\*})
53
52
  normalized << scope.sub(%r{https?://}, '')
53
+ elsif multi_subs && multi_subs[1] && multi_subs[2]
54
+ subs = multi_subs[1].split('|')
55
+ subs.each { |sub| normalized << "#{sub}#{multi_subs[2]}"}
54
56
  else
55
57
  normalized << scope
56
58
  end
@@ -58,4 +60,4 @@ class YesWeHack
58
60
  normalized
59
61
  end
60
62
  end
61
- end
63
+ end
@@ -31,8 +31,8 @@ class ScopesExtractor
31
31
 
32
32
  if options[:yeswehack]
33
33
  jwt = YesWeHack::Auth.jwt
34
-
35
34
  results['YesWeHack'] = {}
35
+
36
36
  YesWeHack::Programs.sync(results['YesWeHack'], options, jwt)
37
37
  end
38
38
 
@@ -52,9 +52,10 @@ class ScopesExtractor
52
52
 
53
53
  if options[:hackerone]
54
54
  results['Hackerone'] = {}
55
+
55
56
  Hackerone::Programs.sync(results['Hackerone'], options)
56
57
  end
57
58
 
58
- p results
59
+ results
59
60
  end
60
- end
61
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scopes_extractor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua MARTINELLE
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-13 00:00:00.000000000 Z
11
+ date: 2023-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -85,45 +85,45 @@ dependencies:
85
85
  - !ruby/object:Gem::Version
86
86
  version: 2.9.1
87
87
  - !ruby/object:Gem::Dependency
88
- name: typhoeus
88
+ name: rotp
89
89
  requirement: !ruby/object:Gem::Requirement
90
90
  requirements:
91
91
  - - "~>"
92
92
  - !ruby/object:Gem::Version
93
- version: '1.4'
93
+ version: '6.2'
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: 1.4.0
96
+ version: 6.2.2
97
97
  type: :runtime
98
98
  prerelease: false
99
99
  version_requirements: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '1.4'
103
+ version: '6.2'
104
104
  - - ">="
105
105
  - !ruby/object:Gem::Version
106
- version: 1.4.0
106
+ version: 6.2.2
107
107
  - !ruby/object:Gem::Dependency
108
- name: rotp
108
+ name: typhoeus
109
109
  requirement: !ruby/object:Gem::Requirement
110
110
  requirements:
111
111
  - - "~>"
112
112
  - !ruby/object:Gem::Version
113
- version: '6.2'
113
+ version: '1.4'
114
114
  - - ">="
115
115
  - !ruby/object:Gem::Version
116
- version: 6.2.2
116
+ version: 1.4.0
117
117
  type: :runtime
118
118
  prerelease: false
119
119
  version_requirements: !ruby/object:Gem::Requirement
120
120
  requirements:
121
121
  - - "~>"
122
122
  - !ruby/object:Gem::Version
123
- version: '6.2'
123
+ version: '1.4'
124
124
  - - ">="
125
125
  - !ruby/object:Gem::Version
126
- version: 6.2.2
126
+ version: 1.4.0
127
127
  description:
128
128
  email:
129
129
  - contact@jomar.fr