homepage Welcome to WebmasterWorld Guest from 54.198.130.203
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member

Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
Forum Library, Charter, Moderators: coopster & jatar k

PHP Server Side Scripting Forum

This 41 message thread spans 2 pages: 41 ( [1] 2 > >     
Combatting Webform hijack
wendystewart80




msg:1303808
 1:20 pm on Jun 14, 2006 (gmt 0)

My webform has been hijacked. Any suggestions how to make this form secure?:

<?php
$org=$_POST['org'];
$address1=$_POST['address1'];
$address2=$_POST['address2'];
$address3=$_POST['address3'];
$city=$_POST['city'];
$pcode=$_POST['postcode'];
$region=$_POST['region'];
$tel=$_POST['tel'];
$fax=$_POST['fax'];
$email=$_POST['email'];
$web=$_POST['web'];
$name=$_POST['name'];
$image=$_POST['image'];
$projdesc=$_POST["projdesc"];
$cats1=$_POST['cats1'];
$rate1=$_POST["rate1"];
$cats2=$_POST['cats2'];
$rate2=$_POST["rate2"];
$cats3=$_POST['cats3'];
$rate3=$_POST["rate3"];
$cats4=$_POST['cats4'];
$rate4=$_POST["rate4"];
$cats5=$_POST['cats5'];
$rate5=$_POST["rate5"];

$min_age=$_POST['agefrom'];
$max_age=$_POST['ageto'];
$gptext=$_POST['pracbite'];
$gptitle=$_POST['practitle'];
$gpc1=$_POST['gpc1'];
$rate1=$_POST["rate1"];
$gpc2=$_POST['gpc2'];
$rate2=$_POST["rate2"];
$gpc3=$_POST['gpc3'];
$rate3=$_POST["rate3"];
$gpc4=$_POST['gpc4'];
$rate4=$_POST["rate4"];
$gpc5=$_POST['gpc5'];
$rate5=$_POST["rate5"];
$praccontact=$_POST["praccontact"];

mail ("email address", "Practice Bite",
"New Practice Bite

Project Info:
Organisation: $org
Address: $address1
$address2
$address3
City: $city
Post code: $pcode
Region: $region
Tel: $tel
Fax: $fax
Email: $email
Web: $web
Contact Name: $name
Image: $image
Project Desc: $projdesc
C1: $cats1
R1: $rate1
C2: $cats2
R2: $rate2
C3: $cats3
R3: $rate3
C4: $cats4
R4: $rate4
C5: $cats5
C5: $rate5
Practice Example:
Min age: $min_age
Max age: $max_age
P Title; $gptitle
P Text: $gptext
P1: $gpc1
R1: $rate1
P2: $gpc2
R2: $rate2
P3: $gpc3
R3: $rate3
P4: $gpc4
R4: $rate4
P5: $gpc5
R5: $rate5
Contact Name: $praccontact"
);
echo ("<p>Your practice bite has been submitted.</p>
<p>Many thanks.</p>");
?>

 

justgowithit




msg:1303809
 1:34 pm on Jun 14, 2006 (gmt 0)

- ** Validate your input prior to passing it (it doesn't look like you have any validation here)
- Use a variable security graphic input
- Make sure that register_globals is OFF
- Make sure your originating form's action is declared correctly
- Post through https and redirect successful queries back

Habtom




msg:1303810
 1:41 pm on Jun 14, 2006 (gmt 0)

I would use combination of preg_match(), trim(), htmlentities(), add_slashes() and few others to clear up the input before I begin using it.

Habtom

justgowithit




msg:1303811
 1:43 pm on Jun 14, 2006 (gmt 0)

You could also use something like Zend_Mail.

henry0




msg:1303812
 2:41 pm on Jun 14, 2006 (gmt 0)

So you did find the right place :)
First you need to surround each post with a function similar to this one:
That could be located at root level
And named: secure.php

<?
function Clean($string){
if (get_magic_quotes_gpc())
{
return $string;
}
else
{
return mysql_real_escape_string($string);
}

$string = trim($string);
$string = safeEscapeString($string);
$string = htmlentities($string);
return $string;
}
foreach($_POST as $name => $value){
$_POST[$name] = Clean($value);
}
foreach($_GET as $name => $value){
$_GET[$name] = Clean($value);
}
foreach($_COOKIE as $name => $value){
$_COOKIE[$name] = Clean($value);
}
foreach($_REQUEST as $name => $value){
$_REQUEST[$name] = Clean($value);
}
?>

Using it:

Include the file within your form destination script
require_once("../../secure.php");

Next:

For example: $main_title =Clean($_POST['main_title']);

Other security
Example email regex:

if (isset ($email) &&!empty ($email) )

$regexp = "^([_a-z0-9-]+)(\.[_a-z0-9-]+)*@([a-z0-9-]+)(\.[a-z0-9-]+)*(\.[a-z]{2,4})$";
if (!eregi($regexp, $email))
{
echo "The email should ONLY contain Alphanumerical Characters! (Alphabetical and numeric) And: @ and - or_ <br>
<b>You entered: $email</b><br>
<a href='../register.php'><b>Please try again</b></a>";

Exit();
}
else
{

DewChugr




msg:1303813
 7:16 pm on Jun 15, 2006 (gmt 0)

This should help with some attacks. Include this in the web page with your form and pass the token as a hidden value. This will insure that the form you processed was actually filled out on your website. With the time session you can limit the time between when the form loads and when it is processed.

$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
$_SESSION['token_time'] = time();

Then when you get to your validation page include this.

if ($_POST['token']!= $_SESSION['token']) {
echo "Invalid data!";
exit;
}
$token_age = time() - $_SESSION['token_time'];
if ($token_age >= LOGIN_TIME_LIMIT) {
// time limit can be set here as number instead
// of LOGIN_TIME_LIMIT define, such as 60*10
exit;
}

I didn't create this, but I can't remember where I first saw it. Of course, you still need to make sure that the information passed with your form is valid.

Steve

henry0




msg:1303814
 7:49 pm on Jun 15, 2006 (gmt 0)

This check that the data is the expeted data
<<<
// ************* State

$state=htmlentities($_POST['state']);
$clean_state = array();
switch ($_POST['state'])
{
case 'ct':
case 'ma':
case 'ny':
$clean_state['state'] = htmlentities(($_POST['state']));
break;
}
$state=$clean_state['state'];
if ($state!=$clean_state['state'])
{
echo" <h1>Alert! we are aware of the tentative intrusion in State options</h1><br>";
Exit();
}

// ******* End of state

>>>

eelixduppy




msg:1303815
 7:59 pm on Jun 15, 2006 (gmt 0)

As a slight moderation to henry0's code, I would do something like this:

$state=htmlentities($_POST['state']);
$acceptable_states = array("ct","ma","ny");
if(in_array($state,$acceptable_states))
{
echo "State is good";
}
else {
echo "State is bad! :(";
exit;
}

This should work ;)

henry0




msg:1303816
 8:14 pm on Jun 15, 2006 (gmt 0)

Looks good
Reason behind? Less RPM to the engine :)

eelixduppy




msg:1303817
 8:38 pm on Jun 15, 2006 (gmt 0)

The reason is with your declaration ($state=$clean_state['state']; ) the following if statement would never evaluate to true. ;)

