githack 0.2.0 → 0.3.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
  SHA1:
3
- metadata.gz: 45b9752319cd83954a52829df8728540731f5fe7
4
- data.tar.gz: 99461ea4306976cdcedfea9927d13b778c96fda4
3
+ metadata.gz: a900b5b7270b5e428ca145df3ff430d2ba06d936
4
+ data.tar.gz: 7f63c2b10228956cc19120b2787bebcdfbb560bb
5
5
  SHA512:
6
- metadata.gz: e5908cddcecc60d86ba4ccf49a9685af8e930ccdf88d9a48507c2bfb442e7ec0274460c01ae1e2e85f800042d6e43723fcda6dd8090b53c080575dfd789b26af
7
- data.tar.gz: 6da3344fb2cbd29c67d0648d947bfa82b0a9a09b04a47497f4db7825072632500864fd1b9a25258b623d9dbb28a1329e925b8f2f8c4f5140d44249ea43b87848
6
+ metadata.gz: 071452db5375ca0af30f609e9432b90b2b636cd494309be220375d519665476c59a548f3176785a0da81244643a423bcd6d1878e70aae55b50a7f0c485042e86
7
+ data.tar.gz: 6f92e2fdf1374fdd0171921a41ed44add19aa473ad7fdfa682852dd5ffbe277db4b27410a1833c1ac503d471156ed0b98cc05156e279f11a3264c7ed2cf24ac3
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- githack (0.2.0)
4
+ githack (0.3.0)
5
5
  git (~> 1.5)
6
6
  tty-spinner (~> 0.8)
7
7
 
@@ -38,4 +38,4 @@ DEPENDENCIES
38
38
  rspec (~> 3.0)
39
39
 
40
40
  BUNDLED WITH
