Question about abuse of a CGI script

M

Martin Kissner

hello together,

I had a CGI Skript on my mothers website to send email from a html form
(method post) for about two yaers.

The script was quite simple and had no checking of the User input
implemented.
When I wrote the script two years ago, I didn't even know that this is
neccesary.
I used Mail::Mailer to send the input from the form in a nicely formated
html email to my mother's email address.

Now the script was abused by a spammer who sent at least 6000 (probably
far more) spam emails.

I found *perldoc -q "How do I make sure"* which will enable me to secure
my script, but I also have another question:

How can I recieve the exact input of the spammer to my form as email
without giving him the chance to abuse my script. I want to understand,
what he did and how it worked.

Any information will be appreciated.
Thanks in advance

Best regards
Martin
 
M

Matt Garrish

Martin Kissner said:
hello together,

I had a CGI Skript on my mothers website to send email from a html form
(method post) for about two yaers.

The script was quite simple and had no checking of the User input
implemented.
When I wrote the script two years ago, I didn't even know that this is
neccesary.

That's a scary statement to confess to... : )
How can I recieve the exact input of the spammer to my form as email
without giving him the chance to abuse my script. I want to understand,
what he did and how it worked.

It would seem that if you have really secured your script, the person's
method would no longer work. Usually there is nothing special about what the
spammers do. They rely on you using cheap scripts like the one's you get
from Matt's archive, which they can then easily exploit because the source
code is free to look over and the bugs with it well known. Or they look for
obvious exploits like the ability to cc the email to someone and then flood
that field with email addresses.

I don't know how to answer your question except to say you should log every
request to that form with all the parameters submitted until the spammer
hits you again. I don't see how you can distinguish the spammer and allow
that person to run your script but not really execute it, which it sounds
like you want. You might also want to look into measures like captchas,
which will foil all but the most determined hackers.

Matt
 
D

DJ Stunks

Martin said:
How can I recieve the exact input of the spammer to my form as email
without giving him the chance to abuse my script. I want to understand,
what he did and how it worked.

If you are using CGI.pm (as I hope you are) you could check out either
of the following sections of the module's docs:
- "SAVING THE STATE OF THE SCRIPT TO A FILE"
- "DUMPING OUT ALL THE NAME/VALUE PAIRS"

Combine this with MIME::Lite to send yourself a copy.

I don't know, however, how you will filter "spam" emails from "actual"
emails - this part is up to you... (Regexp::Common::spam = qr{viagra}?
:p)

-jp
 
M

Martin Kissner

DJ Stunks wrote :
If you are using CGI.pm (as I hope you are) you could check out either
of the following sections of the module's docs:
- "SAVING THE STATE OF THE SCRIPT TO A FILE"
- "DUMPING OUT ALL THE NAME/VALUE PAIRS"

I didn't use CGI.pm and I have read that CGI.pm in many cases produces
much overhead.
Combine this with MIME::Lite to send yourself a copy.

I don't know, however, how you will filter "spam" emails from "actual"
emails - this part is up to you... (Regexp::Common::spam = qr{viagra}?

The problem is not so much how to filter spam from real mail since I
have renamed the original form an put in some quick'n'dirty filters.
Now I want to set up a form with the original filename and process it in
a way which helps me to understand how the attack of the spammer works.

I will check the docs you posted to see if I will find anything I could
use.
Thanks and Best regards
Martin
 
M

Martin Kissner

Matt Garrish wrote :
That's a scary statement to confess to... : )

Well, I am an autodidact and sometimes things must be learned the hard
way ;-)
It would seem that if you have really secured your script, the person's
method would no longer work.

Up to now I did not really secure the script but I have put in some
filters to prevent the person's method from working. I think this is is
a large scale spammer since he sends mail to far more than 100.000
recipients.
Usually there is nothing special about what the
spammers do. They rely on you using cheap scripts like the one's you get
from Matt's archive, ...

or mine *g*
... which they can then easily exploit because the source
code is free to look over and the bugs with it well known. Or they look for
obvious exploits like the ability to cc the email to someone and then flood
that field with email addresses.