henry0




msg:1303818
 8:57 pm on Jun 15, 2006 (gmt 0)

Sure, I do not want it to be true
there are tens of the same checking input from a form going to a second page that does the query
I cannot and am not interested in echoing "true" while processing I am only only interested in bad case

so yours if indeed fine if you need it to be true.

(Don't think that I'll be rude by not answering again
got a meeting!)

eelixduppy




msg:1303819
 9:06 pm on Jun 15, 2006 (gmt 0)

I'm sorry for my being vague ;) What I meant to say was that with your script, there will never be an error thrown because the if statement will never be true. If you set one var equal to the other, and then compare them right after, you are going to find that they are the same, therefore not ever evaluating to be different. My script could be changed like this to not show a statement on a good state:
$state=htmlentities($_POST['state']);
$acceptable_states = array("ct","ma","ny");
if(in_array($state,$acceptable_states)==FALSE)
echo "State is bad! :(";
exit;
}
//now use $state from now on

Hope I made myself understood better. BTW, have fun at your meeting ;)

henry0




msg:1303820
 10:52 am on Jun 16, 2006 (gmt 0)

Back in Henry’s “snippet post mortem”
I try to make sure that the expected data is the expected one
And that the data is to be stored in an empty array
$clean_state = array();

Then the job is to try to impeach any var from a source here named clean_state not to be an expected value.

