violent_ruby 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,38 @@
1
+ # Unix Password Cracker
2
+
3
+ The unix password cracker provide a simple interface to crack unix passwords. As hackers do.
4
+
5
+ ## Initialization
6
+
7
+ You can create a new password cracker in a few ways. You can set the `/etc/passwd` and `dictionary` file later if you want to:
8
+
9
+ ### Create a new Unix Password Cracker, with a Config
10
+
11
+ ```ruby
12
+ require 'violent_ruby'
13
+ config = { file: "/etc/passwd", dictionry: "dictionary.txt" }
14
+ upc = ViolentRuby::UnixPasswordCracker.new(config)
15
+ ```
16
+
17
+ ### Create a new Unix Password Cracker, setting stuff later
18
+
19
+ ```ruby
20
+ require 'violent_ruby'
21
+ upc = ViolentRuby::UnixPasswordCracker.new
22
+ upc.file = "/etc/passwd"
23
+ upc.dictionary = "dictionary.txt"
24
+ ```
25
+
26
+ ## Several Ways to Crack'a Password
27
+
28
+ Because aliases are fun. You can crack passwords in a few ways.
29
+
30
+ ```ruby
31
+ require 'violent_ruby'
32
+ upc = ViolentRuby::UnixPasswordCracker.new(file: "/etc/passwd", dictionry: "dictionary.txt")
33
+ upc.crack_passwords
34
+ upc.crack!
35
+ upc.get_crackn
36
+ up.release_the_kraken
37
+ ```
38
+
@@ -0,0 +1,117 @@
1
+ module ViolentRuby
2
+ # Unix Password Cracker provides a friendly interface to
3
+ # crack unix passwords. Because all hackers totes do this.
4
+ # @author Kent 'picat' Gruber
5
+ #
6
+ # == Create a new Unix Password Cracker
7
+ # In order for the password cracker to work, we're going to need a +dictionary+,
8
+ # and an /etc/passwd +file+ we want to crack.
9
+ #
10
+ # @example Basic Usage
11
+ # config = { file: "/etc/passwd", dictionry: "dictionary.txt" }
12
+ # upc = ViolentRuby::UnixPasswordCracker.new(config)
13
+ # upc.crack!
14
+ class UnixPasswordCracker
15
+ # @attr [String] file Path to /etc/passwd file.
16
+ attr_accessor :file
17
+ # @attr [String] dictionary Path to dictionary file.
18
+ attr_accessor :dictionary
19
+
20
+ # Create a new Unix Password Cracker.
21
+ #
22
+ # @param [Hash] args The options to create a new Unix Password Cracker.
23
+ # @param args [String] :file The path to an /etc/passwd file.
24
+ # @param args [String] :dictionary The path to a dictionry of passwords.
25
+ def initialize(args = {})
26
+ @file = false
27
+ @dictionary = false
28
+ if args[:file] && File.readable?(args[:file])
29
+ @file = args[:file]
30
+ @credentials = parse_etc_file(file: args[:file])
31
+ end
32
+ return unless args[:dictionary]
33
+ return unless File.readable?(args[:dictionary])
34
+ @dictionary = args[:dictionary]
35
+ end
36
+
37
+ # Parse a unix /etc/passwd file into a more mangeable form.
38
+ #
39
+ # @param [Hash] args The options when parsing the file.
40
+ # @param args [String] :file The path to an /etc/passwd file.
41
+ # @param args [Boolean] :users Specify that only users should be returned ( default: +false+ ).
42
+ # @param args [Boolean] :passwords Specify that only passwords should be returned ( default: +false+ ).
43
+ # @return [Hash]
44
+ def parse_etc_file(args = {})
45
+ raise 'No /etc/passwd file given.' unless args[:file]
46
+ raise "File #{args[:file]} not readable!" unless File.readable?(args[:file])
47
+ lines = File.readlines(args[:file]).collect do |line|
48
+ line unless line.split(':').first.chars.first.include?('#')
49
+ end
50
+ users = lines.collect { |x| x.split(':')[0] }.map(&:strip)
51
+ return users if args[:users]
52
+ passwords = lines.collect { |x| x.split(':')[1] }.map(&:strip)
53
+ return passwords if args[:passwords]
54
+ users_passwords = Hash[users.zip(passwords)]
55
+ if block_given?
56
+ users_passwords.each do |user, password|
57
+ yield user, password
58
+ end
59
+ else
60
+ users_passwords
61
+ end
62
+ end
63
+
64
+ # Crack unix passwords.
65
+ #
66
+ # @param [Hash] args The options when crack'n some passwords.
67
+ # @param args [String] :file The path to an /etc/passwd file.
68
+ # @param args [String] :dictionary The path to a dictionry of passwords.
69
+ # @return [Array<Hash>]
70
+ def crack_passwords(args = {})
71
+ file = args[:file] || @file
72
+ dict = args[:dictionary] || @dictionary
73
+ results = []
74
+ parse_etc_file(file: file) do |user, password|
75
+ File.readlines(dict).map(&:strip).each do |word|
76
+ results << format_result(user, password, word) if cracked?(password, word)
77
+ end
78
+ end
79
+ results
80
+ end
81
+
82
+ alias crack! crack_passwords
83
+
84
+ alias get_crackn crack_passwords
85
+
86
+ alias release_the_kraken crack_passwords
87
+
88
+ # Check if a given encrypted password matches a given plaintext
89
+ # word when the same crytographic operation is performed on it.
90
+ #
91
+ # @param [String] encrypted_password The encrypted password to check against.
92
+ # @param [String] word The plaintext password to check against.
93
+ # @return [Boolean]
94
+ def check_password(encrypted_password, word)
95
+ if word.strip.crypt(encrypted_password[0, 2]) == encrypted_password
96
+ true
97
+ else
98
+ false
99
+ end
100
+ end
101
+
102
+ alias cracked? check_password
103
+
104
+ private
105
+
106
+ # @api private
107
+ # Format the results for the password crack'n.
108
+ #
109
+ # @param [String] user
110
+ # @param [String] encrypted_pass
111
+ # @param [String] plaintext_pass
112
+ # @return [Hash]
113
+ def format_result(user, encrypted_pass, plaintext_pass)
114
+ { username: user, encrypted_password: encrypted_pass, plaintext_password: plaintext_pass }
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,3 @@
1
+ module ViolentRuby
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,88 @@
1
+ # Vulnerability Scanner
2
+
3
+ The vulnerability scanner class provides a simple way to check if service banners match a list of known vulnerabilities.
4
+
5
+ ## Initialization
6
+
7
+ The Vulnerability Scanner scanner class can be setup in a few flexible ways.
8
+
9
+ ### Basic Setup
10
+
11
+ Provide no targets, ip addresses or even a file. I'll be there for you~
12
+
13
+ ```ruby
14
+ require 'violent_ruby'
15
+ scanner = ViolentRuby::VulnerabilityScanner.new
16
+ ```
17
+
18
+ ### Provide Some Targets with Setup
19
+
20
+ Targets are the known IP addresses for the scanner class. Though, note: you can scan IP addresses that are set during the scan method call. Because I do like flexibility quite a bit, don't I?
21
+
22
+ ```ruby
23
+ require 'violent_ruby'
24
+ ipaddrs = ['192.168.0.2', '192.168.0.3', '192.168.0.4']
25
+ scanner = ViolentRuby::VulnerabilityScanner.new(targets: ipaddrs)
26
+ ```
27
+
28
+ ### Provide a Dictionary with Setup
29
+
30
+ Because you can do that.
31
+
32
+ ```ruby
33
+ require 'violent_ruby'
34
+ scanner = ViolentRuby::VulnerabilityScanner.new(dictionary: "known_vulnerable_banners.txt")
35
+ ```
36
+
37
+ ## Banner Grabbing
38
+
39
+ Maybe you just wana grab some banners? I feel you bruhv. Let's do that.
40
+
41
+ ### Grab Banner from 192.168.0.2 on port 8080
42
+
43
+ ```ruby
44
+ require 'violent_ruby'
45
+ scanner = ViolentRuby::VulnerabilityScanner.new
46
+ scanner.retrieve_banner('192.168.0.2', 8080)
47
+ # => "MS-IIS WEB SERVER 5.0"
48
+ ```
49
+
50
+ ### Banner Grabbing, in'a Block
51
+
52
+ Because maybe expressing things in blocks is just the best thing every.
53
+
54
+ ```ruby
55
+ require 'violent_ruby'
56
+ scanner = ViolentRuby::VulnerabilityScanner.new
57
+ scanner.retrieve_banner('192.168.0.2', 8080) do |banner|
58
+ puts "Banner found: " + banner if banner
59
+ end
60
+ ```
61
+
62
+ ## Basic Scanning
63
+
64
+ The Vulnerability Scanner class does have a `scan()` method, because that makes a lot of sense!
65
+
66
+ ### Method to the Madness
67
+
68
+ The scan method provides most of the underlying magic for this class.
69
+
70
+ ```ruby
71
+ require 'violent_ruby'
72
+ scanner = ViolentRuby::VulnerabilityScanner.new
73
+ scanner.scan(ip: "192.168.0.2", port: 8080, file: "dictionary.txt")
74
+ ```
75
+
76
+ ```ruby
77
+ require 'violent_ruby'
78
+ scanner = ViolentRuby::VulnerabilityScanner.new
79
+ scanner.scan(ips: ["192.168.0.2", "192.168.0.3" ], port: 8080, file: "dictionary.txt")
80
+ ```
81
+
82
+ ```ruby
83
+ require 'violent_ruby'
84
+ scanner = ViolentRuby::VulnerabilityScanner.new
85
+ scanner.file = "dictionary.txt"
86
+ scanner.scan(ips: ["192.168.0.2", "192.168.0.3" ], ports: [80, 8080])
87
+ ```
88
+
@@ -0,0 +1,275 @@
1
+ require 'socket'
2
+ require 'timeout'
3
+
4
+ module ViolentRuby
5
+ # Vulnerability Scanner provides a friendly interface to easily manage
6
+ # banner grabbing +targets+ to match a list of +known vulnerable services+
7
+ # that we want to identify.
8
+ # @author Kent 'picat' Gruber
9
+ #
10
+ # == Create a new Vulnerability Scanner
11
+ # The Vulnerability Scanner scanner class can be setup in a few flexible ways.
12
+ #
13
+ # @example Provide no targets, ip addresses or even a file.
14
+ # scanner = ViolentRuby::VulnerabilityScanner.new
15
+ #
16
+ # @example Provide targets.
17
+ # ipaddrs = ['192.168.0.2', '192.168.0.3', '192.168.0.4']
18
+ # scanner = ViolentRuby::VulnerabilityScanner.new(targets: ipaddrs)
19
+ #
20
+ # @example Provide a file of known vulnerabilities.
21
+ # scanner = ViolentRuby::VulnerabilityScanner.new(known_vulnerabilities: "vuln_banners.txt")
22
+ #
23
+ # @example Just set targets and provide a file later.
24
+ # scanner = ViolentRuby::VulnerabilityScanner.new
25
+ # ['192.168.0.2', '192.168.0.3'].each do |ip|
26
+ # scanner.targets << ip
27
+ # end
28
+ # scanner.targets
29
+ # # => ['192.168.0.2', '192.168.0.3']
30
+ # File.readlines("vuln_banners.txt").map(&:strip).each |banner|
31
+ # scanner.known_vulnerabilities << banner
32
+ # end
33
+ # # => ['MS-IIS WEB SERVER 4.0', 'MS-IIS WEB SERVER 5.0']
34
+ # scanner.scan
35
+ #
36
+ # == Banner Grabbing
37
+ # The Vulnerability Scanner provides a simple banner grabbing method which can be used.
38
+ #
39
+ # @example Connect to 192.168.0.2 on port 8080
40
+ # scanner = ViolentRuby::VulnerabilityScanner.new
41
+ #
42
+ # # If no banner, or hit timeout.
43
+ # scanner.retrieve_banner('192.168.0.2', 8080)
44
+ # # => false
45
+ #
46
+ # # If banner exists.
47
+ # scanner.retrieve_banner('192.168.0.2', 80)
48
+ # # => "MS-IIS WEB SERVER 5.0"
49
+ #
50
+ # @example Connect to 192.168.0.2 on port 8080, trying for 10 seconds
51
+ # scanner = ViolentRuby::VulnerabilityScanner.new
52
+ # scanner.retrieve_banner('192.168.0.2', 8080, 10)
53
+ #
54
+ # @example Connect to 192.168.0.2 on port 8080, with a given block
55
+ # scanner = ViolentRuby::VulnerabilityScanner.new
56
+ # scanner.retrieve_banner('192.168.0.2', 8080) do |banner|
57
+ # # do something with banner ( false if none found )
58
+ # if banner
59
+ # puts "Banner found: " + banner
60
+ # else
61
+ # puts "Banner not found."
62
+ # end
63
+ # end
64
+ #
65
+ # == Example Usage
66
+ # The VulnerabilityScanner is meant to be easy and flexible to use.
67
+ #
68
+ # @example Basic
69
+ # require 'violent_ruby'
70
+ # config = { targets: ['192.168.0.2', '192.168.0.3' ], known_vulnerabilities: 'vulns.txt' }
71
+ # scanner = ViolentRuby::VulnerabilityScanner.new(config)
72
+ # scanner.scan
73
+ #
74
+ # @example Advanced (sort'a)
75
+ # require 'violent_ruby'
76
+ # scanner = ViolentRuby::VulnerabilityScanner.new
77
+ # scanner.targets = ['192.168.0.2', '192.168.0.3' ]
78
+ # scanner.known_vulnerabilities = 'vulns.txt'
79
+ # scanner.scan(port: 8080)
80
+ #
81
+ class VulnerabilityScanner
82
+ # @attr [Array<String>] targets List of target ip addresses.
83
+ attr_accessor :targets
84
+ # @attr [Array<String>] known_vulnerabilities List of known vulnerabilities.
85
+ attr_accessor :known_vulnerabilities
86
+
87
+ # Create a new instance of the vulnerability scanner.
88
+ #
89
+ # @param [Hash] args The options to create a new Vulnerability Scanner. Very optional.
90
+ # @param args [Array<String>] :targets The targets to work with.
91
+ # @param args [Array<String>] :known_vulnerabilities A file containing known vulnerabilities.
92
+ # @return [VulnerabilityScanner]
93
+ def initialize(args = {})
94
+ @targets = []
95
+ @known_vulnerabilities = []
96
+ self.targets = args[:targets] if args[:targets]
97
+ self.known_vulnerabilities = args[:known_vulnerabilities] if args[:known_vulnerabilities]
98
+ end
99
+
100
+ # Retrieve a banner from a given ip and port for a given ammount
101
+ # of seconds, or default for two seconds.
102
+ #
103
+ # @param [String] ip Target ip address.
104
+ # @param [Integer] port Target port number.
105
+ # @param [Integer] seconds Timeout value.
106
+ # @return [String,Boolean]
107
+ def retrieve_banner(ip, port, seconds = 2)
108
+ banner = false
109
+ Timeout.timeout(seconds) do
110
+ socket = TCPSocket.new(ip, port)
111
+ banner = socket.recv(1024)
112
+ socket.close
113
+ end
114
+ return false unless banner
115
+ banner.strip!
116
+ yield banner if block_given?
117
+ banner
118
+ rescue
119
+ false
120
+ end
121
+
122
+ # Check if a given banner is included in a given file which
123
+ # should contain a list of vulnerable banners to match
124
+ # against in order to determine vulnerabilities.
125
+ #
126
+ # @param [String] banner Target banner to check.
127
+ # @param optional [String] file A file containing vulnerable banners.
128
+ # @return [Boolean]
129
+ def check_vulnerabilities(banner, file = false)
130
+ if file
131
+ File.readlines(file).map(&:strip).each do |line|
132
+ return true if line.match?(banner)
133
+ end
134
+ else
135
+ @known_vulnerabilities.each do |vulnerability|
136
+ return true if vulnerability.match?(banner)
137
+ end
138
+ end
139
+ false
140
+ end
141
+
142
+ # Human readable alias.
143
+ alias :vulnerable? :check_vulnerabilities
144
+
145
+ # Do the scanning!
146
+ #
147
+ # @param [Hash] args Scan arguments.
148
+ # @param args [String] :ip @see handle_ip
149
+ # @param args [Array<String>] :ips @see handle_ip
150
+ # @param args [Integer] :port @see handle_port
151
+ # @param args [Array<Integer>] :ports @see handle_port
152
+ # @param args [String] :file @see handle_file
153
+ # @param args [Integer] :timeout @see handle_timeout
154
+ # @return [void]
155
+ def scan(args = {})
156
+ ip_addrs = handle_ip(args)
157
+ ports = handle_port(args)
158
+ timeout = handle_timeout(args)
159
+ file = handle_file(args)
160
+ results = []
161
+ ip_addrs.each do |ip|
162
+ ports.each do |port|
163
+ retrieve_banner(ip, port, timeout) do |banner|
164
+ results << result(ip, port, banner) if vulnerable?(banner, file)
165
+ end
166
+ end
167
+ end
168
+ results
169
+ end
170
+
171
+ # @param [String,Array<String>] args Either a IP address or an array of IP addresses.
172
+ # @return [void]
173
+ def targets=(args)
174
+ if args.is_a? String
175
+ @targets << args
176
+ else args.is_a? Array
177
+ args.each { |target| @targets << target }
178
+ end
179
+ end
180
+
181
+ # @param [String,Array<String>] args Either a banner string or an array of banner strings.
182
+ # @return [void]
183
+ def known_vulnerabilities=(args)
184
+ if File.readable?(args)
185
+ File.readlines(args[:known_vulnerabilities]).map(&:strip).each do |line|
186
+ @known_vulnerabilities << line
187
+ end
188
+ elsif args.is_a? String
189
+ @known_vulnerabilities << args
190
+ elsif args.is_a? Array
191
+ args.each { |vulnerability| @known_vulnerabilities << vulnerability }
192
+ end
193
+ end
194
+
195
+ private
196
+
197
+ # @api private
198
+ # This method manages what is done with the result once we know
199
+ # a vulnerable banner is found.
200
+ #
201
+ # @param [String] ip
202
+ # @param [Integer] port
203
+ # @param [String] banner
204
+ # @return [Hash]
205
+ def result(ip, port, banner)
206
+ {ip: ip, port: port, banner: banner}
207
+ end
208
+
209
+ # @api private
210
+ # This method manages dealing with handling the +ip+ arguments
211
+ # for the +scan+ method in a clean manner.
212
+ #
213
+ # @param [Hash] args
214
+ # @param args [String] :ip Single ip address.
215
+ # @param args [Array<String>] :ips Multiple ip addresses.
216
+ # @return [Array<String>]
217
+ def handle_ip(args = {})
218
+ if args[:ip]
219
+ [args[:ip]]
220
+ elsif args[:ips]
221
+ args[:ips]
222
+ else
223
+ @targets
224
+ end
225
+ end
226
+
227
+ # @api private
228
+ # This method manages dealing with handling the +port+ arguments
229
+ # for the +scan+ method in a clean manner.
230
+ #
231
+ # @param [Hash] args
232
+ # @param args [String] :port Single port.
233
+ # @param args [Array<String>] :ips Multiple ports.
234
+ # @return [Array<Integer>]
235
+ def handle_port(args = {})
236
+ if args[:port]
237
+ [args[:port]]
238
+ elsif args[:ports]
239
+ args[:ports]
240
+ else
241
+ [21, 22, 25, 80, 110, 443]
242
+ end
243
+ end
244
+
245
+ # @api private
246
+ # This method manages dealing with handling the +timeout+ argument
247
+ # for the +scan+ method in a clean manner.
248
+ #
249
+ # @param [Hash] args
250
+ # @param args [Integer] :timeout Timeout in seconds.
251
+ # @return [Integer]
252
+ def handle_timeout(args = {})
253
+ if args[:timeout]
254
+ args[:timeout]
255
+ else
256
+ 2
257
+ end
258
+ end
259
+
260
+ # @api private
261
+ # This method manages dealing with handling the +file+ argument
262
+ # for the +scan+ method in a clean manner.
263
+ #
264
+ # @param [Hash] args
265
+ # @param args [Integer] :file File containing vulnerable banners.
266
+ # @return [String, Boolean]
267
+ def handle_file(args = {})
268
+ if args[:file]
269
+ args[:file]
270
+ else
271
+ false
272
+ end
273
+ end
274
+ end
275
+ end