Testing for SSI Injection (OTG-INPVAL-009)

Revision as of 01:47, 23 August 2008 by Marco (Talk | contribs)

Jump to: navigation, search

OWASP Testing Guide v2 Table of Contents

Brief Summary

Web servers usually give developers the ability to add small pieces of dynamic code inside static HTML pages, without having to deal with full-fledged server-side or client-side languages. This feature is incarnated by the Server-Side Includes (SSI). In SSI injection testing, we test if it is possible to inject into the application data that will be interpreted by SSI mechanisms. A successful exploitation of this vulnerability allows an attacker to inject code into HTML pages or even perform remote code execution.

Description of the Issue

Server-Side Includes are directives that the web server parses before serving the page to the user. They represent an alternative to writing CGI programs or embedding code using server-side scripting languages, when there's only need to perform very simple tasks. Common SSI implementations provide commands to include external files, to set and print web server CGI environment variables, and to execute external CGI scripts or system commands.

Putting an SSI directive into a static HTML document is as easy as writing a piece of code like the following:


to print out the current time.


to include the output of a CGI script.


to include the content of a file.


to include the output of a system command.

Then, if the web server's SSI support is enabled, the server will parse these directives. In the default configuration, usually, most web servers don't allow the use of the exec directive to execute system commands.

As in every bad input validation situation, problems arise when the user of a web application is allowed to provide data that makes the application or the web server behave in an unforeseen manner. With regard to SSI injection, the attacker could provide an input that, if inserted by the application (or maybe directly by the server) into a dynamically generated page, would be parsed as one or more SSI directives.

This is a vulnerability very similar to a classical scripting language injection vulnerability. One mitigation is that the web server needs to be configured to allow SSI. On the other hand, SSI injection vulnerabilities are often simpler to exploit, since SSI directives are easy to understand and, at the same time, quite powerful, e.g., they can output the content of files and execute system commands.

Black Box testing

The first thing to do when testing in a Black Box fashion is finding if the web server actually support SSI directives. The answer is almost certainly a yes, as SSI support is quite common. To find out we just need to discover which kind of web server is running on our target, using classical information gathering techniques.

Whether we succeded or not in discovering this piece of information, we could guess if SSI are supported just looking at the content of the target web site we are testing: if it makes use of .shtml file then SSI are probably supported, as this extension is used to identify pages containing these directives. Unfortunately, the use of the shtml extension is not mandatory, so not having found any shtml files doesn't necessarily mean that the target is not prone to SSI injection attacks.

Let's go to the next step, which is needed not only to find out if an SSI injection attack is really plausible, but also to identify the input points we can use to inject our malicious code.

In this step the testing activity is exactly the same needed to test for other code injection vulnerabilities. We need to find every page where the user is allowed to submit some kind of input and verify whether the application is correctly validating the submitted input or, otherwise, if we could provide data that is going to be displayed unmodified (as error message, forum post, etc.). Beside common user supplied data, input vectors that are always to be considered are HTTP request headers and cookies content, that can be easily forged.

Once we have a list of potential injection points, we can check if the input is correctly validated and then find out where in the web site the data we provided are going to be displayed. We need to make sure that we are going to be able to make characters like that used in SSI directives:

< ! # = / . " - > and [a-zA-Z0-9]

go through the application and be parsed by the server at some point.

Exploiting the lack of validation, is as easy as submitting, for example, a string like the following:

<!--#include virtual="/etc/passwd" -->

in a input form, instead of the classical:


The directive would be then parsed by the server next time it needs to serve the given page, thus including the content of the Unix standard password file.

The injection can be performed also in HTTP headers, if the web application is going to use that data to build a dynamically generated page:

GET / HTTP/1.0
Referer: <!--#exec cmd="/bin/ps ax"-->
User-Agent: <!--#virtual include="/proc/version"-->

Gray Box testing and example

Being able to review the application source code we can quite easily find out:

  1. If SSI directives are used; if they are, then the web server is going to have SSI support enabled, making SSI injection at least a potential issue to investigate;
  2. Where user input, cookie content and http headers are handled; the complete input vectors list is then quickly built;
  3. How the input is handled, what kind of filtering is performed, what characters the application is not letting through and how many type of encoding are taken into account.

Performing these steps is mostly a matter of using grep, to find the right keywords inside the source code (SSI directives, CGI environment variables, variables assignment involving user input, filtering functions and so on).




OWASP Testing Guide v2

Here is the OWASP Testing Guide v2 Table of Contents