When implementing Server Side Includes (SSI) on nginx 1.16.1
, extra bytes were being returned in the responses. While this wouldn’t be noticed when viewed in a webpage, it can provide information disclosure when viewing the raw stream. The extra bytes were caused by Transfer-Encoding: Chunked
being used in the HTTP response.
Transfer-Encoding
The Transfer-Encoding
HTTP header is defined by RFC2616 as:
The Transfer-Encoding general-header field indicates what (if any)
type of transformation has been applied to the message body in order
to safely transfer it between the sender and the recipient. This
differs from the content-coding in that the transfer-coding is a
property of the message, not of the entity.
Transfer-Encoding: Chunked
When Transfer-Encoding: Chunked
is in use, each chunked portion of the body must be preceded by it’s length in hexadecimal format followed by a \r\n
. The last line of the body should be 0
indicating transfer is complete.
The following example shows an HTTP response using this technique. The HTTP body begins with 6b
indicating the length of the body followed by the terminating 0
.
6b
<link rel=”stylesheet” href=”/css/normalize.min.css”>
<link rel=”stylesheet” href=”/css/test.min.css”>0
Information Disclosure
The reason this leads to information disclosure is each SSI
section of the webpage is proceeded by it’s size which the following example will illustrate. The message body shows fb
as the size of the first chunck. Then 6b
is used to show the SSI
portion while 401
is the length of the remaining body. This makes it clear that the CSS files are being added via SSI
.
fb
<!doctype html>
…html header content omitted…6b
<link rel=”stylesheet” href=”/css/normalize.min.css”>
<link rel=”stylesheet” href=”/css/test.min.css”>401
…rest of body omitted…
</html>0
Having this information allows someone to understand the logic of the webpage/webapp and potentially target that portion. While not concerning if SSI
is being used to serve static html
files. The issue is using SSI
for dynamic purposes such as requests to a CGI
script or another web application.
Remediation
Fixing this is quite easy, simply add the following to the server
configuration block.
server {
chunked_transfer_encoding off;
}
Test
Testing can be done using the SocketHttpRequest
PowerShell module from my github page: https://github.com/phbits/SocketHttpRequest. Running the following commands will return the raw HTTP response headers and body.
Import-Module SocketHttpRequest.psd1
$httpRequest = @'
GET / HTTP/1.0
Host: www.domain.com'@
$Result = Invoke-SocketHttpRequest -IP 1.1.1.1 -Port 443 -UseTls -HttpRequest $httpRequest -FullResponse
Write-Host "$($Result.response.headers)"
Write-Host "$($Result.response.body)"