diff --git a/extensions/social_engineering/config.yaml b/extensions/social_engineering/config.yaml index 98e2852d6..d5b3444b2 100644 --- a/extensions/social_engineering/config.yaml +++ b/extensions/social_engineering/config.yaml @@ -28,5 +28,14 @@ beef: port: 587 use_tls: true helo: "gmail.com" # this is usually the domain name - from: "yourmail@gmail.com" + from: "yourpass@gmail.com" password: "yourpass" + # available templates + templates: + default: + # images are by default inline, so if you want to attach something, see below + images: ["beef_logo.png"]#,"second_image.png"] + images_cids: + cid1: "beef_logo.png" + #cid2: "second_image.png" + attachment: [""] diff --git a/extensions/social_engineering/mass_mailer/mass_mailer.rb b/extensions/social_engineering/mass_mailer/mass_mailer.rb index 11c0e3aae..66a965f4f 100644 --- a/extensions/social_engineering/mass_mailer/mass_mailer.rb +++ b/extensions/social_engineering/mass_mailer/mass_mailer.rb @@ -23,22 +23,23 @@ module BeEF def initialize @config = BeEF::Core::Configuration.instance - @user_agent = @config.get('beef.extension.social_engineering.mass_mailer.user_agent') - @host = @config.get('beef.extension.social_engineering.mass_mailer.host') - @port = @config.get('beef.extension.social_engineering.mass_mailer.port') - @helo = @config.get('beef.extension.social_engineering.mass_mailer.helo') - @from = @config.get('beef.extension.social_engineering.mass_mailer.from') - @password = @config.get('beef.extension.social_engineering.mass_mailer.password') + @config_prefix = "beef.extension.social_engineering.mass_mailer" + @templates_dir = "#{File.expand_path('../../../../extensions/social_engineering/mass_mailer/templates', __FILE__)}/" - @subject = "Hi from BeEF" + @user_agent = @config.get("#{@config_prefix}.user_agent") + @host = @config.get("#{@config_prefix}.host") + @port = @config.get("#{@config_prefix}.port") + @helo = @config.get("#{@config_prefix}.helo") + @from = @config.get("#{@config_prefix}.from") + @password = @config.get("#{@config_prefix}.password") end # tos_hash is an Hash like: # 'antisnatchor@gmail.com' => 'Michele' # 'ciccio@pasticcio.com' => 'Ciccio' - def send_email(tos_hash) + def send_email(template, subject, tos_hash) # create new SSL context and disable CA chain validation - if @config.get('beef.extension.social_engineering.mass_mailer.use_tls') + if @config.get("#{@config_prefix}.use_tls") @ctx = OpenSSL::SSL::SSLContext.new @ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE # In case the SMTP server uses a self-signed cert, we proceed anyway @ctx.ssl_version = "TLSv1" @@ -46,10 +47,10 @@ module BeEF # create a new SMTP object, enable TLS with the previous instantiated context, and connects to the server smtp = Net::SMTP.new(@host, @port) - smtp.enable_starttls(@ctx) unless @config.get('beef.extension.social_engineering.mass_mailer.use_tls') == false + smtp.enable_starttls(@ctx) unless @config.get("#{@config_prefix}.use_tls") == false smtp.start(@helo, @from, @password, :login) do |smtp| tos_hash.each do |mail, name| - message = compose_email(mail, name, @subject) + message = compose_email(mail, name, subject, template) smtp.send_message(message, @from, mail) end end @@ -58,23 +59,27 @@ module BeEF #todo sending to hostmonster the email is probably flagged as spam: # todo: error -> 550 550 Administrative prohibition (state 17 - def compose_email(to, name, subject) + def compose_email(to, name, subject, template) msg_id = random_string(50) boundary = "------------#{random_string(24)}" rel_boundary = "------------#{random_string(24)}" - plain_text = "Hi #{name},\nPlease be sure to check this link:\n" - @file_path = '/Users/morru/WORKS/BeEF/beef-44Con-code/extensions/social_engineering/mass_mailer/templates/default/' - file = 'beef_logo.png' + link = "http://127.0.0.1:3000/demos/basic.html" + linktext = "http://antisnatchor.com" header = email_headers(@from, @user_agent, to, name, subject, msg_id, boundary) - plain_body = email_plain_body(plain_text,boundary) + plain_body = email_plain_body(parse_template(name, link, linktext, "#{@templates_dir}#{template}/mail.plain"),boundary) rel_header = email_related(rel_boundary) - html_body = email_html_body(rel_boundary, file, plain_text) - image = email_add_image(file,rel_boundary) + html_body = email_html_body(parse_template(name, link, linktext, "#{@templates_dir}#{template}/mail.plain"),rel_boundary) + + images = "" + @config.get("#{@config_prefix}.templates.default.images").each do |image| + images += email_add_image(image, "#{@templates_dir}#{template}/#{image}",rel_boundary) + end + close = email_close(boundary) - message = header + plain_body + rel_header + html_body + image + close + message = header + plain_body + rel_header + html_body + images + close print_debug "Raw Email content:\n #{message}" message end @@ -119,35 +124,27 @@ EOF related end - def email_html_body(rel_boundary, file, plain_body) + def email_html_body(html_body, rel_boundary) html_body = < - -#{plain_body}
-
- #{file}
-
-Thanks - - +#{html_body} --#{rel_boundary} EOF html_body end - def email_add_image(file, rel_boundary) - file_encoded = [File.read(@file_path + file)].pack("m") # base64 + def email_add_image(name, path, rel_boundary) + file_encoded = [File.read(path)].pack("m") # base64 encoded + #todo: content-type must be determined at least from file extension, not hardcoded image = < +Content-ID: <#{name}> Content-Disposition: inline; - filename="#{file}" + filename="#{name}" #{file_encoded} --#{rel_boundary} @@ -162,6 +159,31 @@ EOF close end + # Replaces placeholder values from the plain/html email templates + def parse_template(name, link, linktext, template_path) + result = "" + img_config = "#{@config_prefix}.templates.default.images_cids" + img_count = 0 + File.open(template_path, 'r').each do |line| + # change the Recipient name + if line.include?("__name__") + result += line.gsub("__name__",name) + # change the link/linktext + elsif line.include?("__link__") + result += line.gsub("__link__",link).gsub("__linktext__",linktext) + # change images cid/name/alt + elsif line.include?("src=\"cid:__") + img_count += 1 + result += line.gsub("__cid#{img_count}__", + @config.get("#{img_config}.cid#{img_count}")).gsub("__img#{img_count}__", + @config.get("#{img_config}.cid#{img_count}")) + else + result += line + end + end + result + end + def random_string(length) output = (0..length).map{ rand(36).to_s(36).upcase }.join output diff --git a/extensions/social_engineering/mass_mailer/templates/default/beef_logo.png b/extensions/social_engineering/mass_mailer/templates/default/beef_logo.png new file mode 100644 index 000000000..24a718216 Binary files /dev/null and b/extensions/social_engineering/mass_mailer/templates/default/beef_logo.png differ diff --git a/extensions/social_engineering/mass_mailer/templates/default/mail.html b/extensions/social_engineering/mass_mailer/templates/default/mail.html new file mode 100644 index 000000000..5620d00c8 --- /dev/null +++ b/extensions/social_engineering/mass_mailer/templates/default/mail.html @@ -0,0 +1,19 @@ + + + + + +Hi __name __,
+
+We would like to inform you that your BeEF order has been successful.
+You can check the status of your hook at the following link:
+ +__linktext__
+
+Regards,
+The BeEF team
+ +__img1__
+ + + \ No newline at end of file diff --git a/extensions/social_engineering/mass_mailer/templates/default/mail.plain b/extensions/social_engineering/mass_mailer/templates/default/mail.plain new file mode 100644 index 000000000..4b57cf16d --- /dev/null +++ b/extensions/social_engineering/mass_mailer/templates/default/mail.plain @@ -0,0 +1,8 @@ +Hi __name__, + +We would like to inform you that your BeEF order has been successful. +You can check the status of your hook at the following link: +__link__ + +Regards, +The BeEF team \ No newline at end of file