scopes_extractor 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/lib/scopes_extractor/http_client.rb +5 -6
- data/lib/scopes_extractor/platforms/bugcrowd/cookie.rb +1 -1
- data/lib/scopes_extractor/platforms/bugcrowd/programs.rb +4 -2
- data/lib/scopes_extractor/platforms/bugcrowd/scopes.rb +1 -1
- data/lib/scopes_extractor/platforms/hackerone/programs.rb +1 -1
- data/lib/scopes_extractor/platforms/hackerone/scopes.rb +3 -3
- data/lib/scopes_extractor/platforms/intigriti/programs.rb +2 -1
- data/lib/scopes_extractor/platforms/intigriti/token.rb +2 -2
- data/lib/scopes_extractor/platforms/yeswehack/jwt.rb +3 -3
- data/lib/scopes_extractor/platforms/yeswehack/programs.rb +1 -1
- data/lib/scopes_extractor/platforms/yeswehack/scopes.rb +13 -11
- data/lib/scopes_extractor.rb +4 -3
- metadata +12 -12
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 2720124a1d479958f99a1e40d303f5a8fa1fb45727b7c575197561522245cd3f
         | 
| 4 | 
            +
              data.tar.gz: bc579dc76168344ac983876d54db4b55977099e6488fbe26a0971bf85488af35
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 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 | 
            -
                 | 
| 12 | 
            -
                when url.include?('yeswehack')
         | 
| 11 | 
            +
                if url.include?('yeswehack')
         | 
| 13 12 | 
             
                  { 'Content-Type' => 'application/json', Authorization: "Bearer #{authentication}" }
         | 
| 14 | 
            -
                 | 
| 13 | 
            +
                elsif url.include?('intigriti')
         | 
| 15 14 | 
             
                  { Authorization: "Bearer #{authentication}" }
         | 
| 16 | 
            -
                 | 
| 15 | 
            +
                elsif url.include?('bugcrowd')
         | 
| 17 16 | 
             
                  { 'Cookie' => authentication }
         | 
| 18 | 
            -
                 | 
| 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
         | 
| @@ -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( | 
| 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
         | 
| @@ -5,13 +5,13 @@ class Hackerone | |
| 5 5 | 
             
              class Scopes
         | 
| 6 6 | 
             
                def self.sync(program)
         | 
| 7 7 | 
             
                  scopes = {}
         | 
| 8 | 
            -
                  response = HttpClient.get( | 
| 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'] = { | 
| 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'] = | 
| 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'] | 
| 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 =  | 
| 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. | 
| 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
         | 
| @@ -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 | 
            -
                   | 
| 47 | 
            -
                   | 
| 48 | 
            -
             | 
| 49 | 
            -
                    tlds | 
| 50 | 
            -
             | 
| 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
         | 
    
        data/lib/scopes_extractor.rb
    CHANGED
    
    | @@ -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 | 
            -
                 | 
| 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. | 
| 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- | 
| 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:  | 
| 88 | 
            +
              name: rotp
         | 
| 89 89 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 90 90 | 
             
                requirements:
         | 
| 91 91 | 
             
                - - "~>"
         | 
| 92 92 | 
             
                  - !ruby/object:Gem::Version
         | 
| 93 | 
            -
                    version: ' | 
| 93 | 
            +
                    version: '6.2'
         | 
| 94 94 | 
             
                - - ">="
         | 
| 95 95 | 
             
                  - !ruby/object:Gem::Version
         | 
| 96 | 
            -
                    version:  | 
| 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: ' | 
| 103 | 
            +
                    version: '6.2'
         | 
| 104 104 | 
             
                - - ">="
         | 
| 105 105 | 
             
                  - !ruby/object:Gem::Version
         | 
| 106 | 
            -
                    version:  | 
| 106 | 
            +
                    version: 6.2.2
         | 
| 107 107 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 108 | 
            -
              name:  | 
| 108 | 
            +
              name: typhoeus
         | 
| 109 109 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 110 110 | 
             
                requirements:
         | 
| 111 111 | 
             
                - - "~>"
         | 
| 112 112 | 
             
                  - !ruby/object:Gem::Version
         | 
| 113 | 
            -
                    version: ' | 
| 113 | 
            +
                    version: '1.4'
         | 
| 114 114 | 
             
                - - ">="
         | 
| 115 115 | 
             
                  - !ruby/object:Gem::Version
         | 
| 116 | 
            -
                    version:  | 
| 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: ' | 
| 123 | 
            +
                    version: '1.4'
         | 
| 124 124 | 
             
                - - ">="
         | 
| 125 125 | 
             
                  - !ruby/object:Gem::Version
         | 
| 126 | 
            -
                    version:  | 
| 126 | 
            +
                    version: 1.4.0
         | 
| 127 127 | 
             
            description:
         | 
| 128 128 | 
             
            email:
         | 
| 129 129 | 
             
            - contact@jomar.fr
         |