Skip to content

Commit e855b28

Browse files
committed
Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3: Fixes #79265: Improper injection of Host header when using fopen for http requests
2 parents 09e7c86 + d0d6050 commit e855b28

File tree

3 files changed

+104
-28
lines changed

3 files changed

+104
-28
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ PHP NEWS
4444

4545
- Standard:
4646
. Fixed bug #79254 (getenv() w/o arguments not showing changes). (cmb)
47+
. Fixed bug #79265 (Improper injection of Host header when using fopen for
48+
http requests). (Miguel Xavier Penha Neto)
4749

4850
?? ??? ????, PHP 7.4.3
4951

ext/standard/http_fopen_wrapper.c

Lines changed: 63 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -459,41 +459,76 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
459459
strip_header(user_headers, t, "content-type:");
460460
}
461461

462-
if ((s = strstr(t, "user-agent:")) &&
463-
(s == t || *(s-1) == '\r' || *(s-1) == '\n' ||
464-
*(s-1) == '\t' || *(s-1) == ' ')) {
465-
have_header |= HTTP_HEADER_USER_AGENT;
462+
s = t;
463+
while ((s = strstr(s, "user-agent:"))) {
464+
if (s == t || *(s-1) == '\r' || *(s-1) == '\n' ||
465+
*(s-1) == '\t' || *(s-1) == ' ') {
466+
have_header |= HTTP_HEADER_USER_AGENT;
467+
break;
468+
}
469+
s++;
466470
}
467-
if ((s = strstr(t, "host:")) &&
468-
(s == t || *(s-1) == '\r' || *(s-1) == '\n' ||
469-
*(s-1) == '\t' || *(s-1) == ' ')) {
470-
have_header |= HTTP_HEADER_HOST;
471+
472+
s = t;
473+
while ((s = strstr(s, "host:"))) {
474+
if (s == t || *(s-1) == '\r' || *(s-1) == '\n' ||
475+
*(s-1) == '\t' || *(s-1) == ' ') {
476+
have_header |= HTTP_HEADER_HOST;
477+
break;
478+
}
479+
s++;
471480
}
472-
if ((s = strstr(t, "from:")) &&
473-
(s == t || *(s-1) == '\r' || *(s-1) == '\n' ||
474-
*(s-1) == '\t' || *(s-1) == ' ')) {
475-
have_header |= HTTP_HEADER_FROM;
481+
482+
s = t;
483+
while ((s = strstr(s, "from:"))) {
484+
if (s == t || *(s-1) == '\r' || *(s-1) == '\n' ||
485+
*(s-1) == '\t' || *(s-1) == ' ') {
486+
have_header |= HTTP_HEADER_FROM;
487+
break;
476488
}
477-
if ((s = strstr(t, "authorization:")) &&
478-
(s == t || *(s-1) == '\r' || *(s-1) == '\n' ||
479-
*(s-1) == '\t' || *(s-1) == ' ')) {
480-
have_header |= HTTP_HEADER_AUTH;
489+
s++;
481490
}
482-
if ((s = strstr(t, "content-length:")) &&
483-
(s == t || *(s-1) == '\r' || *(s-1) == '\n' ||
484-
*(s-1) == '\t' || *(s-1) == ' ')) {
485-
have_header |= HTTP_HEADER_CONTENT_LENGTH;
491+
492+
s = t;
493+
while ((s = strstr(s, "authorization:"))) {
494+
if (s == t || *(s-1) == '\r' || *(s-1) == '\n' ||
495+
*(s-1) == '\t' || *(s-1) == ' ') {
496+
have_header |= HTTP_HEADER_AUTH;
497+
break;
498+
}
499+
s++;
486500
}
487-
if ((s = strstr(t, "content-type:")) &&
488-
(s == t || *(s-1) == '\r' || *(s-1) == '\n' ||
489-
*(s-1) == '\t' || *(s-1) == ' ')) {
490-
have_header |= HTTP_HEADER_TYPE;
501+
502+
s = t;
503+
while ((s = strstr(s, "content-length:"))) {
504+
if (s == t || *(s-1) == '\r' || *(s-1) == '\n' ||
505+
*(s-1) == '\t' || *(s-1) == ' ') {
506+
have_header |= HTTP_HEADER_CONTENT_LENGTH;
507+
break;
508+
}
509+
s++;
491510
}
492-
if ((s = strstr(t, "connection:")) &&
493-
(s == t || *(s-1) == '\r' || *(s-1) == '\n' ||
494-
*(s-1) == '\t' || *(s-1) == ' ')) {
495-
have_header |= HTTP_HEADER_CONNECTION;
511+
512+
s = t;
513+
while ((s = strstr(s, "content-type:"))) {
514+
if (s == t || *(s-1) == '\r' || *(s-1) == '\n' ||
515+
*(s-1) == '\t' || *(s-1) == ' ') {
516+
have_header |= HTTP_HEADER_TYPE;
517+
break;
518+
}
519+
s++;
496520
}
521+
522+
s = t;
523+
while ((s = strstr(s, "connection:"))) {
524+
if (s == t || *(s-1) == '\r' || *(s-1) == '\n' ||
525+
*(s-1) == '\t' || *(s-1) == ' ') {
526+
have_header |= HTTP_HEADER_CONNECTION;
527+
break;
528+
}
529+
s++;
530+
}
531+
497532
/* remove Proxy-Authorization header */
498533
if (use_proxy && use_ssl && (s = strstr(t, "proxy-authorization:")) &&
499534
(s == t || *(s-1) == '\r' || *(s-1) == '\n' ||

ext/standard/tests/http/bug79265.phpt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
--TEST--
2+
Bug #79265 (Improper injection of Host header when using fopen for http requests)
3+
--INI--
4+
allow_url_fopen=1
5+
--SKIPIF--
6+
<?php require 'server.inc'; http_server_skipif('tcp://127.0.0.1:12342'); ?>
7+
--FILE--
8+
<?php
9+
require 'server.inc';
10+
11+
$responses = array(
12+
"data://text/plain,HTTP/1.0 200 OK\r\n\r\n",
13+
);
14+
15+
$pid = http_server("tcp://127.0.0.1:12342", $responses, $output);
16+
17+
$opts = array(
18+
'http'=>array(
19+
'method'=>"GET",
20+
'header'=>"RandomHeader: localhost:8080\r\n" .
21+
"Cookie: foo=bar\r\n" .
22+
"Host: userspecifiedvalue\r\n"
23+
)
24+
);
25+
$context = stream_context_create($opts);
26+
$fd = fopen('http://127.0.0.1:12342/', 'rb', false, $context);
27+
fseek($output, 0, SEEK_SET);
28+
echo stream_get_contents($output);
29+
fclose($fd);
30+
31+
http_server_kill($pid);
32+
33+
?>
34+
--EXPECT--
35+
GET / HTTP/1.0
36+
Connection: close
37+
RandomHeader: localhost:8080
38+
Cookie: foo=bar
39+
Host: userspecifiedvalue

0 commit comments

Comments
 (0)