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 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

Pull Requests

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 Nov 22 12:01:29 2024 UTC