Welcome Guest ( Log In | Register )



 
Reply to this topicStart new topic
> Quickly Create Form Variables, simple form, variable creation, referer check, safe guard variables
mastercomputers
post Dec 15 2006, 05:00 PM
Post #1


BUG.SWAT.PATROL
Group Icon

Group: Members
Posts: 626
Joined: 1-September 04
From: Auckland, New Zealand
Member No.: 27



The reason I wanted to share this is I've seen so many people do this with their forms when using PHP.

CODE
$username = $_POST['username'];
$password = sha1($_POST['password']);
$another_var = $_POST['another_var'];


... and so on, just imagine if you had a large number of form inputs, do you really want to create each and every variable name?

Why people do this, is probably due to most of the examples I've seen on the web, that does not show an easier and much quicker way of doing it. Though my way might be much easier and quicker, it does introduce security concerns which I've tried to eliminate the most commonly seen problems with the method I'm about to show but since I only created this today, I haven't really had the chance to extensively test every possible flaw that could lurk in it.

I should mention I develop on PHP 5, but this should work with PHP 4.3 and could possibly work with PHP 4 but I think some of the things I've done would need to be rewritten to work with it.

So first of all the complete PHP page that demonstrates what I want to show, I will break down the PHP code and explain that, the form is simple HTML conforming to XHTML 1.1 standards, but the importance here is the PHP code itself.

simple_form.php
CODE
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-NZ">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Quick Form Variable Creation</title>
    </head>
    <body>
        <?php
        $allowed_referers = array('yourdomain.com');
        if (!empty($_POST['login']) && $_POST['login'] == 'Login')
        {
            if (!empty($_SERVER['HTTP_REFERER']))
            {
                $referer = current(array_splice(explode('/',$_SERVER['HTTP_REFERER']),2,1));
            }
            else
            {
                exit('<h1>BAD REFERER</h1><p>Oops!</p></body></html>');
            }
            if (!in_array($referer,$allowed_referers))
            {
                exit('<h1>BAD REFERER</h1><p>Oops!</p></body></html>');
            }
            array_pop($_POST);
            $created_variables = '';
            foreach ($_POST as $name => $value)
            {
                if (empty($$name))
                {
                    if (!empty($name) || !empty($value))
                    {
                        ${$name} = $value;
                        $created_variables .= '<tr><td>$'.$name.'</td><td>'.$value.'</td></tr>';
                    }
                }
            }
        }
        ?>
        <p><strong>Please Note:</strong> This is just a <em>demonstration</em>, please do not insert <strong>passwords</strong> that you use, as it is displayed back in plain text.</p>
        <br />
        <p><?php if (!empty($username)) { echo 'Welcome back <strong>'.$username.'</strong>, Thank you for logging in.'; } else { echo 'Hello <strong>Guest</strong>, Please log in.'; } ?></p>
        <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
            <fieldset>
                <legend>Login Form</legend>
                <ul>
                    <li><label for="username">Username:</label> <input id="username" name="username" type="text" /></li>
                    <li><label for="password">Password:</label> <input id="password" name="password" type="password" /></li>
                </ul>
                <input id="login" name="login" value="Login" type="submit" />
            </fieldset>
        </form>
        <?php
        if (!empty($created_variables)) { ?>
        <table>
            <thead>
                <tr>
                    <th>Variable Name</th>
                    <th>Variable Value</th>
                </tr>
            </thead>
            <tfoot>
                <td colspan="2"><em>These were the variables created from the above form.</em></td>
            </tfoot>
            <tbody>
                <?php echo $created_variables; ?>
            </tbody>
        </table>
        <?php } ?>
    </body>
</html>


First of all, I'll explain the form. This is a basic form, that takes user's input and sends the information back to the same page to be processed. The input names of the form become the created variables so that we do not have to manually create them ourselves. With the information gathered from the form, it will alter and add additional information to the page, creating a table after the form, displaying the variables created and the values they were assigned. Remember the password is not encrypted in any way with this form, it is a demonstration and will display it back in plain text, if you're using a password input, be sure to encrypt the variable that it is assigned. In this example, you would do something like the code below after the variable has been created:

CODE
if (!empty($password)) { $password = sha1($password); }


