Email and smtp.sendmail security vulnerabilities?

J

John W. Long

Hi,

I've created a small class and supporting methods for sending email from a
web page. I use it like this:

msg = Web::Email::Message.new(
:from => from,
:to => to,
:subject => subject,
:body => body.untaint # security vulnerability?
)
Web::Email.send(msg)

All of the email strings :)from, :to, etc...) could potentially come from
the the outside world. I'm doing some munging on the :from, :to, and
:subject strings replacing \n \r \f \e and \b with something
non-threatening. Right now I'm just untainting the :body string, but I have
the distinct feeling that I may be exposing myself to a security
vulnerability because I don't really understand what the Net::SMTP class is
doing in the background.

Could someone who understands how Net::SMTP works check over my code (see
below) and comment on security vulnerabilities? Also I looked for details on
specification for email, but a brief search on google didn't turn up
anything. Can someone point me in the right direction?

Thanks,

John Long
http://wiseheartdesign.com

<code>
# you will probably want to paste this into
# a syntax highlighting editor like Scite
require 'net/smtp'
module Web
module Email
class Message
attr_accessor :from, :to, :subject, :body

def initialize(hash = {})
@from = hash[:from]
@to = hash[:to]
@subject = hash[:subject]
@body = hash[:body]
end

def message
time = current_time
<<-SMTP_MSG
Subject: #{@subject}
Message-Id: <#{"%.8f" % time.to_f}@iblp.org>
Date: #{time.strftime("%a, %d %b %Y %H:%M:%S %z %Z")}
From: #{@from}
To: #{@to}

#{@body}
SMTP_MSG
end

def current_time
Time.now
end
end
def self.send(msg)
msg.subject = safe_subject(msg.subject) # munges and untaints string
msg.from = safe_address(msg.from)
msg.to = safe_address(msg.to)
raise ArgumentError, 'msg.body tainted' if msg.body.tainted?
raise ArgumentError, 'msg tainted' if msg.tainted?
Net::SMTP.start('localhost', 25) {|smtp|
smtp.sendmail(msg.message, msg.from, msg.to)
}
end
def self.safe_subject(subject)
subject.gsub(/[\n\r\f\e\b]/, ' ').untaint
end
def self.safe_address(address)
address.gsub(/[\n\r\f\e\b]/, '').untaint
end
end
end
</code>
 
H

Hugh Sasse Staff Elec Eng

Hi,

I've created a small class and supporting methods for sending email from a
web page. I use it like this:

msg = Web::Email::Message.new(
:from => from,
:to => to,
:subject => subject,
:body => body.untaint # security vulnerability?
)
Web::Email.send(msg)

All of the email strings :)from, :to, etc...) could potentially come from
the the outside world. I'm doing some munging on the :from, :to, and

That is your security problem in itself. Far better would be to
permit certain addresses only, and let the user choose them by
passing a hash (such as MD5) of the desired address into the form.
Thus different addresses cannot easily be created, because only
those selected addresses will be reverse mapped (md5->address).
This selection would obviously have to be done from a radio button
or similar selector.

Why go to all this trouble? See
http://spamcop.net/fom-serve/cache/270.html
for links to details about formmail which used to be open.
Basically, anyone could use your script for relaying mail via your
machine...

Hugh
 
J

John W. Long

Hi,
That is your security problem in itself. Far better would be to
permit certain addresses only, and let the user choose them by
passing a hash (such as MD5) of the desired address into the form.
Thus different addresses cannot easily be created, because only
those selected addresses will be reverse mapped (md5->address).
This selection would obviously have to be done from a radio button
or similar selector.

Well, at any one time I do not intend to allow the user to enter all of the
information. Right now we have an "email this page" form on our web site.
Which allows the user to send a link from our web site to a friend. They
enter their name and email, their friends name and email, and a brief
message. The code then wraps their message with some standard text and the
link. You can see our old form here:

http://iblp.org/email.asp

This emails something like this to their friend:

<email>
Hi John,

Your friend Bill wants you to visit:

#{link}

Message:

#{usermessage}

--------------------
The Institute in Basic Life Principles
http://iblp.org
Why go to all this trouble? See
http://spamcop.net/fom-serve/cache/270.html
for links to details about formmail which used to be open.
Basically, anyone could use your script for relaying mail via your
machine...

While I realize that anyone with enough know how could send mail from the
form, he would have to be willing to send the message with our header and
footer (something I hope would discourage spammers from using our form).

The main thing I want to know is if someone could enter a message that would
add headers to the email or cause the footer not to be displayed, or exploit
some other security vulnerability. Right now I'm preventing the email fields
from having more than one address, and am forcing the name fields to only
have certian characters. The field that I am primarily worried about is the
message field.
 
H

Hugh Sasse Staff Elec Eng

Hi,


Well, at any one time I do not intend to allow the user to enter all of the
information. Right now we have an "email this page" form on our web site. [...]
http://iblp.org/email.asp
[...]

This is open to the same kind of abuse.
While I realize that anyone with enough know how could send mail from the

But it isn't much know how: it is only constructing a URL. Then the
"spam" comes via your domain, and you get blacklisted.
form, he would have to be willing to send the message with our header and
footer (something I hope would discourage spammers from using our form).

Spammers don't seem to care much how their message is delivered.
This statement is anecdotal, of course. Add a tablespoon or 4 of
salt, to taste.
The main thing I want to know is if someone could enter a message that would
add headers to the email or cause the footer not to be displayed, or exploit
some other security vulnerability. Right now I'm preventing the email fields

I've not looked in that much depth. I think this is a serious
enough flaw to make that much less significant.

Another quick look throws up: You have not trapped ';' although you
don't pass this directly to a shell, so you should be OK.
When you expand the string with #{} they can find out things like
$RUBY_PLATFORM and such, which may reveal more about your system
than you wish to reveal.

The Body cannot become part of the headers, even with vertical tabs,
I think.

The Message id may not be unique, since you only use time.current.
You may need $$ and possibly Thread.current as well to guarantee 2
concurrent submissions having unique ids.

I don't seem to have enough low cunning to think of all the holes
that others are able to point out.

You also may wish to limit submissions from/to an address in a given
period to prevent automated mail bombing.
from having more than one address, and am forcing the name fields to only
have certian characters. The field that I am primarily worried about is the
message field.
Hugh
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,054
Latest member
LucyCarper

Latest Threads

Top