1

I have a minor problem. When I use this code:

<!DOCTYPE HTML>

<html>
    <head>
        <title>Declare Nerf War!</title>
    </head>
    <body>
        <?php
        $form="<center><form action='decwargen.php' method='POST'>
            Your Name: <input type='text' name='yname' placeholder='John Doe'><br>
            Opponent's Name: <input type='text' name='oname' placeholder='Jane Doe'><br>
            Why? <input type='text' name='why' placeholder='for stealing my stuff'><br>
            Date of war: <input type='text' name='dwar' placeholder='10/11/13'><br>
            Time of war: <input type='text' name='twar' placeholder='10:56 PM'><br>
            Created on: <input type='text name='crtd' placeholder='10/10/13'><br>
            <input type='submit' name='subbut' value='Submit'></center>
        </form>";
        $ok = $_POST ['subbut'];
        if($ok){
            $yname = $_POST ['yname'];
            $oname = $_POST ['oname'];
            $why = $_POST ['why'];
            $dwar = $_POST ['dwar'];
            $twar = $_POST ['twar'];
            $created = $_POST ['crtd'];
            echo("<center><h1>Declaration of war</h1><br><p contenteditable='true'>I, " . $yname . " declare war on " . $oname . " for/because " . $why . ". This will happen on " . $dwar . " at " . $twar . ".<br>Created on" . $created);
        } else echo($form);
        ?>
    </body>
</html>

The web browser says:

Notice: Undefined index: subbut in /Applications/MAMP/htdocs/decwargen.php on line 17

when I first go to the page, then

Notice: Undefined index: crtd in /Applications/MAMP/htdocs/decwargen.php on line 24

when I enter data. Can anyone please help?

Funk Forty Niner
  • 74,450
  • 15
  • 68
  • 141
jelimoore
  • 13
  • 1
  • 5

4 Answers4

3

Change your

 <input type='text name='crtd' placeholder='10/10/13'>
          -------^ quote not closed properly

to

<input type='text' name='crtd' placeholder='10/10/13'>

From your recent question edit, also make the following change:

Replace your

$ok = $_POST ['subbut'];
        if($ok){

to

if(isset($_POST ['subbut']))
        {
That1Guy
  • 7,075
  • 4
  • 47
  • 59
Shankar Narayana Damodaran
  • 68,075
  • 43
  • 96
  • 126
1

As an additional safety tip, DO NOT EVER print something without sanitizing it.

-- edit --

When writing any code that can accept user submitted content, you need to bear in mind that user content can never be trusted. Malicious users can submit specially crafted data that could allow them to gain access to your application, the end user's computer, or much more.

One way to reduce (or control) the threat is to do the following:

  1. Validate the data: Make sure that the type of data matches what you expect for a field (number, text, email, etc).
  2. Sanitize the data: Perform some cleanup to remove undesirable things contained in the data.
  3. Validate the legitimacy of the form (Optional but recommended): If applicable, ensure that the code is being submitted by a form that was truly generated by your web site and use CAPTCHA to prevent automated content submission when possible.
  4. Escape the data: When displaying the data or passing it on to other systems (database, api call, etc.), make sure that you escape the received data so that it does not negatively after those systems.

You can get more information about doing these things and much more using a simple Google search. You can also look at PHP Sanitize filters

Now going back to the actual code that was used in the original question.

I have taken the liberty to print the form below the declaration of war so that you can declare even more wars if you wish.

The code looks like the following ...

<!DOCTYPE HTML>

<html>
    <head>
        <title>Declare Nerf War!</title>
    </head>
    <body>
        <?php
        $form="<center><form action='decwargen.php' method='POST'>
            Your Name: <input type='text' name='yname' placeholder='John Doe'><br>
            Opponent's Name: <input type='text' name='oname' placeholder='Jane Doe'><br>
            Why? <input type='text' name='why' placeholder='for stealing my stuff'><br>
            Date of war: <input type='text' name='dwar' placeholder='10/11/13'><br>
            Time of war: <input type='text' name='twar' placeholder='10:56 PM'><br>
            Created on: <input type='text' name='crtd' placeholder='10/10/13'><br>
            <input type='submit' name='subbut' value='Submit'></center>
        </form>";
        $ok = $_POST['subbut'] ?? false;
        if($ok){
            $yname = $_POST['yname'];
            $oname = $_POST['oname'];
            $why = $_POST['why'];
            $dwar = $_POST['dwar'];
            $twar = $_POST['twar'];
            $created = $_POST['crtd'];
            echo "<center><h1>Declaration of war</h1><br><p contenteditable='true'>I, " . $yname . " declare war on " . $oname . " for/because " . $why . ". This will happen on " . $dwar . " at " . $twar . ".<br>Created on " . $created;
        };
        ?>
        <hr>
        <?php echo $form; ?>
    </body>
</html>

I realize that the question was originally asked in 2013. Still, I am going to solve the Notice: Undefined index: subbut ... using a more modern PHP feature.

I would replace ...

<?php
$ok = $_POST ['subbut'];

with ...

<?php
$ok = $_POST['subbut'] ?? false;

You can find out more about the new PHP Null coalescing operator (the Elvis operator ??) at http://php.net/manual/en/language.operators.comparison.php#example-105

When you submit and declaration of war, you will have something similar to the following image ...

enter image description here

HTML Injection

Now, you are going to see what happens with your form when someone performs a simple HTML injection on your page.

Instead of submitting the name as John Doe, I am going to submit John Doe</form><form action="http://example.com" target="_blank"><input value="You got hacked">

The result is visible on the following image ...

enter image description here

If you try to submit another declaration, you will notice that the form will be submitted to the example.com domain. That's because:

  1. The </form> tag will try to close the current form in case the submitted value was printed inside a form. If there was no form to close off, than the tag will be invalid and the browser will ignore it.
  2. Then, my new form is added using <form action="http://example.com" target="_blank">. Browsers will usually reject a nested form tag. Because of this, my form will take over the next form by invalidating its opening tag.

Someone could argue by saying that the original example was not printing a form. Sure. But that does not change what I am trying to convey.

Instead of creating a form, I could have injected a tag what would load an elaborate Javascript application that would then run on your site's domain and do whatever is possible using Javascript. I could have also added an iframe or other things.

The bottom line is, do not use or directly print anything submitted to your script. Heck, you cannot even trust content coming for your own database because you don't know if it's been altered by someone else. You still need do perform some clean up to guard against XSS and CSRF using the data.

asiby
  • 3,229
  • 29
  • 32
  • 1
    This is a really clear and concise answer that both answers the question and shines light on some very valid security concerns. A really good read and example. – The Humble Rat Dec 22 '18 at 13:06
0

When you first go to the page $_POST['subbut'] Does not exist. It only exists once the form has been posted. In order to avoid this you need to use isset. For example use the following code instead

if(isset($_POST ['subbut'])){
        $yname = $_POST ['yname'];
        $oname = $_POST ['oname'];
        $why = $_POST ['why'];
        $dwar = $_POST ['dwar'];
        $twar = $_POST ['twar'];
        $created = $_POST ['crtd'];
        echo("<center><h1>Declaration of war</h1><br><p contenteditable='true'>I, " . $yname . " declare war on " . $oname . " for/because " . $why . ". This will happen on " . $dwar . " at " . $twar . ".<br>Created on" . $created);
    } else echo($form);

Also change this line

Created on: <input type='text name='crtd' placeholder='10/10/13'><br>

to this

Created on: <input type='text' name='crtd' placeholder='10/10/13'><br>
The Humble Rat
  • 4,586
  • 6
  • 39
  • 73
  • Sanitize your data before printing it out. This is a HUUUUUGE security whole. – asiby Dec 20 '18 at 14:51
  • @asiby Please elaborate. Why not take my example and use it in your answer showing how you would do this differently. I notice you have put an answer but to be honest it is a low quality answer as it acts more as a comment and does not address the initial question. If you take my code which is the answer to the question and imporve on how it should be done in a more secure way then it will have more value and I would be more than happy to upvote it. For anyone else I suggest looking here https://stackoverflow.com/questions/129677/whats-the-best-method-for-sanitizing-user-input-with-php – The Humble Rat Dec 21 '18 at 15:12
  • You are right. My answer doesn't help much. I will edit it and add more information. – asiby Dec 21 '18 at 15:21
0

You have a quote mistake. Try to change

type='text name='crtd'

to

type='text' name='crtd'
Leneron
  • 25
  • 1
  • 6