Yes, I think so.
Two days before the attack I reallized 5 emails with strange looking
values in the form fields. I afterwards could extract a single Bcc
address which I suppose is controlled by the spammer and is used to
report exploitable mail forms.
I don't know how to answer your question except to say you should log every
request to that form with all the parameters submitted until the spammer
hits you again. I don't see how you can distinguish the spammer and allow
that person to run your script but not really execute it, which it sounds
like you want. You might also want to look into measures like captchas,
which will foil all but the most determined hackers.

Distiguishing the spammer at this point is no problem.
As soon as I rename my email form back and open the filters I
implemented, he hits me over and over again from different IP addresses.
I could collect 10thousands of email addresses from his list because they
are listed in the first input field of my form.

I have already removed any variables from the part of my script which
sets the mailheaders but still he gets through.

What I want is to execute a script which enables me to analyse the
method the spammer uses in order to learn how this works - not because I
want to redo it, but I am interested.
If possible I would like to read the exact code (and other input) he
writes to the input fields of my form.

Best regards
Martin
 
J

John W. Kennedy

Martin said:
hello together,

I had a CGI Skript on my mothers website to send email from a html form
(method post) for about two yaers.

The script was quite simple and had no checking of the User input
implemented.
When I wrote the script two years ago, I didn't even know that this is
neccesary.
I used Mail::Mailer to send the input from the form in a nicely formated
html email to my mother's email address.

Now the script was abused by a spammer who sent at least 6000 (probably
far more) spam emails.

A device that has worked for me to foil robot spammers is simply to
leave the submit button out of the HTML and create it instead at onload
time, using JavaScript. It won't stop a human, but generally stymies robots.

--
John W. Kennedy
"But now is a new thing which is very old--
that the rich make themselves richer and not poorer,
which is the true Gospel, for the poor's sake."
-- Charles Williams. "Judgement at Chelmsford"
 
G

Gunnar Hjalmarsson

Martin said:
What I want is to execute a script which enables me to analyse the
method the spammer uses in order to learn how this works - not because I
want to redo it, but I am interested.

If you post the (relevant part of the) script here, somebody will
probably be able to tell you what the problem is.
 
A

A. Sinan Unur

DJ Stunks wrote :

I didn't use CGI.pm and I have read that CGI.pm in many cases produces
much overhead.

While CGI.pm is not going to automatically solve your problems,
the reason you give above for not using CGI.pm is plain stupid.
Who cares about CGI.pm overhead for an email script?

The question you have to ask yourself is why you want any odd visitor to
your web site to be able to send email to anyone at all even if it is
not large scale spamming.

Take a look at Gunnar Hjalmarsson's CGI::ContactForm:

http://search.cpan.org/~gunnar/CGI-ContactForm-1.30/lib/CGI/ContactForm.pm

Sinan
 
X

xhoster

Martin Kissner said:
DJ Stunks wrote :

I didn't use CGI.pm and I have read that CGI.pm in many cases produces
much overhead.

How polite of you to avoid the use of CGI in order to avoid overhead. Now
the spammers can spam 3.7% faster!

Seriously, how many legitimate hits on your script do you expect to have
each minute? How much overhead will that contribute? Hmmm...

Xho
 
M

Martin Kissner

A. Sinan Unur wrote :
While CGI.pm is not going to automatically solve your problems,
the reason you give above for not using CGI.pm is plain stupid.
Who cares about CGI.pm overhead for an email script?

Well, the 'and' was supposed to imply that the overhead was/is not the
reason for not using CGI.pm, it just encouraged me a little bit.
I am alos concious that my homemade modules probably have far more
overhead than CGI.pm ;-)

It might have been wrong not to use CGI.pm for this case, but I decided
not to use CGI.pm for several reasons. The website is presented in
several languages, uses databases and many templates (with
HTML::Template). Also I use CSS very much.

After I had read perldoc CGI I did not like the syntax
and felt like it might be not so easy to combine all the things I
mentioned above. (Maybe it is for an expierienced perl programmer which I
am not.) To me it looked like the HTML/CSS is not well enough divided
from the perl code (for my needs).
The question you have to ask yourself is why you want any odd visitor to
your web site to be able to send email to anyone at all even if it is
not large scale spamming.

No I don't think so, beause I do not want this.
What I want is to understand how this attack worked and find my own way
to prevent this in the furure.
There is a lot spoken about not to reinvent whe wheel but sometimes
doing so (and making errors) is a good source of understanding and
learning. So please be patient ;-)

Thank you for your feedback and best regards
Martin
 
G

Gunnar Hjalmarsson

A. Sinan Unur said:
Actually, I'll take that back ... It looks like CGI::ContactForm
automatically Bcc's the message to the email address entered by
the website visitor. It seems to me, that is a whole through which
spam can be sent to anyone.

Well, yes, if you choose to look at it that way. I consider it to be a
feature, serving two purposes:

1. The sender receives a copy of the message s/he sent.

2. If the stated address turns out to be invalid, the form owner
receives the resulting return message, letting him/her know that there
is no point in replying.

The script only allows one submitted email address, so if a spammer
would abuse it, the form owner would receive a copy of each spam
message. It should also be noted that those copies include
X-Originating-IP headers, letting you deny access to the script from
those IP addresses.

Needless to say, I have been using a few CGI::ContactForm generated
forms myself for quite a while, and the kind of abuse you are warning
for simply does not happen.

Yes, spammers must be taken into account when designing mail apps, but I
refuse to be scared to such an extent that the spammers effectively
dictate every aspect of my design.
 
A

A. Sinan Unur

A. Sinan Unur wrote :


Well, the 'and' was supposed to imply that the overhead was/is not the
reason for not using CGI.pm, it just encouraged me a little bit.
I am alos concious that my homemade modules probably have far more
overhead than CGI.pm ;-)

It might have been wrong not to use CGI.pm for this case, but I
decided not to use CGI.pm for several reasons. The website is
presented in several languages, uses databases and many templates
(with HTML::Template). Also I use CSS very much.

After I had read perldoc CGI I did not like the syntax
and felt like it might be not so easy to combine all the things I
mentioned above. (Maybe it is for an expierienced perl programmer
which I am not.) To me it looked like the HTML/CSS is not well enough
divided from the perl code (for my needs).

You do not have to use the HTML generation methods of CGI.pm to benefit
from it. In fact, I almost never do.

If the fact that the HTML generation methods are there when you use
CGI.pm, then you could switch to CGI::Minimal:

http://search.cpan.org/~snowhare/CGI-Minimal-1.24/lib/CGI/Minimal.pod
No I don't think so, beause I do not want this.

Then set up the script to only to send to one person.
What I want is to understand how this attack worked and find my own
way to prevent this in the furure.

One way would be for you to post your code here so we can explain what
is going on.

Another option is to log every request.
So please be patient ;-)

Have you seen the posting guidelines. Especially the part about posting
code?

Sinan
 
M

Martin Kissner

Gunnar Hjalmarsson wrote :
If you post the (relevant part of the) script here, somebody will
probably be able to tell you what the problem is.

Yes, absolutely.
I did not do so in the first place for two reasons.

1. I am not really sure which part is relevant.
2. It took me some time to simplify the script and remove several
conditions etc.


I hoped someone might be able to point me to the right direction without
seeing code.

Now her comes the code.
And, yes I already know that it was bad to process the user input
unchecked.
Thanks for looking at the code, I hope i have provided appropriate
information.

Best regards
Martin

--- code ---

my %userinput;
sub process {
%userinput = parse_input($_[1]);
generate_output() if send_mail();
}

sub send_mail {
use Mail::Mailer;
my $mailer = Mail::Mailer->new;
$mailer->open ({
To => '(e-mail address removed)',
# The spammers script still worked after I had replaced the variables
# with fixed values
From => "$userinput{name} <$userinput{from}>",
'Content-Type' => 'text/html',
Subject => "My Subject",
});
print $mailer <<"END"
<html>...
<br>$userinput{name}
<br>$userinput{otherfield}
...</html>
END
$mailer->close;
}

sub parse_input {
# I hope I did not mess this up when I simplified it
my $input = shift;
my %cgihash;

my @pairs =split(/&/,$input);
foreach my $data (@pairs) {
$data =~ s/\+/ /go;
($key, $value) = split(/=/,$data);
$key =~ s/\%(..)/pack("c",hex($1))/ge;
$value =~ s/\%(..)/pack("c",hex($1))/ge;
$cgihash{$key} = $value;
}
return %cgihash;
}

--- code ---
 
A

A. Sinan Unur

Well, yes, if you choose to look at it that way. I consider it to be a
feature, serving two purposes:

1. The sender receives a copy of the message s/he sent.

2. If the stated address turns out to be invalid, the form owner
receives the resulting return message, letting him/her know that there
is no point in replying.

The script only allows one submitted email address, so if a spammer
would abuse it, the form owner would receive a copy of each spam
message. It should also be noted that those copies include
X-Originating-IP headers, letting you deny access to the script from
those IP addresses.

Needless to say, I have been using a few CGI::ContactForm generated
forms myself for quite a while, and the kind of abuse you are warning
for simply does not happen.

My retraction was made given that the OP has already been identified by
some spammer as a target.

Clearly, the features you are referring to would enable the early
diagnosis of the problem, and tracking of the spammer. Although, in case
anyone decides to abuse the form, I would not want to wake up to a few
thousand extra spam messages in my mailbox.

I also have some personal experience with some IT people just not
thinking this can ever be a serious problem, and then shutting down
servers just to cover up their mistakes. I probably should not go into
more detail here.
Yes, spammers must be taken into account when designing mail apps, but
I refuse to be scared to such an extent that the spammers effectively
dictate every aspect of my design.

IMHO, a fundamental aspect of that design ought to preclude relaying
spam for third parties.

If people really want to keep a copy of their messages to you, you can
give them your email address, and use a spam filter. Or, show them a
copy of the message that was sent.

Sinan
 
A

A. Sinan Unur

Gunnar Hjalmarsson wrote :

Yes, absolutely.
I did not do so in the first place for two reasons.

1. I am not really sure which part is relevant.
2. It took me some time to simplify the script and remove several
conditions etc.

Have you seen the posting guidelines? Especially the part about posting
code?
I hoped someone might be able to point me to the right direction
without seeing code.

How? Are we mindreaders?

use strict;
use warnings;

missing (oh, and don't tell me you did not include those because someone
told you they would slow your script down).
my %userinput;
sub process {
%userinput = parse_input($_[1]);
generate_output() if send_mail();
}

sub send_mail {
use Mail::Mailer;
my $mailer = Mail::Mailer->new;
$mailer->open ({
To => '(e-mail address removed)',
# The spammers script still worked after I had replaced the variables
# with fixed values
From => "$userinput{name} <$userinput{from}>",

So, what happens if $userinput{name} contains:

(e-mail address removed),\[email protected],\[email protected] ...
'Content-Type' => 'text/html',
Subject => "My Subject",
});
print $mailer <<"END"
<html>...
<br>$userinput{name}
<br>$userinput{otherfield}
...</html>

I thought you used templates and such.
END
$mailer->close;
}

sub parse_input {
# I hope I did not mess this up when I simplified it
my $input = shift;
my %cgihash;

my @pairs =split(/&/,$input);
foreach my $data (@pairs) {
$data =~ s/\+/ /go;

Why the 'o' switch?

($key, $value) = split(/=/,$data);
$key =~ s/\%(..)/pack("c",hex($1))/ge;
$value =~ s/\%(..)/pack("c",hex($1))/ge;
$cgihash{$key} = $value;
}
return %cgihash;

No comment.

Sinan
 
M

Martin Kissner

Gunnar Hjalmarsson wrote :
Well, yes, if you choose to look at it that way. I consider it to be a
feature, serving two purposes:

1. The sender receives a copy of the message s/he sent.

2. If the stated address turns out to be invalid, the form owner
receives the resulting return message, letting him/her know that there
is no point in replying.

This is what happend to my mother only that it was not one invalid
address but over 6000 within a few hours.
Needless to say that she was close to a heart attack :)
I had to delete all of these "Mail delivery failed" over a VNC
connection to her computer.
*(To avoid misunderstanding: I have not used Gunnar Hjalmarsson module)*
Yes, spammers must be taken into account when designing mail apps, but I
refuse to be scared to such an extent that the spammers effectively
dictate every aspect of my design.

Thank you very much for writing this. Although I am on a totally
different level than you are, this encourages me to go on searching my
own way of doing things. ;-)

Best regards
Martin

btw: I really appreciate the feedback of the regulars and other
expierienced perl programmers.
This group has been helpful to me many times i the past.
 
G

Gunnar Hjalmarsson

Martin said:
$mailer->open ({
To => '(e-mail address removed)',
# The spammers script still worked after I had replaced the variables
# with fixed values
From => "$userinput{name} <$userinput{from}>",

What would happen if $userinput{name} consists of the string that this
expression results in:

qq|faked\@example.com\nCc: victim1\@example.com, victim2\@example.com,|

?
 
G

Gunnar Hjalmarsson

A. Sinan Unur said:
My retraction was made given that the OP has already been identified by
some spammer as a target.

I was talking about CGI::ContactForm, which only allows one submitted
address. The OP's script allows for just about anything, including
linefeed characters in the message header fields.
Clearly, the features you are referring to would enable the early
diagnosis of the problem, and tracking of the spammer. Although, in case
anyone decides to abuse the form, I would not want to wake up to a few
thousand extra spam messages in my mailbox.

Neither would I, and again, it has never happened to me, and nobody else
has reported anything like it.
If people really want to keep a copy of their messages to you, you can
give them your email address, and use a spam filter.

You must be joking. ;-)
Or, show them a copy of the message that was sent.

Sure, that would be an alternative.
 
M

Martin Kissner

A. Sinan Unur wrote :
Have you seen the posting guidelines? Especially the part about posting
code?

Yes, I guess you are talking about the part which suggests to post a
small but working script which can be copied and pasted and which
demonstrates the problem.
Sorry, but I was not able to provide such a script because the relevant
code is included in a selfmade module which I have admittedly designed
not optimally. It was my first somewhat larger module to write.
How? Are we mindreaders?

No, but I thought if I'd admit that I processed uncheckt userinput from
the form maybe someone could point out some examples how this input can
make my script do bad things (like execute external code).
use strict;
use warnings;

missing (oh, and don't tell me you did not include those because someone
told you they would slow your script down).

No, I won't
Actuallly I use these two always. I forgot to mention this. Sorry.
In fact I have learned this from this group and have read you pointing
it out many many times.
my %userinput;
sub process {
%userinput = parse_input($_[1]);
generate_output() if send_mail();
}

sub send_mail {
use Mail::Mailer;
my $mailer = Mail::Mailer->new;
$mailer->open ({
To => '(e-mail address removed)',
# The spammers script still worked after I had replaced the variables
# with fixed values
From => "$userinput{name} <$userinput{from}>",

So, what happens if $userinput{name} contains:

(e-mail address removed),\[email protected],\[email protected] ...

Then the mail which is sent to the reciever of the email contains some
additional sendere:
(e-mail address removed), (e-mail address removed) and (e-mail address removed)

It is a little weired to recieve one _single_ email from _four_ senders
but this is not critical yet (it's not good either, of course).

I tried adding (e-mail address removed),\nBcc:[email protected] to see if
I could use this to send myself a Bcc but it just added another sender.

I also tried putting in some code with different modifications but none
of them worked (Something like ">\n; [some perl code here]").
I thought you used templates and such.

Yes, is this relevant?
I didn't think so but I might be wrong.
Why the 'o' switch?

I have taken this from a book. The book says it saves cpu time because
the pattern is only compiled once. It suggests to always use it in loops
unless the pattern changes.
No comment.

Hm, - okay (wondering silently).

I have realized that the userinput can change the desired result but I
have not yet found out, how it can change the recipient or add
additional code to the script.

Any additional help will be gladly appreciated
Best regards
Martin
 

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,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top