gophish-ruby 0.2.0 → 0.4.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.md +18 -1
- data/README.md +199 -0
- data/Rakefile +1 -1
- data/docs/API_REFERENCE.md +320 -0
- data/docs/EXAMPLES.md +642 -0
- data/docs/GETTING_STARTED.md +156 -0
- data/lib/gophish/page.rb +56 -0
- data/lib/gophish/smtp.rb +99 -0
- data/lib/gophish/version.rb +1 -1
- data/lib/gophish-ruby.rb +2 -0
- metadata +3 -1
data/docs/GETTING_STARTED.md
CHANGED
@@ -105,6 +105,51 @@ else
|
|
105
105
|
end
|
106
106
|
```
|
107
107
|
|
108
|
+
### 5. Create Your First Landing Page
|
109
|
+
|
110
|
+
Landing pages are what users see when they click phishing links:
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
# Create a basic landing page
|
114
|
+
page = Gophish::Page.new(
|
115
|
+
name: "Microsoft Login Page",
|
116
|
+
html: <<~HTML
|
117
|
+
<!DOCTYPE html>
|
118
|
+
<html>
|
119
|
+
<head>
|
120
|
+
<title>Microsoft Account</title>
|
121
|
+
<style>
|
122
|
+
body { font-family: Arial, sans-serif; margin: 40px; background: #f5f5f5; }
|
123
|
+
.container { max-width: 400px; margin: 0 auto; background: white; padding: 40px; border-radius: 8px; }
|
124
|
+
input { width: 100%; padding: 12px; margin: 10px 0; border: 1px solid #ccc; border-radius: 4px; }
|
125
|
+
button { width: 100%; padding: 12px; background: #0078d4; color: white; border: none; border-radius: 4px; }
|
126
|
+
</style>
|
127
|
+
</head>
|
128
|
+
<body>
|
129
|
+
<div class="container">
|
130
|
+
<h2>Sign in to your account</h2>
|
131
|
+
<form method="post">
|
132
|
+
<input type="email" name="username" placeholder="Email" required>
|
133
|
+
<input type="password" name="password" placeholder="Password" required>
|
134
|
+
<button type="submit">Sign in</button>
|
135
|
+
</form>
|
136
|
+
</div>
|
137
|
+
</body>
|
138
|
+
</html>
|
139
|
+
HTML,
|
140
|
+
capture_credentials: true,
|
141
|
+
redirect_url: "https://www.microsoft.com"
|
142
|
+
)
|
143
|
+
|
144
|
+
if page.save
|
145
|
+
puts "✓ Landing page created successfully with ID: #{page.id}"
|
146
|
+
puts " Captures credentials: #{page.captures_credentials?}"
|
147
|
+
else
|
148
|
+
puts "✗ Failed to create page:"
|
149
|
+
page.errors.full_messages.each { |error| puts " - #{error}" }
|
150
|
+
end
|
151
|
+
```
|
152
|
+
|
108
153
|
## Common Workflows
|
109
154
|
|
110
155
|
### Importing Targets from CSV
|
@@ -208,6 +253,117 @@ template.remove_attachment("old_file.pdf")
|
|
208
253
|
template.save
|
209
254
|
```
|
210
255
|
|
256
|
+
### Working with Landing Pages
|
257
|
+
|
258
|
+
#### Creating Pages with Different Features
|
259
|
+
|
260
|
+
```ruby
|
261
|
+
# Simple page without credential capture
|
262
|
+
basic_page = Gophish::Page.new(
|
263
|
+
name: "Generic Landing Page",
|
264
|
+
html: "<html><body><h1>Thank you!</h1><p>Your action has been completed.</p></body></html>"
|
265
|
+
)
|
266
|
+
|
267
|
+
# Page with credential capture and redirect
|
268
|
+
login_page = Gophish::Page.new(
|
269
|
+
name: "Banking Login Clone",
|
270
|
+
html: <<~HTML
|
271
|
+
<html>
|
272
|
+
<head>
|
273
|
+
<title>Secure Banking</title>
|
274
|
+
<style>
|
275
|
+
body { font-family: Arial, sans-serif; background: #003366; color: white; padding: 50px; }
|
276
|
+
.form-container { max-width: 350px; margin: 0 auto; background: white; color: black; padding: 30px; border-radius: 8px; }
|
277
|
+
input { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #ddd; }
|
278
|
+
button { width: 100%; padding: 12px; background: #003366; color: white; border: none; cursor: pointer; }
|
279
|
+
</style>
|
280
|
+
</head>
|
281
|
+
<body>
|
282
|
+
<div class="form-container">
|
283
|
+
<h2>Online Banking Login</h2>
|
284
|
+
<form method="post">
|
285
|
+
<input type="text" name="username" placeholder="Username" required>
|
286
|
+
<input type="password" name="password" placeholder="Password" required>
|
287
|
+
<button type="submit">Login</button>
|
288
|
+
</form>
|
289
|
+
</div>
|
290
|
+
</body>
|
291
|
+
</html>
|
292
|
+
HTML,
|
293
|
+
capture_credentials: true,
|
294
|
+
capture_passwords: true,
|
295
|
+
redirect_url: "https://www.realbank.com/login"
|
296
|
+
)
|
297
|
+
|
298
|
+
# Save both pages
|
299
|
+
[basic_page, login_page].each do |page|
|
300
|
+
if page.save
|
301
|
+
puts "✓ Created page: #{page.name} (ID: #{page.id})"
|
302
|
+
puts " Captures credentials: #{page.captures_credentials?}"
|
303
|
+
end
|
304
|
+
end
|
305
|
+
```
|
306
|
+
|
307
|
+
#### Importing Pages from Existing Websites
|
308
|
+
|
309
|
+
```ruby
|
310
|
+
# Import a real website as a landing page template
|
311
|
+
begin
|
312
|
+
imported_data = Gophish::Page.import_site(
|
313
|
+
"https://login.live.com",
|
314
|
+
include_resources: true # Include CSS, JS, and images
|
315
|
+
)
|
316
|
+
|
317
|
+
page = Gophish::Page.new(imported_data)
|
318
|
+
page.name = "Microsoft Live Login Clone"
|
319
|
+
page.capture_credentials = true
|
320
|
+
|
321
|
+
if page.save
|
322
|
+
puts "✓ Successfully imported website as landing page"
|
323
|
+
puts " Page ID: #{page.id}"
|
324
|
+
puts " HTML size: #{page.html.length} characters"
|
325
|
+
end
|
326
|
+
|
327
|
+
rescue StandardError => e
|
328
|
+
puts "✗ Failed to import website: #{e.message}"
|
329
|
+
puts " Falling back to manual page creation"
|
330
|
+
|
331
|
+
# Create a manual fallback page
|
332
|
+
fallback_page = Gophish::Page.new(
|
333
|
+
name: "Manual Microsoft Login Clone",
|
334
|
+
html: "<html><body><h1>Microsoft</h1><form method='post'><input name='email' type='email' placeholder='Email'><input name='password' type='password' placeholder='Password'><button type='submit'>Sign in</button></form></body></html>",
|
335
|
+
capture_credentials: true
|
336
|
+
)
|
337
|
+
fallback_page.save
|
338
|
+
end
|
339
|
+
```
|
340
|
+
|
341
|
+
#### Managing Existing Pages
|
342
|
+
|
343
|
+
```ruby
|
344
|
+
# List all pages
|
345
|
+
puts "Existing pages:"
|
346
|
+
Gophish::Page.all.each do |page|
|
347
|
+
credential_info = page.captures_credentials? ? " [Captures Credentials]" : ""
|
348
|
+
redirect_info = page.has_redirect? ? " → #{page.redirect_url}" : ""
|
349
|
+
puts " #{page.id}: #{page.name}#{credential_info}#{redirect_info}"
|
350
|
+
end
|
351
|
+
|
352
|
+
# Update a page
|
353
|
+
page = Gophish::Page.find(1)
|
354
|
+
page.name = "Updated Page Name"
|
355
|
+
page.capture_credentials = true
|
356
|
+
page.redirect_url = "https://example.com/success"
|
357
|
+
|
358
|
+
# Modify the HTML content
|
359
|
+
page.html = page.html.gsub("Sign in", "Login")
|
360
|
+
|
361
|
+
if page.save
|
362
|
+
puts "✓ Page updated successfully"
|
363
|
+
puts " Now captures credentials: #{page.captures_credentials?}"
|
364
|
+
end
|
365
|
+
```
|
366
|
+
|
211
367
|
### Managing Existing Groups
|
212
368
|
|
213
369
|
```ruby
|
data/lib/gophish/page.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
require 'active_support/core_ext/object/blank'
|
3
|
+
|
4
|
+
module Gophish
|
5
|
+
class Page < Base
|
6
|
+
attribute :id, :integer
|
7
|
+
attribute :name, :string
|
8
|
+
attribute :html, :string
|
9
|
+
attribute :capture_credentials, :boolean, default: false
|
10
|
+
attribute :capture_passwords, :boolean, default: false
|
11
|
+
attribute :modified_date, :string
|
12
|
+
attribute :redirect_url, :string
|
13
|
+
|
14
|
+
define_attribute_methods :id, :name, :html, :capture_credentials, :capture_passwords, :modified_date, :redirect_url
|
15
|
+
|
16
|
+
validates :name, presence: true
|
17
|
+
validates :html, presence: true
|
18
|
+
|
19
|
+
def body_for_create
|
20
|
+
{
|
21
|
+
name:,
|
22
|
+
html:,
|
23
|
+
capture_credentials:,
|
24
|
+
capture_passwords:,
|
25
|
+
redirect_url:
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.import_site(url, include_resources: false)
|
30
|
+
options = build_import_options url, include_resources
|
31
|
+
response = post '/import/site', options
|
32
|
+
raise StandardError, 'Failed to import site' unless response.success?
|
33
|
+
|
34
|
+
response.parsed_response
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.build_import_options(url, include_resources)
|
38
|
+
{
|
39
|
+
body: { url:, include_resources: }.to_json,
|
40
|
+
headers: { 'Content-Type' => 'application/json' }
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def captures_credentials?
|
45
|
+
capture_credentials == true
|
46
|
+
end
|
47
|
+
|
48
|
+
def captures_passwords?
|
49
|
+
capture_passwords == true
|
50
|
+
end
|
51
|
+
|
52
|
+
def has_redirect?
|
53
|
+
!redirect_url.blank?
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/gophish/smtp.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
require 'active_support/core_ext/object/blank'
|
3
|
+
|
4
|
+
module Gophish
|
5
|
+
class Smtp < Base
|
6
|
+
def self.resource_path
|
7
|
+
'/smtp'
|
8
|
+
end
|
9
|
+
attribute :id, :integer
|
10
|
+
attribute :name, :string
|
11
|
+
attribute :username, :string
|
12
|
+
attribute :password, :string
|
13
|
+
attribute :host, :string
|
14
|
+
attribute :interface_type, :string, default: 'SMTP'
|
15
|
+
attribute :from_address, :string
|
16
|
+
attribute :ignore_cert_errors, :boolean, default: false
|
17
|
+
attribute :modified_date, :string
|
18
|
+
attribute :headers, default: -> { [] }
|
19
|
+
|
20
|
+
define_attribute_methods :id, :name, :username, :password, :host, :interface_type, :from_address,
|
21
|
+
:ignore_cert_errors, :modified_date, :headers
|
22
|
+
|
23
|
+
validates :name, presence: true
|
24
|
+
validates :host, presence: true
|
25
|
+
validates :from_address, presence: true
|
26
|
+
validate :validate_from_address_format
|
27
|
+
validate :validate_headers_structure
|
28
|
+
|
29
|
+
def body_for_create
|
30
|
+
{
|
31
|
+
name:, username:, password:, host:,
|
32
|
+
interface_type:,
|
33
|
+
from_address:,
|
34
|
+
ignore_cert_errors:,
|
35
|
+
headers:
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_header(key, value)
|
40
|
+
headers << { key:, value: }
|
41
|
+
headers_will_change!
|
42
|
+
end
|
43
|
+
|
44
|
+
def remove_header(key)
|
45
|
+
original_size = headers.size
|
46
|
+
headers.reject! { |header| header[:key] == key || header['key'] == key }
|
47
|
+
headers_will_change! if headers.size != original_size
|
48
|
+
end
|
49
|
+
|
50
|
+
def has_headers?
|
51
|
+
!headers.empty?
|
52
|
+
end
|
53
|
+
|
54
|
+
def header_count
|
55
|
+
headers.length
|
56
|
+
end
|
57
|
+
|
58
|
+
def has_authentication?
|
59
|
+
!username.blank? && !password.blank?
|
60
|
+
end
|
61
|
+
|
62
|
+
def ignores_cert_errors?
|
63
|
+
ignore_cert_errors == true
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def validate_from_address_format
|
69
|
+
return if from_address.blank?
|
70
|
+
|
71
|
+
email_regex = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
|
72
|
+
|
73
|
+
unless from_address.match? email_regex
|
74
|
+
errors.add :from_address, 'must be a valid email format (email@domain.com)'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def validate_headers_structure
|
79
|
+
return if headers.blank?
|
80
|
+
return errors.add :headers, 'must be an array' unless headers.is_a? Array
|
81
|
+
|
82
|
+
headers.each_with_index { |header, index| validate_header header, index }
|
83
|
+
end
|
84
|
+
|
85
|
+
def validate_header(header, index)
|
86
|
+
return errors.add :headers, "item at index #{index} must be a hash" unless header.is_a? Hash
|
87
|
+
|
88
|
+
validate_header_field header, index, :key
|
89
|
+
validate_header_field header, index, :value
|
90
|
+
end
|
91
|
+
|
92
|
+
def validate_header_field(header, index, field)
|
93
|
+
value = header[field] || header[field.to_s]
|
94
|
+
return unless value.blank?
|
95
|
+
|
96
|
+
errors.add :headers, "item at index #{index} must have a #{field}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/lib/gophish/version.rb
CHANGED
data/lib/gophish-ruby.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gophish-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eli Sebastian Herrera Aguilar
|
@@ -105,6 +105,8 @@ files:
|
|
105
105
|
- lib/gophish/base.rb
|
106
106
|
- lib/gophish/configuration.rb
|
107
107
|
- lib/gophish/group.rb
|
108
|
+
- lib/gophish/page.rb
|
109
|
+
- lib/gophish/smtp.rb
|
108
110
|
- lib/gophish/template.rb
|
109
111
|
- lib/gophish/version.rb
|
110
112
|
- sig/gophish/ruby.rbs
|