Skip to content

Add blacklisted command line flags for sendline via mail() #12783

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

TCGeek
Copy link

@TCGeek TCGeek commented Nov 25, 2023

As discussed, here are the changes I recommend to disable command line flags being passed into the $additional_params for mail().

  • Edited both dev and prod php.ini files.
  • Added function to remove blacklisted commands from user input in mail.c
  • Added additional if statement to verify that allow_additional_sendmail_flags is off to enforce blacklist in mail.c
  • Declared new php_mail_disable_flags function in php_mail.h
  • Added global INI value for mail.allow_additional_sendmail_flags in main.c
  • Defined allow_additional_sendmail_flags as boolean in php_globals.c
  • Added allow test case in mail_blacklist_allowed.phpt
  • Added disallow test case in mail_blacklist_disallowed.phpt

Tested on local instance, everything functions as intended.

@SakiTakamachi
Copy link
Member

This may require RFC.

Copy link
Member

@Girgias Girgias left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few things, indentation for C files are tabs, not spaces.

There hasn't been any discussion that I can see of, neither in #12781 nor on the PHP internals mailing list. So this should probably be brought up to the list, even if it may not require an RFC.

Remove all dangerous command line flags
from the sendmail shell command
*/
PHPAPI zend_string *php_mail_disable_flags(const char *str)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please pass in the str_length as an argument, we know the size and this prevents a useless computation.

Also, this will just truncate the command if it contains a null byte.

const char* blacklist[4] = {"-O", "-C", "-X", "-be"};
size_t str_length = strlen(str);
char *return_str = emalloc(str_length + 1);
strcpy(return_str, str);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use memcpy.

char *return_str = emalloc(str_length + 1);
strcpy(return_str, str);
for (int i = 0; i < 4; ++i) {
size_t blacklist_length = strlen(blacklist[i]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm really not a fan of this, those strings are constant and computing the lengths at runtime really feels off

{
const char* blacklist[4] = {"-O", "-C", "-X", "-be"};
size_t str_length = strlen(str);
char *return_str = emalloc(str_length + 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this allocation really needed?

You can just allocate the zend_string directly, and iterate on the underlying char pointer.

Remove all dangerous command line flags
from the sendmail shell command
*/
PHPAPI zend_string *php_mail_disable_flags(const char *str)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, why is this exposed as a PHPAPI? can't it be static

Copy link
Member

@bukka bukka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this requires at least some discussion on internals and potentially RFC if there is no clear agreement on the new options.

*/
PHPAPI zend_string *php_mail_disable_flags(const char *str)
{
const char* blacklist[4] = {"-O", "-C", "-X", "-be"};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be better to make this configurable as a list of potentially insecure flags changeable using INI. You could keep those as default.

@@ -749,6 +749,7 @@ PHP_INI_BEGIN()
PHP_INI_ENTRY("smtp_port", "25", PHP_INI_ALL, NULL)
STD_PHP_INI_BOOLEAN("mail.add_x_header", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, mail_x_header, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("mail.mixed_lf_and_crlf", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, mail_mixed_lf_and_crlf, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("mail.allow_additional_sendmail_flags", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, allow_additional_sendmail_flags, php_core_globals, core_globals)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to have a mode for this which would either allow, deny or ignore the list of insecure flags. The default should be deny so users get warning if such flag is present. That's better than just silently ignore things IMHO.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could potentially consider warn mode that would would ignore it but also produce warning so users can catch those changes. That could be potentially default.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
4 participants