41
- 1.16.1
41
+ 1.16.3
data/README.md CHANGED
@@ -2,18 +2,16 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/githack.svg)](https://rubygems.org/gems/githack)
4
4
 
5
- Crawl [Git][git]'s commits of a given repository to find forgotten credentials
5
+ Crawl [Git][git]'s commits of a given repository to find forgotten credentials according to given framework.
6
6
 
7
- Currently support:
7
+ > [See documentation ](https://www.rubydoc.info/gems/githack/Githack/Repositories) to know which framework is currently supported
8
8
 
9
- - [Ruby on Rails](https://rubyonrails.org)
10
-
11
- - _config/secrets.yml_
12
- - _config/database.yml_
13
9
 
14
10
  ## Dependencies
15
11
 
16
- You need to install [Git][git]. Exemple for Debian based distributions:
12
+ You need to install [Git][git].
13
+
14
+ Exemple for Debian based distributions:
17
15
 
18
16
  ```bash
19
17
  $ sudo apt install git
@@ -44,31 +42,44 @@ Simply use tis to clone the remote repository in your temporary folder
44
42
  ```ruby
45
43
  require 'githack'
46
44
 
47
- repository = Githack::RailsRepository.new 'https://github.com/RaspberryCook/website'
45
+ repository = Githack::Repositories::Rails::v4.new 'https://github.com/RaspberryCook/website'
48
46
  ```
49
47
 
50
- And then you can search on repository like this:
48
+ And then you can search on repository using `databases` or `secrets` who returns `Array<Githack::Leak>`. `Githack::Leak` contains `sha`, `file` and `content`:
51
49
 
52
50
  ```ruby
53
- repository.search_rails_config_database
54
- # [{"adapter"=>"mysql2", "database"=>"raspberry_cook", "encoding"=>"utf8", "username"=>"raspberry_cook", "password"=>"secret", "host"=>"localhost", "pool"=>5, "timeout"=>5000}])
55
-
56
- repository.search_rails_config_secrets
57
- # [{"development"=>{"marmiton_password"=>"20462046"}, "production"=>{"marmiton_password"=>"20462046"}, "test"=>{"marmiton_password"=>"20462046"}}])
51
+ repository.databases.each do |leak|
52
+ # <Githack::Leak:Githack::Leak:0x00556db18af998 ... >,
53
+ puts leak.sha
54
+ # => 566fac779248c345192512423770f14cf4af1435
55
+ puts leak.file
56
+ # => /tmp/https___github_com_madeindjs_fooder/config/database.yml
57
+ puts leak.content
58
+ # "development:\n" +
59
+ # " adapter: mysql2\n" +
60
+ # " database: raspberry_cook\n" +
61
+ # " encoding: utf8\n" +
62
+ # " username: raspberry_cook\n" +
63
+ # " password: secret\n" +
64
+ # " host: localhost\n" +
65
+ end
66
+
67
+ repository.secrets.each do |leak|
68
+ # ....
69
+ end
58
70
  ```
59
71
 
60
72
  Theses methods will:
61
73
 
62
74
  1. Search all commit were file changed
63
75
  2. Checkout on theses commit to get file content
64
- 3. Filter only usefull informations
65
76
 
66
77
  ### As command line tool
67
78
 
68
79
  Simply use
69
80
 
70
81
  ```bash
71
- $ githack.rb https://github.com/RaspberryCook/website
82
+ $ githack.rb --framework=Rails::V4 https://github.com/madeindjs/fooder
72
83
  ```
73
84
 
74
85
  ## Development
@@ -79,7 +90,35 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
79
90
 
80
91
  ## Contributing
81
92
 
82
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/githack. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
93
+ Bug reports and pull requests are welcome on GitHub at https://github.com/madeindjs/githack. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
94
+
95
+ ### Add new framwork to support
96
+
97
+ Fork this repository & create a new file based on `Githack::Repositories::Rails`
98
+
99
+ ```bash
100
+ $ cp lib/githack/repositories/rails.rb
101
+ ```
102
+
103
+ Then simply overwride
104
+
105
+ ```ruby
106
+ # lib/githack/repositories/your_framework.rb
107
+ module Githack
108
+ module Repositories
109
+ # Module who hold all version of your framework
110
+ module YourFramework
111
+ # Represent a version of your framework
112
+ class V1 < Githack::Repository
113
+ # Represent the path to secrets files
114
+ DATABASE_PATHS = [File.join('config', 'database.php')].freeze
115
+ # Represent the path to database configuration files
116
+ SECRET_PATH = [File.join('config', 'secrets.yml')].freeze
117
+ end
118
+ end
119
+ end
120
+ end
121
+ ```
83
122
 
84
123
  ## Code of Conduct
85
124
 
@@ -8,14 +8,19 @@ url = nil
8
8
 
9
9
  options = {
10
10
  skip_config_secrets: false,
11
- skip_config_database: false
11
+ skip_config_database: false,
12
+ framework: nil
12
13
  }
13
14
 
14
- OptionParser.new do |opts|
15
+ optparse = OptionParser.new do |opts|
15
16
  opts.banner = 'Usage: githack.rb URL with URL as remote URL of a Git repository (currently works only for Rails project)'
16
17
 
17
18
  url = ARGV.pop
18
19
 
20
+ opts.on '-f', '--framework FRAMEWORK', 'Specify repository framework to target to find leaked data', 'use without parameter to get the complete list' do |framework|
21
+ options[:framework] = framework
22
+ end
23
+
19
24
  opts.on '--skip_config_secrets', 'Not search for config/secrets.yml' do |_o|
20
25
  options[:skip_config_secrets] = true
21
26
  end
@@ -24,22 +29,41 @@ OptionParser.new do |opts|
24
29
  options[:skip_config_secrets] = true
25
30
  end
26
31
 
32
+ opts.on('-h', '--help', 'Display this screen') do
33
+ puts opts
34
+ exit
35
+ end
36
+
27
37
  unless url
28
38
  puts "You must provide a Git remote URL\r\n\r\n"
29
39
  puts opts
30
40
  exit
31
41
  end
32
- end.parse!
42
+ end
43
+
44
+ optparse.parse!
45
+
46
+ unless Githack::Repositories.get_availables_frameworks_versions_pretty.include?(options[:framework])
47
+
48
+ puts "You must specify framework\r\n\r\n"
49
+ Githack::Repositories.get_availables_frameworks_versions_pretty.each do |framework|
50
+ puts format(' - %s', framework)
51
+ end
52
+
53
+ exit
54
+ end
55
+
56
+ framework_class = Githack::Repositories.const_get(options[:framework])
33
57
 
34
58
  spinner = TTY::Spinner.new '[:spinner] Cloning repository ...'
35
59
  spinner.auto_spin
36
- repository = Githack::RailsRepository.new url
60
+ repository = framework_class.new url
37
61
  spinner.stop('Done!')
38
62
 
39
63
  unless options[:skip_config_database]
40
64
  spinner = TTY::Spinner.new '[:spinner] Search in config/database.yml (Rails) ...'
41
65
  spinner.auto_spin
42
- result = repository.search_rails_config_database
66
+ result = repository.databases
43
67
  spinner.stop('Done!')
44
68
  pp result
45
69
  end
@@ -47,7 +71,7 @@ end
47
71
  unless options[:skip_config_secrets]
48
72
  spinner = TTY::Spinner.new '[:spinner] Search in config/secrets.yml (Rails) ...'
49
73
  spinner.auto_spin
50
- result = repository.search_rails_config_secrets
74
+ result = repository.secrets
51
75
  spinner.stop('Done!')
52
76
  pp result
53
77
  end
@@ -1,6 +1,42 @@
1
1
  require 'githack/version'
2
- require 'githack/rails_repository'
2
+ require 'githack/repositories/cakephp'
3
+ require 'githack/repositories/laravel'
4
+ require 'githack/repositories/rails'
5
+ require 'githack/repositories/symfony'
6
+ require 'githack/leak'
3
7
 
4
8
  module Githack
5
- # Your code goes here...
9
+ # Represent frameworks available to parse leaked data
10
+ module Repositories
11
+ # Get all class available as repository
12
+ #
13
+ # @return [Array<Class>]
14
+ def self.get_availables_frameworks_versions
15
+ available = []
16
+
17
+ frameworks = Githack::Repositories.constants.select do |c|
18
+ Githack::Repositories.const_get(c).is_a? Module
19
+ end
20
+
21
+ frameworks.each do |framework|
22
+ framework_module = Githack::Repositories.const_get(framework)
23
+
24
+ Githack::Repositories.const_get(framework).constants.each do |v|
25
+ v_class = framework_module.const_get(v)
26
+ available << v_class if v_class.is_a? Class
27
+ end
28
+ end
29
+
30
+ available
31
+ end
32
+
33
+ # Get all class available as repository as pretty string
34
+ #
35
+ # @return [Array<String>]
36
+ def self.get_availables_frameworks_versions_pretty
37
+ Repositories.get_availables_frameworks_versions.map do |framework|
38
+ framework.to_s.gsub('Githack::Repositories::', '')
39
+ end.sort
40
+ end
41
+ end
6
42
  end
@@ -0,0 +1,11 @@
1
+ module Githack
2
+ class Leak
3
+ attr_reader :sha, :content, :file
4
+
5
+ def initialize(sha, file)
6
+ @sha = sha
7
+ @file = file
8
+ @content = File.read(file)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ require 'githack/repository'
2
+
3
+ module Githack
4
+ module Repositories
5
+ module CakePHP
6
+ class V3 < Githack::Repository
7
+ DATABASE_PATHS = [
8
+ File.join('config', 'app.php')
9
+ ].freeze
10
+
11
+ # SECRET_PATH = ['config', 'secrets.yml']
12
+ end
13
+
14
+ class V2 < Githack::Repository
15
+ DATABASE_PATHS = [
16
+ File.join('app', 'Config', 'database.php')
17
+ ].freeze
18
+
19
+ # SECRET_PATH = ['config', 'secrets.yml']
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ require 'githack/repository'
2
+
3
+ module Githack
4
+ module Repositories
5
+ module Laravel
6
+ class V5 < Githack::Repository
7
+ DATABASE_PATHS = [
8
+ File.join('config', 'database.php')
9
+ ].freeze
10
+
11
+ # SECRET_PATH = ['config', 'secrets.yml']
12
+ end
13
+
14
+ class V4 < V5
15
+ DATABASE_PATHS = [
16
+ File.join('app', 'config', 'database.php')
17
+ ].freeze
18
+
19
+ # SECRET_PATH = ['config', 'secrets.yml']
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ require 'githack/repository'
2
+
3
+ module Githack
4
+ module Repositories
5
+ module Rails
6
+ class V5 < Githack::Repository
7
+ SECRET_PATHS = [
8
+ File.join('config', 'secrets.yml')
9
+ ].freeze
10
+
11
+ DATABASE_PATHS = [
12
+ File.join('config', 'database.yml')
13
+ ].freeze
14
+ end
15
+
16
+ class V4 < V5
17
+ end
18
+
19
+ class V3 < V5
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,49 @@
1
+ require 'githack/repository'
2
+
3
+ module Githack
4
+ module Repositories
5
+ module Symfony
6
+ class V4 < Githack::Repository
7
+ SECRET_PATHS = ['.env'].freeze
8
+
9
+ # https://symfony.com/doc/4.1/doctrine.html
10
+ DATABASE_PATHS = [
11
+ File.join('config', 'packages', 'doctrine.yaml'),
12
+ File.join('config', 'packages', 'doctrine.xml'),
13
+ File.join('config', 'packages', 'doctrine.php')
14
+ ].freeze
15
+ end
16
+
17
+ class V3 < Githack::Repository
18
+ SECRET_PATHS = ['.env'].freeze
19
+
20
+ # https://symfony.com/doc/3.3/doctrine.html
21
+ DATABASE_PATHS = [
22
+ File.join('app', 'config', 'parameters.xml'),
23
+ File.join('app', 'config', 'parameters.yml'),
24
+ File.join('app', 'config', 'parameters.php')
25
+ ].freeze
26
+ end
27
+
28
+ class V2 < Githack::Repository
29
+ SECRET_PATHS = ['.env'].freeze
30
+
31
+ # https://symfony.com/doc/2.8/doctrine.html
32
+ DATABASE_PATHS = [
33
+ File.join('app', 'config', 'config.xml'),
34
+ File.join('app', 'config', 'config.yml'),
35
+ File.join('app', 'config', 'config.php')
36
+ ].freeze
37
+ end
38
+
39
+ class V1 < Githack::Repository
40
+ SECRET_PATHS = [].freeze
41
+
42
+ # https://symfony.com/legacy/doc/reference/1_4/en/07-Databases
43
+ DATABASE_PATHS = [
44
+ File.join('config', 'databases.yml')
45
+ ].freeze
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,11 +1,17 @@
1
1
  require 'tmpdir'
2
2
  require 'yaml'
3
3
  require 'git'
4
+ require 'githack/leak'
4
5
 
5
6
  module Githack
6
7
  class Repository
7
8
  attr_reader :git, :remote, :name, :path
8
9
 
10
+ # Represent the path to secrets files
11
+ SECRET_PATH = [].freeze
12
+ # Represent the path to database configuration files
13
+ DATABASE_PATH = [].freeze
14
+
9
15
  def initialize(remote)
10
16
  @remote = remote
11
17
  @name = remote.gsub /[^0-9A-Z]/i, '_'
@@ -18,40 +24,61 @@ module Githack
18
24
  end
19
25
  end
20
26
 
21
- protected
27
+ # Get all changements for config/secrets.yml file (who contains some API keys)
28
+ #
29
+ # @return [Array<Githack::Leak>]
30
+ def secrets
31
+ leaks = []
32
+ files = self.class::SECRET_PATHS.map { |f| File.join(@path, f) }
22
33
 
23
- # Checkout on all file changes
34
+ get_leaks(*files).each do |leak|
35
+ leaks << leak
36
+ yield lead if block_given?
37
+ end
38
+ leaks
39
+ end
40
+
41
+ # Get all changements for config/database.yml file (who contains database configuration for Ruby on Rails Framework)
24
42
  #
25
- # @param file <String> absolute filepath
26
- # @yield <Hash> YAML file parsed
27
- def checkout_on_yaml_file_change(file)
28
- checkout_on_file_change(file) do
29
- begin
30
- data = YAML.safe_load(File.read(file))
31
- yield data
32
- rescue Psych::SyntaxError => e
33
- # can't parse YAML file
34
- end
43
+ # @return [Array<Githack::Leak>]
44
+ def databases
45
+ leaks = []
46
+ files = self.class::DATABASE_PATHS.map { |f| File.join(@path, f) }
47
+
48
+ get_leaks(*files).each do |leak|
49
+ leaks << leak
50
+ yield lead if block_given?
35
51
  end
52
+ leaks
36
53
  end
37
54
 
55
+ protected
56
+
38
57
  # Checkout on all file changes
39
58
  #
40
- # @param file <String> absolute filepath
41
- # @yield <Git::Log>
42
- def checkout_on_file_change(file)
59
+ # @yield [Githack::Leak]
60
+ def get_leaks(*files)
61
+ leaks = []
43
62
  @git.checkout 'master'
44
- begin
45
- @git.log.object(file).each do |commit|
46
- @git.checkout commit
47
- next unless File.exist? file
48
63
 
49
- yield commit
64
+ files.each do |file|
65
+ begin
66
+ @git.log.object(file).each do |commit|
67
+ @git.checkout commit
68
+ next unless File.exist? file
69
+
70
+ leak = Githack::Leak.new(commit.sha, file)
71
+ leaks << leak
72
+
73
+ yield leak if block_given?
74
+ end
75
+ rescue StandardError
76
+ Psych::BadAlias
50
77
  end
51
- rescue StandardError
52
- Psych::BadAlias
78
+ @git.checkout 'master'
53
79
  end
54
- @git.checkout 'master'
80
+
81
+ leaks
55
82
  end
56
83
  end
57
84
  end
@@ -1,3 +1,3 @@
1
1
  module Githack
2
- VERSION = '0.2.0'.freeze
2
+ VERSION = '0.3.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: githack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rousseau Alexandre
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-19 00:00:00.000000000 Z
11
+ date: 2018-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: git
@@ -101,7 +101,11 @@ files:
101
101
  - bin/setup
102
102
  - githack.gemspec
103
103
  - lib/githack.rb
104
- - lib/githack/rails_repository.rb
104
+ - lib/githack/leak.rb
105
+ - lib/githack/repositories/cakephp.rb
106
+ - lib/githack/repositories/laravel.rb
107
+ - lib/githack/repositories/rails.rb
108
+ - lib/githack/repositories/symfony.rb
105
109
  - lib/githack/repository.rb
106
110
  - lib/githack/version.rb
107
111
  homepage: https://github.com/madeindjs/githack
@@ -1,35 +0,0 @@
1
- require 'githack/repository'
2
-
3
- module Githack
4
- class RailsRepository < Repository
5
- # Get all changements for config/secrets.yml file (who contains some API keys)
6
- def search_rails_config_secrets
7
- results = []
8
-
9
- absolute_file_path = File.join @path, 'config', 'secrets.yml'
10
-
11
- checkout_on_yaml_file_change(absolute_file_path) do |secrets|
12
- results << secrets
13
- end
14
-
15
- results.uniq
16
- end
17
-
18
- # Get all changements for config/database.yml file (who contains database configuration for Ruby on Rails Framework)
19
- def search_rails_config_database
20
- results = []
21
-
22
- absolute_file_path = File.join @path, 'config', 'database.yml'
23
-
24
- checkout_on_yaml_file_change(absolute_file_path) do |configs|
25
- configs.each do |config|
26
- config_data = config[1]
27
- next if config_data['adapter'] == 'sqlite3'
28
- results << config_data
29
- end
30
- end
31
-
32
- results.uniq
33
- end
34
- end
35
- end