However the client form may be (by a malicious user) tricked at the $_POST[‘state’] level.

So the switch statement helps in properly filtering the data.

So again $clean_state is initialized in an empty array
Once we know that $_POST['state'] can only be CT, MA, NY
We store the value in $_POST['state']

Therefore state may be used anywhere in the script with a real good assumption that the data is not tinted.

I was inspired by a security authority, to me it makes sense as is.

Anyway the beauty of PHP is that there is more that one way to skin a cat

le_gber




msg:1303821
 8:36 am on Jul 1, 2006 (gmt 0)

I was inspired by a security authority, to me it makes sense as is.

would that be Chris Shiflett on page 11 of 'Essential PHP Security' ... :)

Currently going over the book for my current PHP project, some very good stuff in there, but a bit hard for newbies (ie. me)

henry0




msg:1303822
 11:43 am on Jul 1, 2006 (gmt 0)

Hey, aren't we peoples of great taste with an appetite for intellectual challenges! :)

That’s the one, I mentioned it a couple of months ago; I think it was added in our “Library listing”

Not that hard to read and understand, I really like it a lot.

whoisgregg




msg:1303823
 5:11 pm on Jul 1, 2006 (gmt 0)

My webform has been hijacked.

I think Wendy is experiencing the problem where this form is being used as a spam relay... Hijacking a webform that uses php's built-in mail function is a relatively simple matter of "injecting" cc: and bcc: headers.

Although all the validation suggested thus far is a good idea to do, it still doesn't address this spam relay problem. A more specific check is required, something along the lines of (untested pseudocode):

// bcc and cc are the worst, but let's be thorough
$header_injection_attempts = array(
"bcc:",
"cc:",
"to:",
"content-type:",
"mime-version:",
"multipart/mixed",
"content-transfer-encoding:"
);
// lowercase the email
$email_body_lower = strtolower($email_body);
// innocent until proven guilty
$injection_attempted = false;
foreach($header_injection_attempts as $attempt){
// check the email for each possible attempt
if(strpos($email_body_lower, $attempt)!==false){
// we found something bad being attempted
$injection_attempted = true;
// get out of the loop
break;
}
}
if($injection_attempted){
// log the error, and visitor IP
// don't send the email
} else {
// send the email
mail(....);
}

henry0




msg:1303824
 5:44 pm on Jul 1, 2006 (gmt 0)

Looks like it will perform a good check
Thanks, if you don'tmind I could use it.
I suggest adding to the array " .EXE "

At first glance I did not understand what were your needle (read too fast) I thought that the top of the script was the usual email stuffs until I realized it was an array :)
I will test it but how can we be sure that it will not result in a false/true or true/false
I guess testing on production is the only choice.

<< edit
added " .EXE "
>>>

le_gber




msg:1303825
 7:28 pm on Jul 1, 2006 (gmt 0)

[newbie question]

Appologies for the newbie question but what would happen if one was to make the mail() variables into CONSTANT

Would one malicious person still be able to 'inject' one of our form and hijack it?

[/newbie question]

whoisgregg




msg:1303826
 10:35 pm on Jul 1, 2006 (gmt 0)

how can we be sure that it will not result in a false/true or true/false

A false positive will occur if the user legitimately includes any of those text strings in the message. You can search for those terms only if they occur at the beginning of a new line, but for simplicity's sake I didn't include such a check in my sample pseudo code.

For example, this message would trigger a false positive (which would frustrate the customer), even though it is not an injection attempt:

"Hello, I emailed your company before and cc:'ed the shipping department, but my widgets still haven't arrived!"

So you probably want to do a better, specific search for the injection code with a "\r\n" before it. (Which may be as simple as adding that to the array in my sample code, dunno -- haven't tested it. Can strpos find "\r\n?")

mail() variables into CONSTANT

The headers are "injected" through the message parameter so if you allow user input to be included there, then whether the message parameter comes from a variable assignment or from a defined constant wouldn't make a difference. At least, I don't think it would... to be honest I only discovered what Constants were for a couple weeks ago. :/

willybfriendly




msg:1303827
 11:42 pm on Jul 1, 2006 (gmt 0)

Nice article on mail injection in PHP here -

[securephpwiki.com...]

The article offers this function as a solution:

<?php
$from = $_POST["sender"];
$from = urldecode($from);
if (eregi("\r",$from) ¦¦ eregi("\n",$from)){
die("Why? :(");
}
?>

There must be a lot of this going on. I just had to tighten up a 3 year old script last night after noticing attempts to hack it - probably successful I might add since the script was so full of holes. (It was one of the first I ever wrote.)

Live and learn...

WBF

henry0




msg:1303828
 12:15 pm on Jul 2, 2006 (gmt 0)

Great thread, we both learn from it
WBF, this is a very first to me.
Hope no one with commerce in mind has it.

From your link:
<<<
We see you're using Internet Explorer, which is not compatible with this site. We strongly suggest downloading Firefox. We think you'll like it better:
>>>

I have both and Opera, but I did not know that anyone was pushing so strongly toward FF.

rohitj




msg:1303829
 2:44 pm on Jul 3, 2006 (gmt 0)

add slashes and validate that the script isn't being remotely executed.

There's a good article on sitepoint that you need to check on common exploits for PHP scripts--some of them are applicable in this situation.

jatar_k




msg:1303830
 6:02 pm on Jul 3, 2006 (gmt 0)

another thread where we have covered a lot of validation and security tips

PHP Security [webmasterworld.com]

incrediBILL




msg:1303831
 7:20 pm on Jul 3, 2006 (gmt 0)

Include the IP address and USER AGENT of each form submitted in the email and then you might know who to block if it's coming from a single source.

the13thmajestic




msg:1303832
 12:18 am on Jul 4, 2006 (gmt 0)

*Eyes Crossed!*

Sooo...can someone please sum all of this up in english for those of us who are novices or who learn by example?

I have been a victim of this very problem and had to take all of my forms down. I'm not versed enough in PHP forms to even allow for security as it pertains to the coding itself.

Of course I am aware of the need for secure forms, but until now it hasn't been an issue for me so I haven't learned that aspect of forms. I can create a working form using PHP just fine, I just don't know the security part of the formula works yet.

xalex




msg:1303833
 4:47 am on Jul 4, 2006 (gmt 0)

This happened to me few weeks back. Your first line of defence is a good CAPTCHA. Second make sure you use the function addslashes(). Those two alone will take care most of the spam.

~Security is relative.

willybfriendly




msg:1303834
 5:07 am on Jul 4, 2006 (gmt 0)

addslashes will do nothing to prevent email injection. Until about 6 months ago I knew nothing about this vulnerability. Until a week ago I had ignored it. Then I got bit.

Read through this thread again, and read the articles referenced. The PHP mail() function acts as an open proxy if steps are not taken to harden it.

WBF

jatar_k




msg:1303835
 6:06 am on Jul 4, 2006 (gmt 0)

>> can someone please sum all of this up in english for those of us who are novices or who learn by example

never trust anything any user submits to your site

test it for length, size, type and anything else that is appropriate, use captcha if needed, harden your mail functions so they can't be tricked

there are other things that may need to be done as well

henry0




msg:1303836
 1:07 pm on Jul 4, 2006 (gmt 0)

Variation on WillybFriendly:

(for each field used in an email.)
$field = preg_replace( "/[\n\r]+/", " ", $field );

Kelowna




msg:1303837
 10:38 pm on Jul 4, 2006 (gmt 0)

Well I for one know nothing about coding and can only offer some newbie advice to those who are facing the same problems as I am.

It appears that in my case some sort of autosubmit to blog software thinks that my forms are some sort of blog that they can post to. I was getting tons of submissions that just looked like someone tring to add spam links to a blog. What I did was renamed my script and that worked for a few days... they must be spidering pages looking for form scripts to submit to as they found me again with the new script name.

What I did next was to rename the from processor script again, then scramble the code using one of those free java things so the html looks like java but all works well on the page.

This seems to have worked for me as their spiders no longer can find the php script and I can block the 100's of reffer's ips that are trying to post to the old script names that I find in my logs. Hope that helps those who are as php challanged as myself.

This 41 message thread spans 2 pages: 41 ( [1] 2 > >
Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved