Skip to content
This repository was archived by the owner on May 16, 2018. It is now read-only.

"Invalid header line detected" error if HTTP header value is empty #587

Merged
merged 1 commit into from
Aug 6, 2015

Conversation

weierophinney
Copy link
Member

In Version 1.12.13 is a bug which is not in Version 1.12.11.

If an HTTP header value is empty I get the Exception "Invalid header line detected" in Zend_Http_Response line 573

This happens because the regex in line 528 does not match if the value is empty.
As far as I know empty values are allowed in HTTP 1.1.

If I change the regex in line 528 from
"|^([\w-]+):\s_(.+)|s"
to
"|^([\w-]+):\s_(.*)|s"
it works fine. So just replacing the + by a *.

It would be nice if this could be fixed in the code, because this breaks existing code.
For me it broke the feed reader, which is fetching and parsing an RSS feed where one HTTP response header value is empty.

@froschdesign
Copy link
Member

This happens because the regex in line 528 does not match if the value is empty.

Are you sure?

This is the old version:

if (preg_match("|^([\w-]+):\s*(.+)|", $line, $m)) {

This is the new version:

if (preg_match("|^([\w-]+):\s*(.+)|s", $line, $m)) {

More informations to the changes in version 1.12.12: ZF2015-04: Potential CRLF injection attacks in mail and HTTP headers

@PHPGangsta
Copy link
Author

Hi Frank,

yes, that's what I'm seeing, I'm sure ;-)

Maybe the difference is that the explode() in the past (<=1.12.11) was done with
$lines = explode("\n", $parts[0]);

So there maybe was a \r left, and that \r was matching the (.+) in the old version.

In the current version it's
$lines = explode("\r\n", $parts[0]);

I just tested it again, 1.12.11 is working fine. If I switch to 1.12.13 it's not working and I get the Exception. If I change the + to * it's working again.

This is an example URL that fails:
http://rss.sueddeutsche.de/rss/Politik

You can try it yourself with this simple stripped down example:
Zend_Http_Response::extractHeaders("Expires:300\r\nImagetoolbar:\r\nPragma:no-cache");

@froschdesign
Copy link
Member

Hallo Michael,

yes, that's what I'm seeing, I'm sure ;-)

😉

This is an example URL that fails:
http://rss.sueddeutsche.de/rss/Politik

Good example!

You can try it yourself…

I trust you.

@froschdesign froschdesign added this to the 1.12.14 milestone Jul 16, 2015
@weierophinney weierophinney modified the milestones: 1.12.15, 1.12.14 Aug 3, 2015
@LaneNelsonHD
Copy link

Don't know if this is the right place to put this, but we just upgraded to 1.12.13 (from 1.12.3), and found that the Regex cited above would not recognize an Http Header "zipi.step: 0".
Our analysis indicates that the regex "|^([\w-]+):\s*(.+)|s" used to match headers does not recognize the dot/period in zipi.step, and the header is rejected. The field name zipi.step appears to comply with RFC7230 (see the definition of a token on p 83), and that there might be additional characters (tchars in the specification, also on p 83) that may be acceptable when used in header field names but which would be rejected by the Regex. As long as you are fixing the blank space problem, perhaps you could expand the acceptable characters to at least include the dot/period?

@akrabat
Copy link
Contributor

akrabat commented Aug 5, 2015

ping @weierophinney for comment.

@weierophinney
Copy link
Member

Indeed, the regex for header names should be:

/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/

to ensure that any valid token is allowed.

Is anybody working on a patch at this point? If so, where?

@akrabat
Copy link
Contributor

akrabat commented Aug 5, 2015

@weierophinney No one is working on this at the moment as the last time it was touched was for a security fix.

weierophinney added a commit to weierophinney/zf1 that referenced this pull request Aug 5, 2015
…lues are retained

- If the header value is empty, the header should still be in the
  returned array.
- If the header name is a valid header token per RFC 7230, do not reject
  it.
…lues are retained

- If the header value is empty or missing, the header should still be in the
  returned array.
- If the header name is a valid header token per RFC 7230, do not reject
  it.

Ensure null headers are also treated
@weierophinney
Copy link
Member

I've converted this issue to a pull request, with an attached patch that:

  • Defines tests for the original reported issue (empty header values were causing the parser to skip the header line)
  • Defines a test for the issue reported by @LaneNelsonHD (valid header names per RFC 7230 were not being matched).
  • Adds code to correct the behavior.

Please review, and let me know if the solutions work for you.

@weierophinney
Copy link
Member

Tests on 5.2 fail currently as they are blocked on #591; however, relevant test results start here:

Tests pass on other required platforms, and the HTTP tests pass on both PHP 7 and HHVM. (Not sure why PHP 7 shows failing status; I do not see any test failures in the run.)

@PHPGangsta
Copy link
Author

Looks good to me, Matthew! Thanks for the fixes!

@akrabat akrabat merged commit d05b9ff into zendframework:master Aug 6, 2015
akrabat added a commit that referenced this pull request Aug 6, 2015
@akrabat
Copy link
Contributor

akrabat commented Aug 6, 2015

Thanks Matthew.

@LaneNelsonHD
Copy link

Looks like it solves our problems as well. Many thanks!

@weierophinney weierophinney deleted the hotfix/587 branch August 10, 2015 16:14
tavy315 added a commit to tavy315/zendframework1 that referenced this pull request Aug 13, 2015
…lues are retained

- If the header value is empty or missing, the header should still be in the
  returned array.
- If the header name is a valid header token per RFC 7230, do not reject
  it.

Ensure null headers are also treated
dsikkema-magento pushed a commit to magento/zf1 that referenced this pull request Sep 30, 2015
Zend Framework 1.12.15

- [582: Incorrect application of timeout option in curl http client adapter](zendframework#582)
- [587: &quot;Invalid header line detected&quot; error if HTTP header value is empty](zendframework#587)
- [591: ZF2015-06 fix broke the ZF on PHP 5.2](zendframework#591)
- [593: fix typo in PHPDoc @throws annotation of Zend&zendframework#95;Registry::get()](zendframework#593)
- [595: Removing annoying warning.](zendframework#595)
- [597: Fix setting of CURLOPT&zendframework#95;TIMEOUT](zendframework#597)

Conflicts:
	README.md
	library/Zend/Db/Select.php
	library/Zend/Service/DeveloperGarden/BaseUserService.php
	library/Zend/Service/DeveloperGarden/Client/ClientAbstract.php
	library/Zend/Service/DeveloperGarden/Client/Exception.php
	library/Zend/Service/DeveloperGarden/Client/Soap.php
	library/Zend/Service/DeveloperGarden/ConferenceCall.php
	library/Zend/Service/DeveloperGarden/ConferenceCall/ConferenceSchedule.php
	library/Zend/Service/DeveloperGarden/ConferenceCall/Exception.php
	library/Zend/Service/DeveloperGarden/ConferenceCall/Participant.php
	library/Zend/Service/DeveloperGarden/ConferenceCall/ParticipantDetail.php
	library/Zend/Service/DeveloperGarden/ConferenceCall/ParticipantStatus.php
	library/Zend/Service/DeveloperGarden/Credential.php
	library/Zend/Service/DeveloperGarden/Exception.php
	library/Zend/Service/DeveloperGarden/IpLocation.php
	library/Zend/Service/DeveloperGarden/IpLocation/IpAddress.php
	library/Zend/Service/DeveloperGarden/LocalSearch.php
	library/Zend/Service/DeveloperGarden/LocalSearch/Exception.php
	library/Zend/Service/DeveloperGarden/LocalSearch/SearchParameters.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/AddConferenceTemplateParticipantRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/CommitConferenceRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/CreateConferenceRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/CreateConferenceTemplateRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/GetConferenceListRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/GetConferenceStatusRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/GetConferenceTemplateListRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/GetConferenceTemplateParticipantRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/GetConferenceTemplateRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/GetParticipantStatusRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/GetRunningConferenceRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/NewParticipantRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/RemoveConferenceRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/RemoveConferenceTemplateParticipantRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/RemoveConferenceTemplateRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/RemoveParticipantRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/UpdateConferenceRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/UpdateConferenceTemplateParticipantRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/UpdateConferenceTemplateRequest.php
	library/Zend/Service/DeveloperGarden/Request/ConferenceCall/UpdateParticipantRequest.php
	library/Zend/Service/DeveloperGarden/Request/Exception.php
	library/Zend/Service/DeveloperGarden/Request/IpLocation/LocateIPRequest.php
	library/Zend/Service/DeveloperGarden/Request/LocalSearch/LocalSearchRequest.php
	library/Zend/Service/DeveloperGarden/Request/SendSms/SendFlashSMS.php
	library/Zend/Service/DeveloperGarden/Request/SendSms/SendSMS.php
	library/Zend/Service/DeveloperGarden/Request/SendSms/SendSmsAbstract.php
	library/Zend/Service/DeveloperGarden/Request/SmsValidation/GetValidatedNumbers.php
	library/Zend/Service/DeveloperGarden/Request/SmsValidation/Invalidate.php
	library/Zend/Service/DeveloperGarden/Request/SmsValidation/SendValidationKeyword.php
	library/Zend/Service/DeveloperGarden/Request/SmsValidation/Validate.php
	library/Zend/Service/DeveloperGarden/Request/VoiceButler/CallStatus.php
	library/Zend/Service/DeveloperGarden/Request/VoiceButler/NewCall.php
	library/Zend/Service/DeveloperGarden/Request/VoiceButler/NewCallSequenced.php
	library/Zend/Service/DeveloperGarden/Request/VoiceButler/TearDownCall.php
	library/Zend/Service/DeveloperGarden/Request/VoiceButler/VoiceButlerAbstract.php
	library/Zend/Service/DeveloperGarden/Response/BaseType.php
	library/Zend/Service/DeveloperGarden/Response/BaseUserService/ChangeQuotaPoolResponse.php
	library/Zend/Service/DeveloperGarden/Response/BaseUserService/GetAccountBalanceResponse.php
	library/Zend/Service/DeveloperGarden/Response/BaseUserService/GetQuotaInformationResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/AddConferenceTemplateParticipantResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/AddConferenceTemplateParticipantResponseType.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/CCSResponseType.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/CommitConferenceResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/ConferenceCallAbstract.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/CreateConferenceResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/CreateConferenceResponseType.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/CreateConferenceTemplateResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/CreateConferenceTemplateResponseType.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/GetConferenceListResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/GetConferenceListResponseType.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/GetConferenceStatusResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/GetConferenceStatusResponseType.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/GetConferenceTemplateListResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/GetConferenceTemplateListResponseType.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/GetConferenceTemplateParticipantResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/GetConferenceTemplateParticipantResponseType.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/GetConferenceTemplateResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/GetConferenceTemplateResponseType.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/GetParticipantStatusResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/GetParticipantStatusResponseType.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/GetRunningConferenceResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/GetRunningConferenceResponseType.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/NewParticipantResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/NewParticipantResponseType.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/RemoveConferenceResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/RemoveConferenceTemplateParticipantResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/RemoveConferenceTemplateResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/RemoveParticipantResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/UpdateConferenceResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/UpdateConferenceTemplateParticipantResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/UpdateConferenceTemplateResponse.php
	library/Zend/Service/DeveloperGarden/Response/ConferenceCall/UpdateParticipantResponse.php
	library/Zend/Service/DeveloperGarden/Response/Exception.php
	library/Zend/Service/DeveloperGarden/Response/IpLocation/CityType.php
	library/Zend/Service/DeveloperGarden/Response/IpLocation/GeoCoordinatesType.php
	library/Zend/Service/DeveloperGarden/Response/IpLocation/IPAddressLocationType.php
	library/Zend/Service/DeveloperGarden/Response/IpLocation/LocateIPResponse.php
	library/Zend/Service/DeveloperGarden/Response/IpLocation/LocateIPResponseType.php
	library/Zend/Service/DeveloperGarden/Response/IpLocation/RegionType.php
	library/Zend/Service/DeveloperGarden/Response/LocalSearch/LocalSearchResponse.php
	library/Zend/Service/DeveloperGarden/Response/LocalSearch/LocalSearchResponseType.php
	library/Zend/Service/DeveloperGarden/Response/ResponseAbstract.php
	library/Zend/Service/DeveloperGarden/Response/SecurityTokenServer/Exception.php
	library/Zend/Service/DeveloperGarden/Response/SecurityTokenServer/GetTokensResponse.php
	library/Zend/Service/DeveloperGarden/Response/SecurityTokenServer/SecurityTokenResponse.php
	library/Zend/Service/DeveloperGarden/Response/SendSms/SendFlashSMSResponse.php
	library/Zend/Service/DeveloperGarden/Response/SendSms/SendSMSResponse.php
	library/Zend/Service/DeveloperGarden/Response/SendSms/SendSmsAbstract.php
	library/Zend/Service/DeveloperGarden/Response/SmsValidation/GetValidatedNumbersResponse.php
	library/Zend/Service/DeveloperGarden/Response/SmsValidation/InvalidateResponse.php
	library/Zend/Service/DeveloperGarden/Response/SmsValidation/SendValidationKeywordResponse.php
	library/Zend/Service/DeveloperGarden/Response/SmsValidation/ValidateResponse.php
	library/Zend/Service/DeveloperGarden/Response/VoiceButler/CallStatus2Response.php
	library/Zend/Service/DeveloperGarden/Response/VoiceButler/CallStatusResponse.php
	library/Zend/Service/DeveloperGarden/Response/VoiceButler/NewCallResponse.php
	library/Zend/Service/DeveloperGarden/Response/VoiceButler/NewCallSequencedResponse.php
	library/Zend/Service/DeveloperGarden/Response/VoiceButler/TearDownCallResponse.php
	library/Zend/Service/DeveloperGarden/Response/VoiceButler/VoiceButlerAbstract.php
	library/Zend/Service/DeveloperGarden/SecurityTokenServer.php
	library/Zend/Service/DeveloperGarden/SecurityTokenServer/Cache.php
	library/Zend/Service/DeveloperGarden/SendSms.php
	library/Zend/Service/DeveloperGarden/SmsValidation.php
	library/Zend/Service/DeveloperGarden/VoiceCall.php
	library/Zend/Service/Technorati.php
	library/Zend/Service/Technorati/Author.php
	library/Zend/Service/Technorati/BlogInfoResult.php
	library/Zend/Service/Technorati/CosmosResult.php
	library/Zend/Service/Technorati/CosmosResultSet.php
	library/Zend/Service/Technorati/DailyCountsResult.php
	library/Zend/Service/Technorati/DailyCountsResultSet.php
	library/Zend/Service/Technorati/GetInfoResult.php
	library/Zend/Service/Technorati/Result.php
	library/Zend/Service/Technorati/ResultSet.php
	library/Zend/Service/Technorati/SearchResult.php
	library/Zend/Service/Technorati/SearchResultSet.php
	library/Zend/Service/Technorati/TagResult.php
	library/Zend/Service/Technorati/TagResultSet.php
	library/Zend/Service/Technorati/TagsResult.php
	library/Zend/Service/Technorati/TagsResultSet.php
	library/Zend/Service/Technorati/Utils.php
	library/Zend/Service/Technorati/Weblog.php
	library/Zend/Xml/Security.php
	tests/Zend/Xml/TestAsset/Security.php
dgiotas pushed a commit to tripsta/zf1 that referenced this pull request Jun 17, 2016
…lues are retained

- If the header value is empty or missing, the header should still be in the
  returned array.
- If the header name is a valid header token per RFC 7230, do not reject
  it.

Ensure null headers are also treated
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants