Closed mparker17 closed 8 years ago
Paging @davidstrauss for some additional perspective.
The changes outside the headers section look ok.
As an alternative to this code, is there any reason at this point pressflow shouldn't have the same minimum PHP version as Drupal 7?
I did the drupal_set_header()
bit differently:
index 58b74a6..62b8939 100644
--- a/includes/bootstrap.inc
+++ b/includes/bootstrap.inc
@@ -797,6 +797,10 @@ function drupal_load($type, $name) {
* Note: When sending a Content-Type header, always include a 'charset' type,
* too. This is necessary to avoid security bugs (e.g. UTF-7 XSS).
*
+ * Note: No special sanitizing needs to be done to headers. However if a header
+ * value contains a line break a PHP warning will be thrown and the header
+ * will not be set.
+ *
* @param $name
* The HTTP header name, or a status code followed by a reason phrase, e.g.
* "404 Not Found".
@@ -812,7 +816,18 @@ function drupal_set_header($name = NULL, $value = NULL, $append = FALSE) {
if (!isset($name)) {
return $headers;
}
-
+
+ // Protect against header injection attacks if PHP is too old to do that.
+ if (version_compare(PHP_VERSION, '5.1.2', '<')) {
+ foreach (array($name, $value) as $part) {
+ if (strpos($part, "\n") !== FALSE || strpos($part, "\r") !== FALSE) {
+ // Use the same warning message that newer versions of PHP use.
+ trigger_error('Header may not contain more than a single header, new line detected', E_USER_WARNING);
+ return;
+ }
+ }
+ }
+
Mine checks earlier, and bails earlier. It also changes less stuff.
Drupal 7:
define('DRUPAL_MINIMUM_PHP', '5.2.4');
@dsnopek Simpler + faster sounds good to me!
(copying from IRC) I skimmed the commit and think it looks good. For the headers you're basically checking for line breaks in any of the input, which seems right. Another way to do it might have been in the same function that actually calls the PHP header() function (doing it there would more closely match what newer versions of PHP themselves do). But either way seems OK to me.
re: PHP Version, let's not change the requirements within the scope of this security work.
@dsnopek yours looks like it might have a bug to me. Where is the $header variable defined?
@DavidRothstein: Eeep! You are right. Too much patching, reverting, and git'ing around. It should be $part not $header.
I've updated the patch in my comment above to remove the bug that @DavidRothstein noticed
@fluxsauce I've pushed another commit to switch to the code in @dsnopek's earlier comment
New code looks good! :-) This is missing the addition to the docblock from the Drupal 6.38 patch (also shown in my earlier comment), but I don't know how important that really is.
@mparker17 docblock might be good to add and also update the 2nd commit message maybe to refer to the SA for context looking at it later?
@dsnopek @pwolanin done!
Can you rebase those 2 commits together (or we can at merge time)?
@pwolanin done!
Applied the change set from this PR locally.
clean install was fine.
not many automated tests, but those pass 158 passes, 0 fails, and 0 exceptions
Thank you to all who collaborated on this!
https://www.drupal.org/SA-CORE-2016-001
Note there were conflicts in
CHANGELOG.txt
andincludes/common.inc
, that were easy to merge, however, one conflict in drupal_set_header() (in modules/system/system.module) was not, and I had to write custom code for it.Essentially drupal_set_header() had been moved from
includes/common.inc
intoincludes/bootstrap.inc
, and the two functions had diverged somewhat since the move. Looking at the Pressflow code, it appeared to be vulnerable to the same attack that was patched in Drupal core 6.38 (HTTP header injection using line breaks on PHP versions earlier than 5.1.2).In Drupal core, the patch was:
Pressflow constructs headers differently though: it constructs a
$headers
array, where it maps$name_lower
(i.e.: the properly-cased HTTP header name) to$value
(i.e.: the value of that header). It then passes the$headers
array todrupal_send_headers()
.So in this patch, I added the check around the code which modifies the
$headers
array:I would very much appreciate some code review and testing. It's been a while since I've worked with Drupal 6 code and Drupal 6 sites!