php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #35307 [PATCH] header can be injected when using mb_send_mail()
Submitted: 2005-11-21 02:13 UTC Modified: 2005-11-24 23:22 UTC
Votes:2
Avg. Score:4.5 ± 0.5
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: s dot masugata at digicom dot dnp dot co dot jp Assigned: hirokawa (profile)
Status: Closed Package: mbstring related
PHP Version: 5CVS, 4CVS (2005-11-21) (snap) OS: Solaris8
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: s dot masugata at digicom dot dnp dot co dot jp
New email:
PHP Version: OS:

 

 [2005-11-21 02:13 UTC] s dot masugata at digicom dot dnp dot co dot jp
Description:
------------
The unexpected header can be injected at the mb_send_mail function.
The mail function is doing the check of the unexpected  control code to "To" and "Subject".
However, the mb_send_mail function isn't doing a check.


By the feature of the function overload, mail function is exchanged for the mb_send_mail function.
Therefore, it thinks that the check like the mail function is necessary about the mb_send_mail function, too.

It is "To" that seems to need a check.
The report is PHP4 but needs the same correction about PHP5.


--- php-4.4.2RC1/ext/mbstring/mbstring.c,orig	2005-11-05 10:14:05.000000000 +0900
+++ php-4.4.2RC1/ext/mbstring/mbstring.c	2005-11-21 09:42:42.000000000 +0900
@@ -3460,6 +3460,22 @@
  *  Sends an email message with MIME scheme
  */
 #if HAVE_SENDMAIL
+#define SKIP_LONG_HEADER_SEP_MBSTRING(str, pos)										\
+	if (str[pos] == '\r' && str[pos + 1] == '\n' && (str[pos + 2] == ' ' || str[pos + 2] == '\t')) {	\
+		pos += 3;											\
+		while (str[pos] == ' ' || str[pos] == '\t') {							\
+			pos++;											\
+		}												\
+		continue;											\
+	}													\
+	else if (str[pos] == '\n' && (str[pos + 1] == ' ' || str[pos + 1] == '\t')) {	\
+		pos += 2;											\
+		while (str[pos] == ' ' || str[pos] == '\t') {							\
+			pos++;											\
+		}												\
+		continue;											\
+	}													\
+
 PHP_FUNCTION(mb_send_mail)
 {
 	int argc, n;
@@ -3475,6 +3491,8 @@
 	mbfl_memory_device device;	/* automatic allocateable buffer for additional header */
 	const mbfl_language *lang;
 	int err = 0;
+	char *to_r;
+	int to_len, i;
 
 	/* initialize */
 	mbfl_memory_device_init(&device, 0, 0);
@@ -3501,6 +3519,29 @@
 	convert_to_string_ex(argv[0]);
 	if (Z_STRVAL_PP(argv[0])) {
 		to = Z_STRVAL_PP(argv[0]);
+		to_len = Z_STRLEN_PP(argv[0]);
+		if (to_len > 0) {
+			to_r = estrndup(to, to_len);
+			for (; to_len; to_len--) {
+				if (!isspace((unsigned char) to_r[to_len - 1])) {
+					break;
+				}
+				to_r[to_len - 1] = '\0';
+			}
+			for (i = 0; to_r[i]; i++) {
+				if (iscntrl((unsigned char) to_r[i])) {
+						/* According to RFC 822, section 3.1.1 long headers may be separated into
+					 * parts using CRLF followed at least one linear-white-space character ('\t' or ' ').
+					 * To prevent these separators from being replaced with a space, we use the
+					 * SKIP_LONG_HEADER_SEP_MBSTRING to skip over them.
+					 */
+					SKIP_LONG_HEADER_SEP_MBSTRING(to_r, i);
+					to_r[i] = ' ';
+				}
+			}
+		} else {
+			to_r = to;
+		}
 	} else {
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing To: field");
 		err = 1;
@@ -3599,12 +3640,15 @@
 		extra_cmd = php_escape_shell_cmd(extra_cmd);
 	} 
 
-	if (!err && php_mail(to, subject, message, headers, extra_cmd TSRMLS_CC)) {
+	if (!err && php_mail(to_r, subject, message, headers, extra_cmd TSRMLS_CC)) {
 		RETVAL_TRUE;
 	} else {
 		RETVAL_FALSE;
 	}
 
+	if (to_r != to) {
+		efree(to_r);
+	}
 	if (extra_cmd) {
 		efree(extra_cmd);
 	}


Reproduce code:
---------------
<?php

  $TO =    "s.masugata@digicom.dnp.co.jp\nBcc: s.masugata@digicom.dnp.co.jp\n".
           "Subject: SPAM Subject\n\nSPAM SPAM SPAM SPAM Body";

  mb_send_mail( $TO, "TEST Subject", "TEST Body" ); // NG!! mail send.
  mail( $TO, "TEST Subject", "TEST Body" ); // OK!! mail not send.

?>


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-11-21 09:10 UTC] sniper@php.net
Assigned to the maintainer.
 [2005-11-24 23:22 UTC] iliaa@php.net
Thank you for your bug report. This issue has already been fixed
in the latest released version of PHP, which you can download at 
http://www.php.net/downloads.php


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 18:01:28 2024 UTC