Now on to the real stuff.

CODE
$allowed_referers = array('yourdomain.com');


This is to make sure that the form information being received is going to come from the domain you list in this array, as we don't want the form to be submitted from any other place as they could then alter our automatically created variables in a way that could compromise security. Now to make it more secure (just thought of it now), I would create a md5 hash of the form so that I can tell that the page has not been altered at all as it's possible to change the clientside of the page and still have it seem like it came from your site.

CODE
if (!empty($_POST['login']) && $_POST['login'] == 'Login')
        {


This starts the form processing, when the login button is pressed, the posted information gets sent back to the page, and this checks whether login was created and whether the login had the value we made it.

CODE
if (!empty($_SERVER['HTTP_REFERER']))
            {
                $referer = current(array_splice(explode('/',$_SERVER['HTTP_REFERER']),2,1));
            }
            else
            {
                exit('<h1>BAD REFERER</h1><p>Oops!</p></body></html>');
            }
            if (!in_array($referer,$allowed_referers))
            {
                exit('<h1>BAD REFERER</h1><p>Oops!</p></body></html>');
            }


This is the referer check, it checks whether our server got the referer, it then grabs the domain part of the referer (I hope) and if it's not set or is not our allowed referers, it exits with a simple BAD REFERER message, which I'm sure you could be more creative about it. This is where PHP 4 could fail, but I'm sure there's alternative ways to grab the referer.

CODE
array_pop($_POST);


This is to drop the $_POST['login'] from the $_POST, so we don't create a variable for it, but if you do want it, then leave it in. Now I believe this relies on form ordering, so if the submission is not the last, we could not do this, but since we created the form, and made sure it came last, then this should be fine for us.

CODE
$created_variables = '';


This isn't vitally important, it's just to help this demonstration and give us something we can store information in to display back so we can see what happened.

CODE
foreach ($_POST as $name => $value)
            {
                if (empty($$name))
                {
                    if (!empty($name) && !empty($value))
                    {
                        ${$name} = $value;
                        $created_variables .= '<tr><td>$'.$name.'</td><td>'.$value.'</td></tr>';
                    }
                }
            }


This is what people were probably waiting for, the part that makes variable creating easier, basically we are looping through each $_POST item, using the form name and the value. The first if statement checks that what we are using in the form is empty and not used already, otherwise we could potentially overwrite an internal variable we use as it could affect the behaviour of the program, you could possibly handle this another way by changing the variable so it doesn't conflict but then you would need to figure out how you can remember that change, I don't like variated variables like that, e.g. $password, $password1, $password3 so make sure that your form doesn't use anything that conflicts and this is also an area we have to make sure is secure.

Next I did a check if the form name exists and if the value exists, if not, I don't bother with creating a variable, but in your case, you may want to create the empty variables too, and perform your own check on them, incase they are required variables. A quick way you could do this, if you had required variables is to prefix their form name with req_ and then if you encountered this prefix, make sure it's assigned, if not assign a boolean value that the form failed, and tell them what it was that was needed to be filled in and do not process the form any further.

The part that automatically creates the variable is the ${$name} = $value; reading this from the inner, {$name} is the form name the brackets convert it to it's name value, e.g. username, the outer $ is for the variable, so we get $username. Simple right? You could also do $$name but it's not the best practise, however I had to use it in the above for checking if the variable had been created, so it's the only time I'm letting it slide.

That's pretty much all I should need to explain, the rest just checks the variables are created and displays the information back, there's nothing too drastic about what it's doing. I just want to wrap this up, as I got to get back to doing my work.

So hopefully this helps a few people.

Cheers,

MC
Go to the top of the page
 
+Quote Post
Hercco
post Dec 16 2006, 07:14 PM
Post #2


Super Member
Group Icon

Group: Members
Posts: 595
Joined: 4-September 04
Member No.: 228



Thanks for the tip. That's something I've never came to think about probably because I've rarely had to process massive amounts of form input. Proof that's it's really worth reading these forums.


And where you commented that PHP 4 could fail, I don't think it will. I didn't test the code but I didn't notice anything unfamiliar to me and I've always developed in PHP 4.

Go to the top of the page
 
+Quote Post
TavoxPeru
post Dec 16 2006, 11:44 PM
Post #3


Super Member
Group Icon

Group: [HOSTED]
Posts: 744
Joined: 8-April 06
From: Lima - Peru
Member No.: 12,579



First of all congrats, excellent topic, especially the one related with the variables variable. Now, i just test your code and it have an error because it doesnt shows the table with the submited data when you fill both fields, but dont worry its as simple as add an ! symbol wink.gif.

Simply change this line:
CODE
if (empty($$name))

with this one:
CODE
if (!empty($$name))

Best regards,
Go to the top of the page
 
+Quote Post
mastercomputers
post Dec 22 2006, 04:31 AM
Post #4


BUG.SWAT.PATROL
Group Icon

Group: Members
Posts: 626
Joined: 1-September 04
From: Auckland, New Zealand
Member No.: 27



Actually TavoxPeru,

I did notice that area failing on PHP 4.4.4 (Astahost's version which means the area I commented won't fail, but anything below PHP 4.3 could be of some concern), PHP 5 processes this correctly.

What you are suggesting isn't what the code reflects, what you're saying is, if the variable does exist (not empty means has something), then overwrite the already existing variable. This to me seems like register globals is on, or some automatic variable creation has already taken place, not the way I would configure php.ini nor would this be default, I'll try to dig into it more and see why the variables are already being created, as I might write a routine to remove this automation (I know this is what we wanted, but securing this area would be far better and just allowing ourselves to do this automation).

For now in PHP 4, just comment out if( empty(${$name}) ) { and the ending bracket } and it'll work as intended but will still overwrite existing variables, unless you think you can post the code to solve this before I get to work on it, then by all means do so.

I'll see what I can do, I'm not at home at the moment, and I'm not sure when I'll post the solution, I've also got a bit of code clean up that I did that I want to post too as well as more additions to this code.

Now the reason I'm sharing this area, is that I started working on a complete class for form processing, so that the class can handle all aspects of a form, including uploaded files, mailing, searching, registration, you name what the form does, and that is what I want to have in it. I'm also trying to incorporate ajax into the mix too, so that it will seem to process a lot smoother.


Cheers,


MC
Go to the top of the page
 
+Quote Post
TavoxPeru
post Dec 22 2006, 05:03 AM
Post #5


Super Member
Group Icon

Group: [HOSTED]
Posts: 744
Joined: 8-April 06
From: Lima - Peru
Member No.: 12,579



The cPanel's phpinfo -PHP 4.4.4- shows that the register_globals is on, so i will test the code locally with PHP5 to verify if it works fine, i guess that this is the problem.

Related to the class that you are working on, I think that you have a lot of work to do wink.gif so, in case you need some help, please let me know to colaborate.

Best regards,
Go to the top of the page
 
+Quote Post
mastercomputers
post Dec 24 2006, 12:12 AM
Post #6


BUG.SWAT.PATROL
Group Icon

Group: Members
Posts: 626
Joined: 1-September 04
From: Auckland, New Zealand
Member No.: 27



Here's the updated version that works with PHP 4.4.4 and above with register_globals on. I've seperated the HTML and coding, so that it's not all mixed together, it's easier to work with it if it's seperated.

Here's the simple form (form.html)

CODE
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-NZ">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Simple Login Form</title>
    </head>
    <body>
        <form action="login.php" method="post">
            <fieldset>
                <legend>Login Form</legend>
                <ol>
                    <li><label for="username">Username:</label> <input id="username" name="username" type="text" /></li>
                    <li><label for="password">Password:</label> <input id="password" name="password" type="password" /></li>
                </ol>
                <input id="login" name="login" type="submit" value="Login Now" />
            </fieldset>
        </form>
    </body>
</html>


Here's the PHP (login.php):

CODE
<?php
error_reporting(E_ALL);
if ( @ini_get('register_globals') )
{
    if ( isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS']) )
    {
        exit('<h1>Sorry</h1><p>Not Allowed!!!</p>');
    }
    $protected = array('GLOBALS', '_GET', '_POST', '_COOKIE', '_REQUEST', '_SERVER', '_ENV', '_FILES');
    $input = array_merge($_GET, $_POST, $_COOKIE, $_SERVER, $_ENV, $_FILES, isset($_SESSION) && is_array($_SESSION) ? $_SESSION : array());
    foreach ( $GLOBALS['input'] as $k => $v )
    {
        if (!in_array($k, $GLOBALS['protected']) && isset($GLOBALS[$k]) )
        {
            unset($GLOBALS[$k]);
        }
    }
}
$allow = array('yourdomain.com');
$referer = '';
$created = '';
if ( !empty($_POST['login']) && $_POST['login'] == 'Login Now' )
{
    if ( !empty($_SERVER['HTTP_REFERER']) )
    {
        $GLOBALS['referer'] = current(array_splice(explode('/', $_SERVER['HTTP_REFERER']), 2, 1));
    }
    if ( !in_array($GLOBALS['referer'], $GLOBALS['allow']) )
    {
        exit('<p>Bad Referer</p>');
    }
    unset($_POST['login']);
    foreach ( $_POST as $key => $val )
    {
        if ( empty($GLOBALS[$key]) )
        {
            if ( !empty($key) && !empty($val) )
            {
                $GLOBALS[$key] = $val;
                if ( is_numeric($val) )
                {
                    $GLOBALS['created'] .= '<p>$' . $key . ' = ' . $val . ';</p>'."\n";
                }
                else if ( is_string($val) )
                {
                    $GLOBALS['created'] .= '<p>$' . $key . ' = \'' . $val . '\';</p>'."\n";
                }
            }
        }
    }
    echo $GLOBALS['created'];
}
?>


Now I'm using the GLOBALS variable a lot to just show the scope of the variables, that way you should understand that these variables are in the global scope range and not tied into specific functions.

The only major difference is that I'm emulating register_globals as off, which is the first instruction for this code, because it has to occur first to eliminate the variables being created. It's always a good idea to initialise your own variables rather than rely on them to be already created and initialised.

Now you are probably wondering, what if a variable you want created from your form doesn't get created because it's value was empty, well my method for determining whether a variable is required or not, I would prefix their names with req_ e.g. req_username and then I would create the functions needed to validate these required fields, I have a few validation routines including exact RFC specifications for email addresses as well as my more realistic email address validation routine, however since RFC states what can be valid, it's probably the better choice, my more realistic version is because some of the things they allow, just doesn't seem like what most email providers allow you to have anyways.

There's still more I want to show, including how to make sure a form was not tampered with, but that will probably come after the xmas season, so all the best and merry christmas.

Cheers,

MC
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic

Collapse

> Similar Topics

Topics Topics
  1. How To: Create PDF With Php(18)
  2. Create Your Own Shout Box(13)
  3. How Do I Create A Good Fire Animation Using Flash ?(13)
  4. How Do I Check What Graphics Card I Have?(24)
  5. Help Needed To Create Login Script With Perl/cgi(21)
  6. Finding Yahoo Account Creation Date(1)
  7. Alt Txt Tooltip Popups Over Text Links, How To Do?(11)
  8. PHP Tutorial: Form Verification And Simple Validation(12)
  9. Create A Site Without Cms But Just Dreamweaver?(6)
  10. Help Me Create A Text-based, Turn-based Game(9)
  11. The Cloning Issue(43)
  12. Can You Create A Folder Name "con"(15)
  13. Firefox 2 Has A Spell Check!(40)
  14. How Do I Create Static Routes In Windows Xp?(11)
  15. Very Simple Login-script(18)
  1. A Simple Register Script(3)
  2. Gimp: Working With Text(5)
  3. How To Create Your Own Proxy Site (free And Easy)(13)
  4. Easiest Free Forum To Create Custom Skin For?(2)
  5. Simple Java Question(3)
  6. How Do You Create A Vista?(21)
  7. Engine001 Game Creation Software(2)
  8. Firefox Addon Check(2)
  9. Check Server Headers(3)
  10. Request Form Site Suspended(4)
  11. Create An Animation With Powerpoint(1)
  12. Create An Ftp Server On Your Pc With Serv-u(1)
  13. What You Need Before You Can Create A Text-based Game..(2)


 



- Lo-Fi Version Time is now: 29th August 2008 - 03:30 AM