Forum Moderators: coopster & phranque

Message Too Old, No Replies

Keeping Scripts For My Server Only

How to keep someone from sending data to my scripts

         

StupidScript

11:40 pm on Sep 6, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I have a situation where someone has copied one of my forms to their hard drive and they are executing it from their machine, passing the data to my server to handle.

It's not working completely, as the mail portions of the script are failing (because they are not executing from my server), but the gibberish they are using in their fake form is ending up in my database.

How can I test for execution from my server only, and halt the script when it is executed from somewhere else?

Would

gethostbyaddr()
be useful, and how would I implement it?

Thanks in advance.

KevinADC

1:43 am on Sep 7, 2005 (gmt 0)

10+ Year Member



this may not be the best solution but you can try it. Use $ENV{'HTTP_REFERER'} to get the referring page and check it against your websites name or IP numbers:

my $site = 'www.foobar.com';
if ($ENV{'HTTP_REFERER'} =~ m¦http://([^/]*)$site¦i) {
do something useful
}
else {
do somthing like print a message or exit the script
}

[edited by: jatar_k at 6:06 am (utc) on Sep. 7, 2005]

volatilegx

1:38 pm on Sep 7, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'd log their IP address and then just ban them. The HTTP_REFERER header is easy to spoof.

StupidScript

5:52 pm on Sep 7, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thanks, so far, folks.

How would I detect when they are attempting to send their output through my script in order to log their IP? It's not a port scan or a login situation, so I guess it would come in through a normal server port and look just like normal traffic, except for what it was trying to do.

Also, these attacks are coming through many of the APNIC-registered servers ... which means they're probably spoofs and will cycle through to the next spoofed machine when one IP is blocked. I have grabbed the IP address from the data that ends up in our databases, but by then it's too late.

I'm thinking it may be more reliable to set up a little auth script readable only by the web server user and requiring it in each script, but I'm stuck on how to get the auth value into the script execution without including it in the form that's being hijacked.

Thanks, again.

StupidScript

6:32 pm on Sep 7, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



BTW KevinADC, your workaround does what you expect. :)

If the script is called from somewhere other than the hosting server, it can be detected, and I can grab the IP address from that, too ... unless there is some HTTP_REFERER trickery going on.

KevinADC

10:18 pm on Sep 7, 2005 (gmt 0)

10+ Year Member



the http referer can be spoofed, but I assume the IP address can too, although I am not sure.

you can also try:

REMOTE_ADDR
SERVER_ADDR
SERVER_NAME

to try and block remote usage of your script.

StupidScript

11:16 pm on Sep 7, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thanks again!

SERVER_ADDR seemed to be a good bet during testing, but there's still a lot of ifs and elses involved. Interestingly:

if ($ENV{'SERVER_ADDR'}=="198.112.13.") ...

matches all of the addresses in that Class C block, 198.112.13.1, 198.112.13.2, etc. Since my domains are using many IPs within a C block, it looked pretty good as a broad-stroke identifier.

Unfortunately, SERVER_ADDR and other SERVER environment variables (like SERVER_NAME) apply to the server that's running the script ... not from whence the data came. For that info, the only environment variable I have found so far is HTTP_REFERER, which we all acknowledge can be easily forged. REMOTE_HOST is the IP address of the client, every genuine form-submitter has their own in the same way any bogus form-submitter does, and it is subject to the APNIC/spoofing issues noted above.

Still working on an auth script and getting the correct auth info to it without including it in the form ...

volatilegx

5:44 pm on Sep 8, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You mentioned something about the data they submited being garbage and your server failing to handle it properly. Couldn't you execute a subroutine upon this failure and ban the IP address at that point?

The IP address is contained in the $ENV{'REMOTE_ADDR'} variable. Also, remote IP addresses are very difficult to spoof.

StupidScript

8:40 pm on Sep 8, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thanks, volatilegx.

The way I have it set up now is:

1) Attempt made to pass data to script
2) Garbage of this attack's type detected
3) Log IP, timestamp and form name in a special log file
4) Ban IP using ipchains and iptables
5) Redirect to hacking law information site
6) Exit script

That works ... the log file is being populated and I am not seeing any entries of this type in my database.

But it's pretty specific to those scripts and that type of attack. I'd really like a more global solution to prevent any script on my server from being given data to process from any location other than from my server. So far HTTP_REFERER seems to be the only environment variable that might indicate this condition, but since it's flaky, I'm continuing to explore a seperate auth function as I mentioned above.

KevinADC

9:24 pm on Sep 8, 2005 (gmt 0)

10+ Year Member



htaccess might provide another layer of protection. requiring a name and password would too but might be too inconvenient for your purposes. You can also look into captcha phrasess, which is more for robot attacks but that might be what is happening to you. A bot is indexing the site or just attacking it for some reason.

moltar

9:44 pm on Sep 8, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



if ($ENV{'SERVER_ADDR'}=="198.112.13.") ...  

matches all of the addresses in that Class C block, 198.112.13.1, 198.112.13.2, etc. Since my domains are using many IPs within a C block, it looked pretty good as a broad-stroke identifier.

That is completely wrong. Should be:

if ($ENV{'SERVER_ADDR'} =~ /^198\.112\.13\./) { ... }

StupidScript

10:12 pm on Sep 8, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Yes. You're right. For my purpose, I should have written:

$ENV{'SERVER_ADDR'} eq "194.123.36."

which won't match. Use of the regex you posted would have the same result as the code I posted erroneously earlier, i.e. matches everything in that C block.

Thanks for the correction. ;)
(I'm usually drowning in PHP, so using the different comparison operators for numeric values or strings in Perl is surprising me.)

The "captcha phrases" looks interesting ... force the inclusion of a SESSION variable of some kind ...

freeflight2

10:54 pm on Sep 8, 2005 (gmt 0)

10+ Year Member



with a firewall such as apf a simple 'apf -d IP' would do the trick.

moltar

5:15 pm on Sep 9, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



$ENV{'SERVER_ADDR'} eq "194.123.36."
is also incorrect :)

You can't literaly compare blocks of IP addresses. The IP literlay has to be '194.123.36.' which, of course, is not a valid IP address. With literal comparison you can only match one IP at a time. For example:

if ($ENV{'SERVER_ADDR'} eq '127.0.0.1') { ... }

rocknbil

5:23 pm on Sep 10, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I had some people hammer our scripts that would add a bcc field to the email field, and drop 1000 or so addy's at a time to spam AOL. We began logging their activity explicitly, and from what I can tell, this is done with a program. It hits the script again and again until it figures out the email field, then composes it's dirty work.

The bottom line is that if a program is sophisticated enough, it's being run from the command line and the IP address is EASILY spoofed. So denying a service based on REFERER or other environment variables is a waste of time.

Identify exactly what you expect to be incoming from YOUR form and accept those values ONLY. Be especially aware of the email address: it must match only the pattern

/^[\w.+-]+\@[\w.+-]+$/

Someone please chime in with a better regexp here. :-) I use this one in combination with several other screen methods on the email address.)

Secondly, don't make the "to" address a hidden field in the form. Put it in your script and HARD CODE IT. Even storing it in a variable can be compromised if someone figures out the variable name. What good would it do to hack a script if it can only go to you?

Hope this is the least bit helpful . . .

moltar

5:29 pm on Sep 10, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I had some people hammer our scripts that would add a bcc field to the email field, and drop 1000 or so addy's at a time to spam AOL.

Try to avoid using common names for scripts such as

/cgi-bin/formmail.pl
.

being run from the command line and the IP address is EASILY spoofed.

That's a myth. You cannot "spoof" an IP address unless you mean going through proxy. Or you mean spoofing referrer?

lexipixel

6:19 pm on Sep 11, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month




the mail portions of the script are failing (because they are not executing from my server), but the gibberish they are using in their fake form is ending up in my database.

I have scripts that allow users to add records to the database. In the cases where people may try to add data that I do not want, I have the script write to a temporary database and only after I verify the data does it get moved to the live database.

Another approach I use is to have the script generate a random number and build a string which is based on date, IP address and the random number... the script requires the user to provide an email address, and then emails a "verification message" to that address with the unique random number embedded in a link --- the user needs to receive the email and click the link to verfiy they actually submitted the data... this extra step has cut my junk submissions to 5% of what they were prior to adding this verification process. Again, the records are stored in a temp database until verified so my live data stays clean.


How can I test for execution from my server only, and halt the script when it is executed from somewhere else?

People have suggested several things here, but the truth is anything a "human" can enter into a form and submit, can be automated with a script.

It reminds me of the old MAD Magazine "Spy v. Spy" --- one spy drops an anvil, the other puts a trampoline under it to bounce it back -- the first one then adds a magnet to catch the anvil, etc.. etc...

Verification of email address of person submitting form data has been the only thing I've found that works.

rocknbil

7:15 pm on Sep 13, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You cannot "spoof" an IP address unless you mean going through proxy.

Another late-night feux pas. What can be done though, is once several boxes get rooted, you telnet to one, from there, to another, to another . . . and when you're all done delete the logs. My point was only that you really can't rely on any environment variables to ID an attack.

Verification of email address of person submitting form data has been the only thing I've found that works

Do you mean some method of connecting with the remote mail server and getting a response (or just regexp matching)? If so i implore you, PLEASE SHARE!

I suggest that everyone log EVERYTHING coming in from their forms. You will be surprised at what is going on that you don't know about. I've been watching people trying to hack using other fields - ANY fields - using %0A and entering their own BCC and CC fields. And if you don't screen all data, it works. So even if you DO screen email - they can still spam using your servers.

So much talent wasted . . .

StupidScript

9:07 pm on Sep 13, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I see this is a pretty big problem:

WWW PHP Forum thread [webmasterworld.com]

I've got various regexps and so forth in the scripts now, and am logging and dropping offenders. Seems to be keeping the rabble out for now.

Here's one to protect against attempts to add BCC and CC headers to the single From header by using newlines:

if ($email =~ /\\n/) { log-and-drop }

for example ... like I said, it seems to be a pretty big problem.

rocknbil

9:05 pm on Sep 16, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



SS - that would only work if the email field is the one they are hacking, and it's not always! Besides I never had any luck with the newline subs in the header, I've tried it many ways, including that one you showed in particular. I just couldn't get it to stop them (see below for how I DID.)

Here's an even better [webmasterworld.com] current thread on the topic.

StupidScript

10:05 pm on Sep 16, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thanks for the link, rocknbil.

if ($email =~ /\\n/) { log-and-drop }

Just checks for newlines and

if (($email =~ /\\r/)¦¦($email =~ /\\n/)) { log-and-drop }

should catch carriage returns AND newlines.

My main concern with this is the email field, although the bigger concern is allowing anyone to run any script from somewhere other than my server.

IF the email field is used for specifying the "To:" header, then it's susceptible to being used for spam. For example (using phpmailer class):

$email=$_POST["email"];

...

$mail->AddAddress = ($email,"Spam Target");

...

In this case, without further checking, someone could place this in the "email" form field:

me@mail.com\n\nBCC:victim@email.com,stooge@example.com

and get the BCC header to be created for them, sending spam to "victim" and "stooge". They could even do something like:

me@mail.com\n\nBCC:victim@email.com,stooge@example.com\n\nBODY:My spam message

to get their message out. Mail isn't too particular about how it gets its headers. It'll even send properly with duplicate, forged headers, like my "real" BODY and their fake BODY, one after the other, as long as two newlines separate the headers.

So that's what my previous post was about ... I'll work on keeping others from being able to run my scripts from their machines, but the emergency situation was the possibility of using my machine to send spam.

StupidScript

11:40 pm on Sep 16, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Sorry, rocknbil. I just read your last post in the thread you linked to ... and it's clear you already know about the dangers of allowing newlines/carriage returns in any mailing field. Thanks! :)

rocknbil

1:11 am on Sep 17, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



NP, but I could never get newline subs to work on these guys.

One thing it seems like you may be missing though - it's not just the "to" or the "from" header. If they violate the subject field with a BCC, that would work too. I've even seen (apparently) attack other fields, such as the "how you found out about us" or even comments/message fields. So that's why I say all, better safe than not!

StupidScript

6:12 pm on Sep 19, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I agree: Any form field that will end up being part of a mail message is susceptible to attack.