简体   繁体   中英

How vulnerable is this server side form validation?

I recently wrote this bit of code to validate some forms. As a student developer I might have missed out on security issues.

The script checks required, email, alpha & numeric fields. I have not yet added any sort of captcha which I might add soon enough.

How much damage can a malicious user do with such server side code. (with/without captca)

<?php

    # post data collection
    $name   = "John Doe";
    $email  = "a@b.c";
    $age    = "193";
    $x      = "s";
    $y      = "s";

    # select data that needs validation
    $validate   = array(
        'required'      => array($name, $email, $x, $y),
        'validEmail'    => array($email),
        'validNumber'   => array($age),
        'validAlpha'    => array($name)
    );

    # error messages
    $errorsMsgs = array(
        'required'      => 'Please fill out all required fields.',
        'validEmail'    => 'is an invalid email address.',
        'validNumber'   => 'is an invalid number.',
        'validAlpha'    => 'contains invalid characters. This field only accepts letters and spaces.'
    );

    $errorMarkup    = "<h1>We found a few errors :-(</h1><h2>Please fix these errors and try again</h2><ol>";
    $successMarkup  = "<h1>Success!</h1><h2>Your form was sent successfully.</h2>";
    $backMarkup     = "<a href=\"" . $_SERVER['HTTP_REFERER'] . "\">Back to form</a>";

    # begin state
    $valid = true;

    # loop through fields of error types
    foreach ($validate as $type => $fields) {
        # loop through values of fields to be tested
        foreach ($fields as $value) {
            # throw error if value is required and not entered
            if ($type === 'required' && strlen($value) === 0) {
                $errorMarkup .= "<li>$errorsMsgs[$type]</li>";
                $valid = false;
                break;
            }
            else if (
                        $type === 'validEmail'  && !filter_var($value, FILTER_VALIDATE_EMAIL) ||
                        $type === 'validNumber' && !preg_match('/^[0-9 ]+$/', $value) ||
                        $type === 'validAlpha'  && !preg_match('/^[a-zA-Z ]+$/', $value)
                    ) {
                if (strlen($value) === 0) {break;} # skip check if value is not entered
                $errorMarkup .= "<li>\"$value\" $errorsMsgs[$type]</li>";
                $valid = false;
                continue;
            }
        }
    }

    if ($valid) {
        # email form
        $body = $successMarkup . $backMarkup;
        $title = "Form sent";
    } else {
        $body = $errorMarkup . "</ol>" . $backMarkup;
        $title = "Form errors";
    }

    # write html ouput
    echo "<!DOCTYPE html><head><title>$title</title><style type=\"text/css\">body{margin:100px;font:16px/1.5 sans-serif;color:#111}h1{font-size:32px;margin:0;font-weight:bold}h2{font-size:18px;margin:0 0 20px 0}ol,li{list-style-position:inside;padding-left:0;margin-left:0}</style></head><body>$body</body></html>";
?>

UPDATE: This is a simple email form. It basically validates the data for invalid input and emails it to the website owner. I have added the bit that emails the form below:

if ($valid) {
    $formcontent = "Full Name: $full_name \nEmail Address: $email_address \nLikability: $likability \nCountry: $country \nMessage: $message \nSend me your lousy newsletter: $send_me_your_lousy_newsletter \n";
    $formcontent = wordwrap($formcontent, 70, "\n", true);
    $recipient = "a@b.c"; $subject = "Contact Form"; $mailheader = "From: $email_address \r\n";
    mail($recipient, $subject, $formcontent, $mailheader);

    $body = $successMarkup . $backMarkup;
    $title = "Form sent";
}

1. There are at-least 2 xss vulnerabilities in your application so you need to read up on XSS .

$errorMarkup .= "<li>\"$value\" $errorsMsgs[$type]</li>";

and

 $backMarkup     = "<a href=\"" . $_SERVER['HTTP_REFERER'] . "\">Back to form</a>";

(The attacker can exploit this using a redirect from a URL that contains JavaScript, however browsers should urlencode the referer url which will mitigate this issue.)

You should use this function to sanitize:

htmlspecialchars($var,ENT_QUOTES);

2. Its not clear if this is vulnerable to CRLF injection. If its value is passed though FILTER_VALIDATE_EMAIL then you should be fine:

$mailheader = "From: $email_address \r\n"

3. Also this form is vulnerable to CSRF . And some might say that the attacker doesn't really care. Using CSRF an attacker could create a storm of email, and bomb the inbox of johndoe@gmail.com . If it was vulnerable to CRLF injection I would be more concerned.

Adding a captcha would prevent CSRF and prevent automation as a whole.

Your code is vulnerable to html-injection.

"<li>\"$value\" $errorsMsgs[$type]</li>"

Outputs user data without encoding characters with special meaning in html, in particular <>"' .

Which in turn leads to cross-site-scripting problems.

That happens by outputting $value . So you should encode dangerous characters with htmlspecialchars :

"<li>\"".htmlspecialchars($value)."\" $errorsMsgs[$type]</li>"

(If you use a strange charset you need to specify the charset as parameter to htmlspecialchars . But with common charsets such as UTF-8 and most single byte ANSI charsets this is not required)

I'm assuming for this answer that you are saving the form fields to a MySQL database since you don't specify what happens after form validation. If that's not the case, please update your question appropriately.

I don't see the code that implements email validation. There's potential for SQL injection if you allow certain characters through as part of an email address.

Generally for PHP and MySQL , I would start with mysql_real_escape_string to escape dangerous characters that could otherwise cause unintended behavior (SQL Injection) in the database, no matter what input validation was previously done (what happens if you change the input validation later to allow eg an apostrophe in the name because Amy's Cafe wants to sign up...).

As for Captcha , it has been broken for many years. While it offers some protection against simple bots, serious bots just figure out what to input automatically.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM