The CRLF Injection Attack (sometimes also referred to as HTTP Response Splitting) is a fairly simple, yet extremely powerful web attack. It has been reported in detail in "CWE-113 Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP Response Splitting')".
CRLF (Carriage Return "\r"
and Line Feed "\n"
) is a significant sequence of
characters, representing the the End Of Line (EOL) marker for many Internet
protocols, including, but not limited to MIME (e-mail), NNTP (newsgroups), and,
more importantly, HTTP. When programmers write code for web applications, they
split headers based on where the CRLF is found. If a malicious user is able to
inject his own CRLF sequence into an HTTP stream, he is able to maliciously
control the way a web application functions.
For instance, the following attack is possible using Zend\Mail
:
$message = new Zend\Mail\Message();
$message->setSubject(
"test1\r\nContent-Type: text/html; charset = \"iso-8859-1\"\r\n\r\n"
. "<iframe src=\"http://example.com/\"></iframe>"
. "<!--"
);
$message->setBody("This is the real body!");
var_dump($message->toString());
This var_dump()
shows that the string contains a double CRLF sequence. A mail
server will interpret the HTML code as the message body, instead of the correct
one, executing the attack!
The other Zend Framework component affected by CRLF Injection Attack is Zend\Http
.
In Zend Framework 2, we added three new classes:
Zend\Mail\Header\HeaderName
Zend\Mail\Header\HeaderValue
Zend\Http\Header\HeaderValue
Each defines three static methods:
filter($value)
, for filtering a value based on the relevant IETF specification.isValid($value)
, for validating that a value only contains characters defined in the relevant IETF specification.assertValid($value)
, for asserting that a value is valid (raises an exception for invalid values).We updated the header classes in each component to use the isValid()
and
assertValid()
methods to validate data provided to the class and raise an
exception for invalid data. These utilities are used both when deserializing a
header value, as well as when providing data via constructors and setters,
ensuring that the classes can only emit valid data.
Additionally, we updated deserialization methods in classes representing mail messages and HTTP request and response messages to scan for CRLF injection attempts, and they now raise exceptions on detection.
Users may use the isValid()
methods to pro-actively check for invalid values,
and/or the filter()
methods to sanitize data to use for headers. In the latter
case, developers should be aware that filtering is lossy, as it strips any
invalid characters detected.
For Zend Framework 1, we applied a similar solution as for Zend Framework2,
introducing Zend_Mail_Header_HeaderName
, Zend_Mail_Header_HeaderValue
, and
Zend_Http_Header_HeaderValue
, each with the same static methods and approach
as above. The Zend_Mail_Message
, Zend_Mail_Part
, Zend_Http_Client
,
Zend_Http_Request
, Zend_Http_Response
, and Zend_Http_Header_SetCookie
classes were audited to ensure that they assert valid values.
The following specifications were used when developing the solution:
The patch fixing the issues has been applied in the following versions:
This vulnerability has also been disclosed as CVE-2015-3154.
If you are using Zend\Mail
or Zend\Http
from Zend Framework 2 (either
standalone, or within components like Zend\Mvc
), or if you are using the
Zend_Mail
or Zend_Http
components from Zend Framework 1, we recommend
upgrading immediately.
The Zend Framework team thanks the following for identifying the issues and working with us to help protect its users:
Zend\Mail
; andZend\Http
issue, and
who reviewed the patch and proposed improvements; andReleased 2015-05-07
Have you identified a security vulnerability?
Please report it to us at zf-security@zend.com