moby.rb 1.0.1 → 2.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG +31 -0
- data/Gemfile +4 -0
- data/bin/moby +24 -27
- data/lib/Moby/Backends/MechanizeBackend.rb +157 -0
- data/lib/Moby/Backends/SeleniumBackend.rb +242 -0
- data/lib/Moby/Backends.rb +20 -0
- data/lib/Moby/Configuration.rb +119 -0
- data/lib/Moby/RandomInputGenerator.rb +49 -0
- data/lib/Moby/VERSION.rb +1 -1
- data/lib/Moby.rb +15 -160
- data/lib/Selenium/WebDriver/Driver/Attempt/attempt.rb +18 -0
- data/lib/Selenium/WebDriver/SearchContext/ElementPresentQ/element_presentQ.rb +13 -0
- data/lib/Thoran/Selenium/WebDriver/Driver/Attempt/attempt.rb +53 -0
- data/lib/Thoran/Selenium/WebDriver/SearchContext/ElementPresentQ/element_presentQ.rb +39 -0
- data/moby.rb.gemspec +2 -1
- data/test/Moby/Backends/MechanizeBackend_test.rb +83 -0
- data/test/Moby/Backends/SeleniumBackend_test.rb +44 -0
- data/test/Moby/Backends_test.rb +27 -0
- data/test/Moby/Configuration_test.rb +134 -0
- data/test/Moby/RandomInputGenerator_test.rb +37 -0
- data/test/Moby/VERSION_test.rb +2 -2
- data/test/moby_test.rb +6 -282
- data/test/test_helper.rb +15 -0
- metadata +31 -5
- data/lib/File/self.collect.rb +0 -10
- data/lib/Thoran/File/SelfCollect/self.collect.rb +0 -22
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# test/Moby/Configuration_test.rb
|
|
2
|
+
|
|
3
|
+
require_relative '../test_helper'
|
|
4
|
+
|
|
5
|
+
describe Moby::Configuration do
|
|
6
|
+
let(:url){'https://phishing.example.com/login'}
|
|
7
|
+
|
|
8
|
+
describe "defaults" do
|
|
9
|
+
let(:config){Moby::Configuration.new(url: url)}
|
|
10
|
+
|
|
11
|
+
it "keeps the url" do
|
|
12
|
+
_(config.url).must_equal(url)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "defaults the backend to mechanize" do
|
|
16
|
+
_(config.backend).must_equal(:mechanize)
|
|
17
|
+
_(config.mechanize?).must_equal(true)
|
|
18
|
+
_(config.selenium?).must_equal(false)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "defaults the browser to chrome" do
|
|
22
|
+
_(config.browser).must_equal(:chrome)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "defaults form_number to 0" do
|
|
26
|
+
_(config.form_number).must_equal(0)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "defaults the field names to username and password" do
|
|
30
|
+
_(config.username_field_name).must_equal('username')
|
|
31
|
+
_(config.password_field_name).must_equal('password')
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "defaults the field numbers to 0 and 1" do
|
|
35
|
+
_(config.username_field_number).must_equal(0)
|
|
36
|
+
_(config.password_field_number).must_equal(1)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "runs indefinitely by default" do
|
|
40
|
+
_(config.iterations).must_be_nil
|
|
41
|
+
_(config.fixed_number_of_submissions?).must_equal(false)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "defaults the delay to 0" do
|
|
45
|
+
_(config.delay).must_equal(0)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "is not prefilled, email, verbose or debug by default" do
|
|
49
|
+
_(config.username_prefilled?).must_equal(false)
|
|
50
|
+
_(config.username_is_email_address?).must_equal(false)
|
|
51
|
+
_(config.verbose?).must_equal(false)
|
|
52
|
+
_(config.debug?).must_equal(false)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe "backend and browser selection" do
|
|
57
|
+
it "selects selenium" do
|
|
58
|
+
_(Moby::Configuration.new(url: url, backend: :selenium).selenium?).must_equal(true)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "coerces a string backend to a symbol" do
|
|
62
|
+
_(Moby::Configuration.new(url: url, backend: 'selenium').backend).must_equal(:selenium)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "falls back to mechanize when the backend is nil" do
|
|
66
|
+
_(Moby::Configuration.new(url: url, backend: nil).backend).must_equal(:mechanize)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "falls back to chrome when the browser is nil" do
|
|
70
|
+
_(Moby::Configuration.new(url: url, browser: nil).browser).must_equal(:chrome)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
describe "coercion of string inputs" do
|
|
75
|
+
let(:config) do
|
|
76
|
+
Moby::Configuration.new(
|
|
77
|
+
url: url,
|
|
78
|
+
form_number: '2',
|
|
79
|
+
username_field_number: '3',
|
|
80
|
+
password_field_number: '4',
|
|
81
|
+
delay: '5',
|
|
82
|
+
iterations: '6'
|
|
83
|
+
)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "coerces the numeric switches to integers" do
|
|
87
|
+
_(config.form_number).must_equal(2)
|
|
88
|
+
_(config.username_field_number).must_equal(3)
|
|
89
|
+
_(config.password_field_number).must_equal(4)
|
|
90
|
+
_(config.delay).must_equal(5)
|
|
91
|
+
_(config.iterations).must_equal(6)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "treats a given iterations count as a fixed number of submissions" do
|
|
95
|
+
_(config.fixed_number_of_submissions?).must_equal(true)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
describe "#username_is_email_address?" do
|
|
100
|
+
it "is true when set explicitly" do
|
|
101
|
+
_(Moby::Configuration.new(url: url, username_is_email_address: true).username_is_email_address?).must_equal(true)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "is truthy when a username hostname is given" do
|
|
105
|
+
_(Moby::Configuration.new(url: url, username_hostname: 'example.com').username_is_email_address?).wont_equal(false)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "is truthy when the username field is named email" do
|
|
109
|
+
_(Moby::Configuration.new(url: url, username_field_name: 'email').username_is_email_address?).wont_equal(false)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
describe "#user_agent" do
|
|
114
|
+
it "returns a random agent when not set" do
|
|
115
|
+
agent = Moby::Configuration.new(url: url).user_agent
|
|
116
|
+
_(agent).must_be_kind_of(String)
|
|
117
|
+
_(agent).wont_equal('Mechanize')
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it "returns the set agent" do
|
|
121
|
+
_(Moby::Configuration.new(url: url, user_agent: 'CustomAgent').user_agent).must_equal('CustomAgent')
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
describe "#using_form_name?" do
|
|
126
|
+
it "is false without a form name" do
|
|
127
|
+
_(Moby::Configuration.new(url: url).using_form_name?).must_equal(false)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it "is true with a form name" do
|
|
131
|
+
_(Moby::Configuration.new(url: url, form_name: 'login').using_form_name?).must_equal(true)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# test/Moby/RandomInputGenerator_test.rb
|
|
2
|
+
|
|
3
|
+
require_relative '../test_helper'
|
|
4
|
+
|
|
5
|
+
describe Moby::RandomInputGenerator do
|
|
6
|
+
let(:word_list_path){TestFixtures::WORD_LIST_PATH}
|
|
7
|
+
|
|
8
|
+
def generator(**args)
|
|
9
|
+
Moby::RandomInputGenerator.new(word_list_path: word_list_path, **args)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe "#random_username" do
|
|
13
|
+
it "returns a word from the list by default" do
|
|
14
|
+
_(TestFixtures::WORDS).must_include(generator.random_username)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "returns an email address when username_is_email_address is true" do
|
|
18
|
+
_(generator(username_is_email_address: true).random_username).must_match(/\A[^@]+@[^@]+\z/)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "uses the given hostname for the email address" do
|
|
22
|
+
username = generator(username_hostname: 'example.com', username_is_email_address: true).random_username
|
|
23
|
+
_(username).must_match(/@example\.com\z/)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "generates more than one distinct username" do
|
|
27
|
+
usernames = 20.times.map{generator.random_username}
|
|
28
|
+
_(usernames.uniq.length).must_be(:>, 1)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe "#random_password" do
|
|
33
|
+
it "returns a word from the list" do
|
|
34
|
+
_(TestFixtures::WORDS).must_include(generator.random_password)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/test/Moby/VERSION_test.rb
CHANGED
data/test/moby_test.rb
CHANGED
|
@@ -4,292 +4,16 @@ require_relative './test_helper'
|
|
|
4
4
|
|
|
5
5
|
describe Moby do
|
|
6
6
|
let(:url){'https://phishing.example.com/login'}
|
|
7
|
-
let(:moby){Moby.new(url: url)}
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
# Stub the login page
|
|
13
|
-
stub_request(:get, url)
|
|
14
|
-
.to_return(
|
|
15
|
-
status: 200,
|
|
16
|
-
body: TestFixtures::SIMPLE_LOGIN_FORM,
|
|
17
|
-
headers: {'Content-Type' => 'text/html'}
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
# Stub form submission
|
|
21
|
-
stub_request(:post, 'https://phishing.example.com/login')
|
|
22
|
-
.to_return(status: 200, body: 'Success')
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
after do
|
|
26
|
-
WebMock.reset!
|
|
27
|
-
WebMock.allow_net_connect!
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
describe "initialization" do
|
|
31
|
-
it "accepts url parameter" do
|
|
32
|
-
_(moby.url).must_equal(url)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
it "sets default form_number to 0" do
|
|
36
|
-
_(moby.form_number).must_equal(0)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
it "sets default username_field_name to 'username'" do
|
|
40
|
-
_(moby.username_field_name).must_equal('username')
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
it "sets default password_field_name to 'password'" do
|
|
44
|
-
_(moby.password_field_name).must_equal('password')
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
it "sets default username_field_number to 0" do
|
|
48
|
-
_(moby.username_field_number).must_equal(0)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
it "sets default password_field_number to 1" do
|
|
52
|
-
_(moby.password_field_number).must_equal(1)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
it "accepts form_name parameter" do
|
|
56
|
-
m = Moby.new(url: url, form_name: 'login')
|
|
57
|
-
|
|
58
|
-
_(m.form_name).must_equal('login')
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
it "accepts username_hostname parameter" do
|
|
62
|
-
m = Moby.new(url: url, username_hostname: 'example.com')
|
|
63
|
-
|
|
64
|
-
_(m.username_hostname).must_equal('example.com')
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
it "accepts username_is_email_address parameter" do
|
|
68
|
-
m = Moby.new(url: url, username_is_email_address: true)
|
|
69
|
-
|
|
70
|
-
_(m.username_is_email_address).must_equal(true)
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
describe "mechanize setup" do
|
|
75
|
-
it "creates Mechanize instance lazily" do
|
|
76
|
-
mech = moby.instance_variable_get(:@mechanize)
|
|
77
|
-
|
|
78
|
-
_(mech).must_be_nil
|
|
79
|
-
|
|
80
|
-
moby.send(:mechanize)
|
|
81
|
-
mech = moby.instance_variable_get(:@mechanize)
|
|
82
|
-
|
|
83
|
-
_(mech).must_be_instance_of(Mechanize)
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
it "reuses same mechanize instance" do
|
|
87
|
-
mech1 = moby.send(:mechanize)
|
|
88
|
-
mech2 = moby.send(:mechanize)
|
|
89
|
-
|
|
90
|
-
_(mech1).must_be_same_as(mech2)
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
describe "page loading" do
|
|
95
|
-
it "loads the target URL" do
|
|
96
|
-
page = moby.send(:page)
|
|
97
|
-
|
|
98
|
-
_(page).must_be_instance_of(Mechanize::Page)
|
|
99
|
-
assert_requested(:get, url, times: 1)
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
it "reuses loaded page" do
|
|
103
|
-
page1 = moby.send(:page)
|
|
104
|
-
page2 = moby.send(:page)
|
|
105
|
-
|
|
106
|
-
_(page1).must_be_same_as(page2)
|
|
107
|
-
assert_requested(:get, url, times: 1)
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
it "handles meta refresh redirects" do
|
|
111
|
-
redirect_body = '<html><head><meta http-equiv="Refresh" content="0; url=https://phishing.example.com/real-login"></head></html>'
|
|
112
|
-
|
|
113
|
-
stub_request(:get, url)
|
|
114
|
-
.to_return(status: 200, body: redirect_body, headers: {'Content-Type' => 'text/html'})
|
|
115
|
-
|
|
116
|
-
stub_request(:get, 'https://phishing.example.com/real-login')
|
|
117
|
-
.to_return(status: 200, body: TestFixtures::SIMPLE_LOGIN_FORM, headers: {'Content-Type' => 'text/html'})
|
|
118
|
-
|
|
119
|
-
m = Moby.new(url: url)
|
|
120
|
-
page = m.send(:page)
|
|
121
|
-
|
|
122
|
-
assert_requested(:get, url, times: 1)
|
|
123
|
-
assert_requested(:get, 'https://phishing.example.com/real-login', times: 1)
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
describe "form finding" do
|
|
128
|
-
describe "finding by name" do
|
|
129
|
-
let(:moby) do
|
|
130
|
-
Moby.new(url: url, form_name: 'login')
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
it "finds form by name when form_name is set" do
|
|
134
|
-
moby.send(:page)
|
|
135
|
-
form = moby.send(:form)
|
|
136
|
-
|
|
137
|
-
_(form).must_be_instance_of(Mechanize::Form)
|
|
138
|
-
_(form.name).must_equal('login')
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
describe "finding by number" do
|
|
143
|
-
let(:moby) do
|
|
144
|
-
Moby.new(url: 'https://multi.example.com/page', form_number: 1)
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
it "finds form by number when form_number is set" do
|
|
148
|
-
stub_request(:get, 'https://multi.example.com/page')
|
|
149
|
-
.to_return(
|
|
150
|
-
status: 200,
|
|
151
|
-
body: TestFixtures::MULTIPLE_FORMS,
|
|
152
|
-
headers: {'Content-Type' => 'text/html'}
|
|
153
|
-
)
|
|
154
|
-
moby.send(:page)
|
|
155
|
-
form = moby.send(:form)
|
|
156
|
-
|
|
157
|
-
_(form).must_be_instance_of(Mechanize::Form)
|
|
158
|
-
_(form.node['id']).must_equal('login_form')
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
describe "deafult form" do
|
|
163
|
-
it "defaults to first form" do
|
|
164
|
-
moby.send(:page)
|
|
165
|
-
form = moby.send(:form)
|
|
166
|
-
|
|
167
|
-
_(form).must_be_instance_of(Mechanize::Form)
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
describe "field finding" do
|
|
173
|
-
describe "finding by name" do
|
|
174
|
-
let(:moby) do
|
|
175
|
-
Moby.new(url: url, form_name: 'login', username_field_name: 'username', password_field_name: 'password')
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
it "finds username field by name" do
|
|
179
|
-
moby.send(:page)
|
|
180
|
-
moby.send(:form)
|
|
181
|
-
field = moby.send(:username_field)
|
|
182
|
-
|
|
183
|
-
_(field.name).must_equal('username')
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
it "finds password field by name" do
|
|
187
|
-
moby.send(:page)
|
|
188
|
-
moby.send(:form)
|
|
189
|
-
field = moby.send(:password_field)
|
|
190
|
-
|
|
191
|
-
_(field.name).must_equal('password')
|
|
192
|
-
end
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
describe "finding by number" do
|
|
196
|
-
let(:moby) do
|
|
197
|
-
Moby.new(url: url, username_field_number: 0, password_field_number: 1)
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
it "finds username field by number" do
|
|
201
|
-
moby.send(:page)
|
|
202
|
-
moby.send(:form)
|
|
203
|
-
field = moby.send(:username_field)
|
|
204
|
-
|
|
205
|
-
_(field).wont_be_nil
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
it "finds password field by number" do
|
|
209
|
-
moby.send(:page)
|
|
210
|
-
moby.send(:form)
|
|
211
|
-
field = moby.send(:password_field)
|
|
212
|
-
|
|
213
|
-
_(field).wont_be_nil
|
|
214
|
-
end
|
|
215
|
-
end
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
describe "#username" do
|
|
219
|
-
it "generates random username" do
|
|
220
|
-
username = moby.send(:username)
|
|
221
|
-
|
|
222
|
-
_(username).must_be_kind_of(String)
|
|
223
|
-
_(username.length).must_be(:>, 0)
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
it "generates email address when username_is_email_address is true" do
|
|
227
|
-
m = Moby.new(url: url, username_is_email_address: true)
|
|
228
|
-
username = m.send(:username)
|
|
229
|
-
|
|
230
|
-
_(username).must_match(/@/)
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
it "generates email with custom hostname" do
|
|
234
|
-
m = Moby.new(url: url, username_hostname: 'example.com')
|
|
235
|
-
username = m.send(:username)
|
|
236
|
-
|
|
237
|
-
_(username).must_match(/@example\.com$/)
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
it "generates different usernames" do
|
|
242
|
-
usernames = 10.times.map{moby.send(:username)}
|
|
243
|
-
|
|
244
|
-
_(usernames.uniq.length).must_be(:>, 1)
|
|
245
|
-
end
|
|
8
|
+
it "selects the mechanize backend by default" do
|
|
9
|
+
_(Moby.new(url: url).send(:backend)).must_be_instance_of(Moby::Backends::MechanizeBackend)
|
|
246
10
|
end
|
|
247
11
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
password = moby.send(:password)
|
|
251
|
-
|
|
252
|
-
_(password).must_be_kind_of(String)
|
|
253
|
-
_(password.length).must_be(:>, 0)
|
|
254
|
-
end
|
|
12
|
+
it "selects the selenium backend when configured" do
|
|
13
|
+
_(Moby.new(url: url, backend: :selenium).send(:backend)).must_be_instance_of(Moby::Backends::SeleniumBackend)
|
|
255
14
|
end
|
|
256
15
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
agent = moby.send(:user_agent)
|
|
260
|
-
|
|
261
|
-
_(agent).must_be_kind_of(String)
|
|
262
|
-
_(agent).wont_equal('Mechanize')
|
|
263
|
-
end
|
|
264
|
-
|
|
265
|
-
it "returns set user agent when provided" do
|
|
266
|
-
m = Moby.new(url: url, user_agent: 'CustomAgent')
|
|
267
|
-
|
|
268
|
-
_(m.send(:user_agent)).must_equal('CustomAgent')
|
|
269
|
-
end
|
|
270
|
-
|
|
271
|
-
it "generates different random agents" do
|
|
272
|
-
agents = 10.times.map{Moby.new(url: url).send(:user_agent)}
|
|
273
|
-
|
|
274
|
-
_(agents.uniq.length).must_be(:>, 1)
|
|
275
|
-
end
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
describe "#username_is_email_address?" do
|
|
279
|
-
it "returns true when username_is_email_address is set" do
|
|
280
|
-
m = Moby.new(url: url, username_is_email_address: true)
|
|
281
|
-
|
|
282
|
-
_(m.send(:username_is_email_address?)).must_equal(true)
|
|
283
|
-
end
|
|
284
|
-
|
|
285
|
-
it "returns true when username_hostname is set" do
|
|
286
|
-
m = Moby.new(url: url, username_hostname: 'example.com')
|
|
287
|
-
|
|
288
|
-
_(m.send(:username_is_email_address?)).wont_be_nil
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
it "returns false by default" do
|
|
292
|
-
_(moby.send(:username_field_name)).must_equal('username')
|
|
293
|
-
end
|
|
16
|
+
it "responds to counter_phish" do
|
|
17
|
+
_(Moby.new(url: url)).must_respond_to(:counter_phish)
|
|
294
18
|
end
|
|
295
19
|
end
|
data/test/test_helper.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require 'minitest/autorun'
|
|
4
4
|
require 'minitest-spec-context'
|
|
5
5
|
require 'webmock/minitest'
|
|
6
|
+
require 'tempfile'
|
|
6
7
|
|
|
7
8
|
require_relative '../lib/moby'
|
|
8
9
|
|
|
@@ -33,4 +34,18 @@ module TestFixtures
|
|
|
33
34
|
</body>
|
|
34
35
|
</html>
|
|
35
36
|
HTML
|
|
37
|
+
|
|
38
|
+
WORDS = %w{
|
|
39
|
+
alpha bravo charlie delta echo foxtrot golf hotel india juliet
|
|
40
|
+
kilo lima mike november oscar papa quebec romeo sierra tango
|
|
41
|
+
uniform victor whiskey xray yankee zulu apple banana cherry date
|
|
42
|
+
elder fig grape honey iris jasmine kiwi lemon mango nutmeg
|
|
43
|
+
}.freeze
|
|
44
|
+
|
|
45
|
+
WORD_LIST_FILE = Tempfile.new('moby_words').tap do |file|
|
|
46
|
+
file.write(WORDS.join("\n") << "\n")
|
|
47
|
+
file.flush
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
WORD_LIST_PATH = WORD_LIST_FILE.path
|
|
36
51
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: moby.rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- thoran
|
|
@@ -23,6 +23,20 @@ dependencies:
|
|
|
23
23
|
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: '2'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: selenium-webdriver
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '4'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '4'
|
|
26
40
|
- !ruby/object:Gem::Dependency
|
|
27
41
|
name: switches.rb
|
|
28
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -108,11 +122,23 @@ files:
|
|
|
108
122
|
- README.md
|
|
109
123
|
- Rakefile
|
|
110
124
|
- bin/moby
|
|
111
|
-
- lib/File/self.collect.rb
|
|
112
125
|
- lib/Moby.rb
|
|
126
|
+
- lib/Moby/Backends.rb
|
|
127
|
+
- lib/Moby/Backends/MechanizeBackend.rb
|
|
128
|
+
- lib/Moby/Backends/SeleniumBackend.rb
|
|
129
|
+
- lib/Moby/Configuration.rb
|
|
130
|
+
- lib/Moby/RandomInputGenerator.rb
|
|
113
131
|
- lib/Moby/VERSION.rb
|
|
114
|
-
- lib/
|
|
132
|
+
- lib/Selenium/WebDriver/Driver/Attempt/attempt.rb
|
|
133
|
+
- lib/Selenium/WebDriver/SearchContext/ElementPresentQ/element_presentQ.rb
|
|
134
|
+
- lib/Thoran/Selenium/WebDriver/Driver/Attempt/attempt.rb
|
|
135
|
+
- lib/Thoran/Selenium/WebDriver/SearchContext/ElementPresentQ/element_presentQ.rb
|
|
115
136
|
- moby.rb.gemspec
|
|
137
|
+
- test/Moby/Backends/MechanizeBackend_test.rb
|
|
138
|
+
- test/Moby/Backends/SeleniumBackend_test.rb
|
|
139
|
+
- test/Moby/Backends_test.rb
|
|
140
|
+
- test/Moby/Configuration_test.rb
|
|
141
|
+
- test/Moby/RandomInputGenerator_test.rb
|
|
116
142
|
- test/Moby/VERSION_test.rb
|
|
117
143
|
- test/moby_test.rb
|
|
118
144
|
- test/test_helper.rb
|
|
@@ -131,14 +157,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
131
157
|
requirements:
|
|
132
158
|
- - ">="
|
|
133
159
|
- !ruby/object:Gem::Version
|
|
134
|
-
version:
|
|
160
|
+
version: 3.3.0
|
|
135
161
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
136
162
|
requirements:
|
|
137
163
|
- - ">="
|
|
138
164
|
- !ruby/object:Gem::Version
|
|
139
165
|
version: '0'
|
|
140
166
|
requirements: []
|
|
141
|
-
rubygems_version: 4.0.
|
|
167
|
+
rubygems_version: 4.0.18
|
|
142
168
|
specification_version: 4
|
|
143
169
|
summary: Moby is a credentials poisoning tool which floods phishing forms with fake
|
|
144
170
|
credentials.
|
data/lib/File/self.collect.rb
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# Thoran/File/SelfCollect/self.collect.rb
|
|
2
|
-
# Thoran::File::SelfCollect.collect.rb
|
|
3
|
-
|
|
4
|
-
# 20190821
|
|
5
|
-
# 0.2.0
|
|
6
|
-
|
|
7
|
-
# Changes:
|
|
8
|
-
# 1. + Thoran::File::SelfCollect namespace.
|
|
9
|
-
|
|
10
|
-
module Thoran
|
|
11
|
-
module File
|
|
12
|
-
module SelfCollect
|
|
13
|
-
|
|
14
|
-
def collect(filename, &block)
|
|
15
|
-
open(filename, 'r').collect(&block)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
File.extend(Thoran::File::SelfCollect)
|