easywins 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +51 -0
- data/Rakefile +2 -0
- data/bin/easywins +122 -0
- data/easywins.gemspec +28 -0
- data/lib/easywins.rb +99 -0
- data/lib/easywins/http_client.rb +169 -0
- data/lib/easywins/target.rb +77 -0
- data/lib/easywins/version.rb +3 -0
- metadata +156 -0
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Michael Henriksen
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# Easywins
|
2
|
+
|
3
|
+

|
4
|
+
|
5
|
+
Easywins is a simple security tool that can probe a web server for common
|
6
|
+
paths that can be used for gathering information or for gaining a foothold
|
7
|
+
on the system.
|
8
|
+
|
9
|
+
The list of paths is taken from [@mubix's](https://twitter.com/mubix) crowd-sourced
|
10
|
+
list of common *easy win* paths: https://github.com/pwnwiki/webappurls
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
$ gem install easywins
|
15
|
+
|
16
|
+
## Usage
|
17
|
+
|
18
|
+
Usage: easywins [options] base_url
|
19
|
+
|
20
|
+
Probe a web server for common files and endpoints that are useful for gathering information or gaining a foothold.
|
21
|
+
|
22
|
+
v0.1.0
|
23
|
+
|
24
|
+
Options:
|
25
|
+
-h, --help Show command line help
|
26
|
+
-g, --get Use GET requests instead of HEAD (slower but stealthier)
|
27
|
+
-s, --sleep Sleep between 0 and 10 seconds before each request
|
28
|
+
-x, --spoof Spoof X-Forwarded-For header with random IP addresses
|
29
|
+
--timeout SECONDS Request timeout in seconds
|
30
|
+
(default: 2.5)
|
31
|
+
-r, --retries RETRIES Number of retries on failed requests
|
32
|
+
(default: 3)
|
33
|
+
-t, --threads THREADS Number of threads to use
|
34
|
+
(default: 3)
|
35
|
+
--no-verify Don't do SSL verification
|
36
|
+
--no-redirect-check Don't check if server redirects
|
37
|
+
--no-404-check Don't check if server responds with 404
|
38
|
+
--no-color Don't colorize output
|
39
|
+
--version Show help/version info
|
40
|
+
|
41
|
+
### Example:
|
42
|
+
|
43
|
+
$ easywins --sleep --spoof --threads 5 http://somewebsite.com
|
44
|
+
|
45
|
+
## Contributing
|
46
|
+
|
47
|
+
1. Fork it ( https://github.com/michenriksen/easywins/fork )
|
48
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
49
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
50
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
51
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/bin/easywins
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
require 'easywins'
|
5
|
+
|
6
|
+
class App
|
7
|
+
include Methadone::Main
|
8
|
+
include Methadone::CLILogging
|
9
|
+
|
10
|
+
main do |base_url|
|
11
|
+
begin
|
12
|
+
Paint.mode = 0 if options.include?('no-color')
|
13
|
+
|
14
|
+
target = Easywins::Target.new(base_url, {
|
15
|
+
:spoof => options.include?('spoof'),
|
16
|
+
:timeout => options[:timeout].to_f,
|
17
|
+
:retries => options[:retries],
|
18
|
+
:verify => options['no-verify'].nil?
|
19
|
+
})
|
20
|
+
|
21
|
+
not_found_codes = [404]
|
22
|
+
|
23
|
+
print "\n [*] Checking to see if the server is alive... "
|
24
|
+
if target.alive?
|
25
|
+
print Paint["yes, good.\n", :green]
|
26
|
+
else
|
27
|
+
print Paint["nope, exiting.\n", :red]
|
28
|
+
exit!
|
29
|
+
end
|
30
|
+
|
31
|
+
if !options.include?('no-redirect-check')
|
32
|
+
print " [*] Checking to see if the server redirects... "
|
33
|
+
if target.redirects?
|
34
|
+
print Paint["it does.\n", :yellow]
|
35
|
+
puts Paint[" [*] Changing base URL to #{target.base_url}", :yellow]
|
36
|
+
else
|
37
|
+
print Paint["nope.\n", :green]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
if !options.include?('no-404-check')
|
42
|
+
print " [*] Checking to see if the server responds with 404... "
|
43
|
+
not_found_probe = target.request("/#{SecureRandom.urlsafe_base64}")
|
44
|
+
if not_found_probe.code == 404
|
45
|
+
print Paint["yes, good.\n", :green]
|
46
|
+
else
|
47
|
+
if not_found_probe.code == 200
|
48
|
+
print Paint["#{not_found_probe.code} #{not_found_probe.message}\n", :red]
|
49
|
+
puts Paint[" [*] The server responds with 200 OK. Be prepared for tons of false-positives!", :red]
|
50
|
+
else
|
51
|
+
print Paint["#{not_found_probe.code} #{not_found_probe.message}.\n", :yellow]
|
52
|
+
puts Paint[" [*] Treating #{not_found_probe.code} responses as Not Found.", :yellow]
|
53
|
+
not_found_codes << not_found_probe.code
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
puts " [*] Checking the server for #{Easywins::PATHS.count} interesting paths...\n\n"
|
59
|
+
|
60
|
+
thread_pool = Thread.pool(options[:threads].to_i)
|
61
|
+
column_width = Easywins::PATHS.max { |a, b| a.length <=> b.length }.length + target.base_url.length
|
62
|
+
|
63
|
+
Easywins::PATHS.shuffle.each do |path|
|
64
|
+
thread_pool.process do
|
65
|
+
sleep Random.rand(10) if options.include?('sleep')
|
66
|
+
begin
|
67
|
+
url = "#{target.base_url}#{path}"
|
68
|
+
result = target.request(path, options.include?('get'))
|
69
|
+
|
70
|
+
if result.code == 200
|
71
|
+
puts Paint[" #{url.ljust(column_width)} #{result.code} #{result.message}", :green]
|
72
|
+
else
|
73
|
+
if !not_found_codes.include?(result.code)
|
74
|
+
puts Paint[" #{url.ljust(column_width)} #{result.code} #{result.message}", :yellow]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
rescue => e
|
78
|
+
puts Paint[" #{url.ljust(column_width)} FAILED: #{e.class}", :red]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
thread_pool.shutdown
|
84
|
+
|
85
|
+
puts Paint["\n [*] Done!\n", :green]
|
86
|
+
|
87
|
+
rescue Exception => e
|
88
|
+
if e.is_a?(OptionParser::ParseError) || e.is_a?(ArgumentError)
|
89
|
+
help_now!
|
90
|
+
elsif e.is_a?(Interrupt)
|
91
|
+
puts Paint["\n\n [*] Interrupted.\n", :yellow]
|
92
|
+
elsif e.is_a?(OpenSSL::SSL::SSLError)
|
93
|
+
puts Paint["\n\n [*] There's a problem with the server's SSL certificate. Use the --no-verify option if you know what you're doing.\n", :red]
|
94
|
+
else
|
95
|
+
puts Paint["\n\n [*] WARP CORE BREACH!", :red]
|
96
|
+
puts Paint[" #{e.class}: #{e.message}\n", :red]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
options['threads'] = 3
|
102
|
+
options['timeout'] = Easywins::HttpClient::DEFAULT_TIMEOUT
|
103
|
+
options['retries'] = Easywins::HttpClient::DEFAULT_RETRIES
|
104
|
+
|
105
|
+
on('-g', '--get', "Use GET requests instead of HEAD (slower but stealthier)")
|
106
|
+
on('-s', '--sleep', "Sleep between 0 and 10 seconds before each request")
|
107
|
+
on('-x', '--spoof', "Spoof X-Forwarded-For header with random IP addresses")
|
108
|
+
on('-t', '--timeout SECONDS', "Request timeout in seconds")
|
109
|
+
on('-r', '--retries RETRIES', "Number of retries on failed requests")
|
110
|
+
on('-t THREADS', '--threads', "Number of threads to use")
|
111
|
+
on('--no-verify', "Don't do SSL verification")
|
112
|
+
on('--no-redirect-check', "Don't check if server redirects")
|
113
|
+
on('--no-404-check', "Don't check if server responds with 404")
|
114
|
+
on('--no-color', "Don't colorize output")
|
115
|
+
|
116
|
+
arg :base_url
|
117
|
+
|
118
|
+
description "Probe a web server for common files and endpoints that are useful for gathering information or gaining a foothold."
|
119
|
+
version Easywins::VERSION
|
120
|
+
|
121
|
+
go!
|
122
|
+
end
|
data/easywins.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'easywins/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "easywins"
|
8
|
+
spec.version = Easywins::VERSION
|
9
|
+
spec.authors = ["Michael Henriksen"]
|
10
|
+
spec.email = ["michenriksen@neomailbox.ch"]
|
11
|
+
spec.summary = %q{Probe a web server for common files and endpoints that are useful for gathering information or gaining a foothold.}
|
12
|
+
spec.description = %q{Probe a web server for common files and endpoints that are useful for gathering information or gaining a foothold.}
|
13
|
+
spec.homepage = "https://github.com/michenriksen/easywins"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'httparty'
|
22
|
+
spec.add_dependency 'methadone'
|
23
|
+
spec.add_dependency 'paint'
|
24
|
+
spec.add_dependency 'thread'
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
27
|
+
spec.add_development_dependency "rake"
|
28
|
+
end
|
data/lib/easywins.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'net/http'
|
3
|
+
require 'httparty'
|
4
|
+
require 'methadone'
|
5
|
+
require 'paint'
|
6
|
+
require 'thread/pool'
|
7
|
+
|
8
|
+
require 'easywins/version'
|
9
|
+
require 'easywins/http_client'
|
10
|
+
require 'easywins/target'
|
11
|
+
|
12
|
+
module Easywins
|
13
|
+
PATHS = [
|
14
|
+
'/.bzr/README',
|
15
|
+
'/.git/config',
|
16
|
+
'/.hg/requires',
|
17
|
+
'/.htaccess',
|
18
|
+
'/.htpasswd',
|
19
|
+
'/.svn/wc.db',
|
20
|
+
'/_layouts/groups.aspx',
|
21
|
+
'/_layouts/people.aspx',
|
22
|
+
'/access.log',
|
23
|
+
'/admin',
|
24
|
+
'/admin.nsf',
|
25
|
+
'/administration/index.php',
|
26
|
+
'/administrator/',
|
27
|
+
'/apc.php',
|
28
|
+
'/awstats/',
|
29
|
+
'/axis2/axis2-web/HappyAxis.jsp',
|
30
|
+
'/backup.tar.gz',
|
31
|
+
'/backup/',
|
32
|
+
'/backups/',
|
33
|
+
'/bb-admin',
|
34
|
+
'/c99.php',
|
35
|
+
'/cacti',
|
36
|
+
'/CFIDE/adminapi/administrator.cfc',
|
37
|
+
'/CFIDE/administrator/enter.cfm',
|
38
|
+
'/CFIDE/administrator/index.cfm',
|
39
|
+
'/CFIDE/scripts/ajax/FCKeditor/editor/filemanager/connectors/cfm/upload.cfm',
|
40
|
+
'/cgi-bin/cvsweb',
|
41
|
+
'/cgi-bin/php',
|
42
|
+
'/cgi-bin/php5',
|
43
|
+
'/CHANGELOG.txt',
|
44
|
+
'/console/',
|
45
|
+
'/crossdomain.xml',
|
46
|
+
'/data',
|
47
|
+
'/dev/',
|
48
|
+
'/elmah.axd',
|
49
|
+
'/error.log',
|
50
|
+
'/exchange/',
|
51
|
+
'/files',
|
52
|
+
'/ghost',
|
53
|
+
'/include/',
|
54
|
+
'/includes/',
|
55
|
+
'/index.php?-s',
|
56
|
+
'/index.php?url=admin',
|
57
|
+
'/info.php',
|
58
|
+
'/install',
|
59
|
+
'/INSTALL.txt',
|
60
|
+
'/install/upgrade.php',
|
61
|
+
'/jmx-console/',
|
62
|
+
'/login',
|
63
|
+
'/logon',
|
64
|
+
'/logs/',
|
65
|
+
'/manager',
|
66
|
+
'/manager/html',
|
67
|
+
'/manual/',
|
68
|
+
'/na_admin/ataglance.html',
|
69
|
+
'/owa',
|
70
|
+
'/pgmyadmin/',
|
71
|
+
'/phpinfo.php',
|
72
|
+
'/phpmyadmin/',
|
73
|
+
'/plesk',
|
74
|
+
'/pls/admin',
|
75
|
+
'/private',
|
76
|
+
'/Providers/HtmlEditorProviders/Fck/fcklinkgallery.aspx',
|
77
|
+
'/README.txt',
|
78
|
+
'/robots.txt',
|
79
|
+
'/rockmongo/index.php',
|
80
|
+
'/server-status',
|
81
|
+
'/sitemap.xml',
|
82
|
+
'/sites/default/files/backup_migrate/',
|
83
|
+
'/temp',
|
84
|
+
'/test.php',
|
85
|
+
'/test/',
|
86
|
+
'/tmp',
|
87
|
+
'/trace.axd',
|
88
|
+
'/upload/',
|
89
|
+
'/uploads/',
|
90
|
+
'/user.php',
|
91
|
+
'/webalizer/',
|
92
|
+
'/webdav/',
|
93
|
+
'/webmin',
|
94
|
+
'/WorkArea/version.xml',
|
95
|
+
'/wp-admin/',
|
96
|
+
'/wsman',
|
97
|
+
'/xampp/'
|
98
|
+
]
|
99
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'ipaddr'
|
2
|
+
|
3
|
+
module Easywins
|
4
|
+
class HttpClient
|
5
|
+
include HTTParty
|
6
|
+
|
7
|
+
follow_redirects false
|
8
|
+
|
9
|
+
class UnhandledError < StandardError; end
|
10
|
+
|
11
|
+
DEFAULT_TIMEOUT = 2.5 #seconds
|
12
|
+
DEFAULT_RETRIES = 3
|
13
|
+
|
14
|
+
HANDLED_EXCEPTIONS = [
|
15
|
+
SocketError,
|
16
|
+
Timeout::Error,
|
17
|
+
Errno::ETIMEDOUT,
|
18
|
+
Errno::ECONNRESET,
|
19
|
+
Errno::ECONNREFUSED,
|
20
|
+
Errno::ENETUNREACH,
|
21
|
+
Errno::EHOSTUNREACH,
|
22
|
+
EOFError
|
23
|
+
]
|
24
|
+
|
25
|
+
USER_AGENTS = [
|
26
|
+
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36',
|
27
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14',
|
28
|
+
'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0',
|
29
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36',
|
30
|
+
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36',
|
31
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:28.0) Gecko/20100101 Firefox/28.0',
|
32
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36',
|
33
|
+
'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36',
|
34
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36',
|
35
|
+
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36',
|
36
|
+
'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko',
|
37
|
+
'Mozilla/5.0 (Windows NT 6.1; rv:28.0) Gecko/20100101 Firefox/28.0',
|
38
|
+
'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36',
|
39
|
+
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:28.0) Gecko/20100101 Firefox/28.0',
|
40
|
+
'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0',
|
41
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.74.9 (KHTML, like Gecko) Version/7.0.2 Safari/537.74.9',
|
42
|
+
'Mozilla/5.0 (iPhone; CPU iPhone OS 7_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D167 Safari/9537.53',
|
43
|
+
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36',
|
44
|
+
'Mozilla/5.0 (Windows NT 5.1; rv:28.0) Gecko/20100101 Firefox/28.0',
|
45
|
+
'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36',
|
46
|
+
'Mozilla/5.0 (iPad; CPU OS 7_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D167 Safari/9537.53',
|
47
|
+
'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36',
|
48
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36',
|
49
|
+
'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0',
|
50
|
+
'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36',
|
51
|
+
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36',
|
52
|
+
'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36',
|
53
|
+
'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)',
|
54
|
+
'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36',
|
55
|
+
'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)',
|
56
|
+
'Mozilla/5.0 (X11; Linux x86_64; rv:28.0) Gecko/20100101 Firefox/28.0',
|
57
|
+
'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0',
|
58
|
+
'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko',
|
59
|
+
'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0',
|
60
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:28.0) Gecko/20100101 Firefox/28.0',
|
61
|
+
'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36',
|
62
|
+
'Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D201 Safari/9537.53',
|
63
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:28.0) Gecko/20100101 Firefox/28.0',
|
64
|
+
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/33.0.1750.152 Chrome/33.0.1750.152 Safari/537.36',
|
65
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36',
|
66
|
+
'Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko',
|
67
|
+
'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36',
|
68
|
+
'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36',
|
69
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:28.0) Gecko/20100101 Firefox/28.0',
|
70
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36',
|
71
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/6.1.3 Safari/537.75.14',
|
72
|
+
'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36',
|
73
|
+
'Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:28.0) Gecko/20100101 Firefox/28.0',
|
74
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:29.0) Gecko/20100101 Firefox/29.0',
|
75
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.59.10 (KHTML, like Gecko) Version/5.1.9 Safari/534.59.10',
|
76
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36',
|
77
|
+
'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0',
|
78
|
+
'Mozilla/5.0 (iPhone; CPU iPhone OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B554a Safari/9537.53',
|
79
|
+
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.132 Safari/537.36',
|
80
|
+
'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0',
|
81
|
+
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36',
|
82
|
+
'Mozilla/5.0 (iPad; CPU OS 7_1_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D201 Safari/9537.53',
|
83
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.74.9 (KHTML, like Gecko) Version/6.1.2 Safari/537.74.9',
|
84
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/6.1.3 Safari/537.75.14',
|
85
|
+
'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko',
|
86
|
+
'Mozilla/5.0 (iPad; CPU OS 7_0_6 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B651 Safari/9537.53',
|
87
|
+
'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36',
|
88
|
+
'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0',
|
89
|
+
'Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20140319 Firefox/24.0 Iceweasel/24.4.0',
|
90
|
+
'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)',
|
91
|
+
'Mozilla/5.0 (iPad; CPU OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B554a Safari/9537.53',
|
92
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/536.30.1 (KHTML, like Gecko) Version/6.0.5 Safari/536.30.1',
|
93
|
+
'Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36',
|
94
|
+
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36',
|
95
|
+
'Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0',
|
96
|
+
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:29.0) Gecko/20100101 Firefox/29.0',
|
97
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36',
|
98
|
+
'Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.114 Mobile Safari/537.36',
|
99
|
+
'Mozilla/5.0 (Windows NT 6.0; rv:28.0) Gecko/20100101 Firefox/28.0',
|
100
|
+
'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)',
|
101
|
+
'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)',
|
102
|
+
'Mozilla/5.0 (iPad; CPU OS 7_1 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) CriOS/33.0.1750.21 Mobile/11D167 Safari/9537.53',
|
103
|
+
'Mozilla/5.0 (iPhone; CPU iPhone OS 7_0_6 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B651 Safari/9537.53',
|
104
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.74.9 (KHTML, like Gecko) Version/6.1.2 Safari/537.74.9',
|
105
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11'
|
106
|
+
]
|
107
|
+
|
108
|
+
def initialize(config = {})
|
109
|
+
@config = {
|
110
|
+
:timeout => DEFAULT_TIMEOUT,
|
111
|
+
:retries => DEFAULT_RETRIES
|
112
|
+
}.merge(config)
|
113
|
+
default_timeout = @config[:timeout]
|
114
|
+
end
|
115
|
+
|
116
|
+
def do_head(path, params=nil, opt={})
|
117
|
+
do_request(:head, path, {:query => params}.merge(opt))
|
118
|
+
end
|
119
|
+
|
120
|
+
def do_get(path, params=nil, opt={})
|
121
|
+
do_request(:get, path, {:query => params}.merge(opt))
|
122
|
+
end
|
123
|
+
|
124
|
+
def do_post(path, params=nil, opt={})
|
125
|
+
do_request(:post, path, {:body => params}.merge(opt))
|
126
|
+
end
|
127
|
+
|
128
|
+
def do_put(path, params=nil, opt={})
|
129
|
+
do_request(:put, path, {:body => params}.merge(opt))
|
130
|
+
end
|
131
|
+
|
132
|
+
def do_delete(path, params=nil, opt={})
|
133
|
+
do_request(:delete, path, {:query => params}.merge(opt))
|
134
|
+
end
|
135
|
+
|
136
|
+
private
|
137
|
+
|
138
|
+
def do_request(method, path, options)
|
139
|
+
o = {
|
140
|
+
:headers => {
|
141
|
+
'User-Agent' => random_user_agent
|
142
|
+
}
|
143
|
+
}.merge(options)
|
144
|
+
o[:headers]['X-Forwarded-for'] = random_ip_address if @config[:spoof]
|
145
|
+
with_retries do
|
146
|
+
self.class.send(method, path, o)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def with_retries(&block)
|
151
|
+
tries ||= @config[:retries]
|
152
|
+
yield
|
153
|
+
rescue *HANDLED_EXCEPTIONS => ex
|
154
|
+
if (tries -= 1) > 0
|
155
|
+
sleep 0.2
|
156
|
+
retry
|
157
|
+
end
|
158
|
+
raise ex
|
159
|
+
end
|
160
|
+
|
161
|
+
def random_user_agent
|
162
|
+
USER_AGENTS.sample
|
163
|
+
end
|
164
|
+
|
165
|
+
def random_ip_address
|
166
|
+
ipv4 = IPAddr.new(rand(2**32), Socket::AF_INET).to_s
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
module Easywins
|
4
|
+
class Target
|
5
|
+
|
6
|
+
attr_reader :base_url
|
7
|
+
|
8
|
+
URL_REGEX = /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?\??$/
|
9
|
+
REDIRECT_CODES = [300, 301, 302, 303, 305]
|
10
|
+
|
11
|
+
class InvalidBaseUrlError < StandardError; end
|
12
|
+
class TooManyRedirectsError < StandardError; end
|
13
|
+
|
14
|
+
def initialize(base_url, options = {})
|
15
|
+
@base_url = validate_and_normalize_url!(base_url)
|
16
|
+
@options = options
|
17
|
+
end
|
18
|
+
|
19
|
+
def request(path, use_get = false)
|
20
|
+
url = "#{@base_url}#{path}"
|
21
|
+
if use_get
|
22
|
+
http_client.do_get(url, {}, :verify => @options[:verify])
|
23
|
+
else
|
24
|
+
http_client.do_head(url, {}, :verify => @options[:verify])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def alive?
|
29
|
+
response = request('/', true)
|
30
|
+
rescue *HttpClient::HANDLED_EXCEPTIONS
|
31
|
+
false
|
32
|
+
end
|
33
|
+
|
34
|
+
def redirects?
|
35
|
+
final_url = validate_and_normalize_url!(follow_redirects!("#{@base_url}/"))
|
36
|
+
if @base_url != final_url
|
37
|
+
@base_url = final_url
|
38
|
+
true
|
39
|
+
else
|
40
|
+
false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def validate_and_normalize_url!(url)
|
47
|
+
url = "http://#{url}" unless url =~ /^https?:\/\//i
|
48
|
+
raise InvalidBaseUrlError.new("#{url} is an invalid URL") unless valid_url?(url)
|
49
|
+
normalized_url = url.dup
|
50
|
+
use_ssl = (normalized_url =~ /^https/) || (normalized_url =~ /:443\b/)
|
51
|
+
ends_with_slash = normalized_url =~ /\/$/
|
52
|
+
|
53
|
+
normalized_url.chop! if ends_with_slash
|
54
|
+
normalized_url.gsub!(/^https?:\/\//i, '')
|
55
|
+
|
56
|
+
"http#{'s' if use_ssl}://#{normalized_url}".downcase
|
57
|
+
end
|
58
|
+
|
59
|
+
def follow_redirects!(url, redirects = 5)
|
60
|
+
raise TooManyRedirectsError.new() if redirects.zero?
|
61
|
+
response = http_client.do_get(url, {}, :verify => @options[:verify])
|
62
|
+
if REDIRECT_CODES.include?(response.code)
|
63
|
+
follow_redirects!(response.headers['location'], redirects-1)
|
64
|
+
else
|
65
|
+
url
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def valid_url?(url)
|
70
|
+
url =~ URL_REGEX
|
71
|
+
end
|
72
|
+
|
73
|
+
def http_client
|
74
|
+
@http_client ||= HttpClient.new(@options)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
metadata
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: easywins
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michael Henriksen
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-05-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: httparty
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: methadone
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: paint
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: thread
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: bundler
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '1.6'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '1.6'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: rake
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
description: Probe a web server for common files and endpoints that are useful for
|
111
|
+
gathering information or gaining a foothold.
|
112
|
+
email:
|
113
|
+
- michenriksen@neomailbox.ch
|
114
|
+
executables:
|
115
|
+
- easywins
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- .gitignore
|
120
|
+
- Gemfile
|
121
|
+
- LICENSE.txt
|
122
|
+
- README.md
|
123
|
+
- Rakefile
|
124
|
+
- bin/easywins
|
125
|
+
- easywins.gemspec
|
126
|
+
- lib/easywins.rb
|
127
|
+
- lib/easywins/http_client.rb
|
128
|
+
- lib/easywins/target.rb
|
129
|
+
- lib/easywins/version.rb
|
130
|
+
homepage: https://github.com/michenriksen/easywins
|
131
|
+
licenses:
|
132
|
+
- MIT
|
133
|
+
post_install_message:
|
134
|
+
rdoc_options: []
|
135
|
+
require_paths:
|
136
|
+
- lib
|
137
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
138
|
+
none: false
|
139
|
+
requirements:
|
140
|
+
- - ! '>='
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
+
none: false
|
145
|
+
requirements:
|
146
|
+
- - ! '>='
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
149
|
+
requirements: []
|
150
|
+
rubyforge_project:
|
151
|
+
rubygems_version: 1.8.23
|
152
|
+
signing_key:
|
153
|
+
specification_version: 3
|
154
|
+
summary: Probe a web server for common files and endpoints that are useful for gathering
|
155
|
+
information or gaining a foothold.
|
156
|
+
test_files: []
|