1. Attempting Server-Side Includes (SSI) Injection
Systematically
1.1. Problem
The techniques discussed in this article
work well when searching for “reflected SSI” in a small number of URLs.
However, it is difficult to interactively test for “stored SSI” where an
attacker injects a malicious SSI directive or to interactively test for
“reflected SSI” in a large number of URLs.
1.2. Solution
See Example 1.
Example 1. Script to systematically search for SSI injection
#!/bin/bash
CURL=/usr/bin/curl
# Where do we put the responses received from the server?
OUTPUTDIR=/tmp
# A file with URLs to attack, one per line
# For a GET request, line should be http://<host>:<port>/<path>?<parameter>=
# For a POST request, line should be http://<host>:<port>/<path> <parameter>
URLFILE=urls.txt
# If SSI Injection succeeds, a 'grep' for this string will help find it
UNIQUE_SSI_ID=XYZZY_SSI_INJECT_%Y
typeset -i COUNTER
COUNTER=1
while read LINE
do
# Get the URL and PARAMETER for POST Requests
URL=${LINE% *}
PARAMETER=${LINE#* }
OUTFILE="${OUTPUTDIR}/curl${COUNTER}.html"
COUNTER=${COUNTER}+1
# Safely encode the LINE such that we can SSI-Inject it
# This will help us find the URL that is vulnerable
LINE_ENCODED=`echo ${LINE} | perl -MURI::Escape -lne 'print uri_escape($_)'`
# The SSI Injection payload is:
# <!--#config timefmt="${UNIQUE_SSI_ID}(${LINE_ENCODED})" -->
# <!--#echo var="DATE_LOCAL" -->
INJECTION_STRING="%3C!--%23config%20timefmt=%22${UNIQUE_SSI_ID}
(${LINE_ENCODED})%22%20--%3E"
INJECTION_STRING="${INJECTION_STRING}%3C!
--%23echo%20var=%22DATE_LOCAL%22%20--%3E"
if [ "${URL}" != "${LINE}" ]; then
# If the LINE read from the URLFILE contains a space, we will get here.
# According to our URLFILE format, this indicates a POST request.
curl -f -s -o "${OUTFILE}" -F "${PARAMETER}=${INJECTION_STRING}" ${URL}
else
# If the LINE read from the URLFILE does not contain a space, we will get here.
# According to our URLFILE format, this indicates a GET request.
curl -f -s -o "${OUTFILE}" "${URL}${INJECTION_STRING}"
fi
RETCODE=$?
# check to see if curl failed or the server failed
if [ $RETCODE != 0 ]
then
echo "FAIL: (curl ${RETCODE}) ${LINE}"
else
echo "PASS: (curl ${RETCODE}) ${LINE}"
fi
done < ${URLFILE}
|
1.3. Discussion
Example 1 iterates
through all URLs provided to it and submits an SSI injection test input
to each. The script submits either GET or POST requests depending on the
format of the URLs provided to it. The details are discussed in comments
in the script itself.
The first step in systematically searching for SSI issues is
running this script across all pages and parameters. The injected string
indicates the URL used to inject the test input.
The second step is searching through all of the server’s responses
for the string XYZZY_SSI_INJECT_2009
where 2009 is the current year. Any responses that contain that string
will contain something like XYZZY_SSI_INJECT_2009(http://www.example.com/search.shtml?query=).
The information in parentheses identifies the URL and parameter
vulnerable to SSI injection.
The fourth and final step is searching the local copy of the
entire website for the string XYZZY_SSI_INJECT_2009 where 2009 is the
current year. This will help find stored SSI issues, and the injected
string will identify the page and parameter from which the test input
was injected.
Note that searching for XYZZY_SSI_INJECT is insufficient because
that will find all instances where the server sends back the input
provided by the user. For example, if the page is not vulnerable to
SSI injection, the server’s response may contain the following: <!--#config timefmt="XYZZY_SSI_INJECT_%Y
(http://www.example.com/search.shtml?query=)" -->
<!--#echo var="DATE_LOCAL" -->
The year being appended to the string is what indicates that the
injected string was processed as an SSI directive. |
2. Attempting LDAP Injection Interactively2.1. Problem
Many applications use the Lightweight Directory Access Protocol (LDAP) for
managing credentials and authenticating users. If an application does
not carefully handle user input before adding it to LDAP queries, a
malicious user can modify query logic to authenticate herself without
knowing any credentials, get access to sensitive information, and even
add or delete content.
2.2. Solution
To test for LDAP injection, enter the following in input fields
suspected to be used in LDAP queries and watch for unusual responses
from the server. An unusual response may be a random user record, a list
of all users, and so on. If such an unusual response is received, then
the application is vulnerable to LDAP injection.
*
*)(|(cn=*
*)(|(cn=*)
*)(|(cn=*))
normalInput
)(|(cn=* normalInput
)(|(cn=*)normalInput
)(|(cn=*))
To attempt LDAP injection during user authentication, attempt to
enter the strings as the username and/or password where normalInput should be replaced with
something legitimate (a valid username/password). Also, attempt entering
a real username in the system along with one of the strings as the
password, and attempt entering a real password in the system along with
one of the strings as the username.
2.3. Discussion
With LDAP injection, an attacker’s goal involves either
authenticating without credentials or getting access to sensitive
information. This involves guessing what the underlying LDAP query looks
like and then injecting specially crafted input to change its
logic.
Consider some of the test inputs discussed in Section 12.16.2, earlier. The first test input would be
appropriate if the underlying LDAP query is similar to the code shown in
Example 2.
Example 2. Sample LDAP query for searching by username and
password
(&(cn=userName)(password=userPassword))
|
If the application executes the above query and assumes that the
user is authenticated if the query returns at least one record, then the
attacker could authenticate without a username or password if he enters
* as the username and the
password.
Note that an attacker can leverage LDAP injection in many
different ways. For example, consider what could happen when the
application executes the query shown in Example 3 and then checks the password in the
returned record to authenticate a user.
Example3. Sample LDAP query for searching by username only
(&(cn=userName)(type=Users))
|
The application may contain account lockout functionality such that after three consecutive
invalid login attempts, it locks out the user account as a security
measure. Consider what happens when the attacker enters userName)(password=guess as the username and
guess as the password. The LDAP query
becomes (&(cn=userName)(password=guess)(type=Users))
and will return a record if and only if the password for user userName is guess. As far as the application is concerned,
if no record is returned, the username entered by the attacker is
invalid, and so, there is no account to lock out. Once the attacker
guesses the correct password, she is authenticated successfully. Thus,
the attacker effectively subverts the account lockout mechanism and can
brute-force passwords.
Entering
* as the username would return all
records in the LDAP store, and the application detecting that multiple
records were returned would check the password entered by the attacker
against every single one of the returned records and would authenticate
the user if a match occurred in any record! The security of the
application was thus reduced to the attacker’s ability to guess the
weakest password in the system.
In general, when testing for LDAP injection interactively, it is
helpful to monitor the actual queries being generated by the application
to tune the attack to the particular application. There are several ways
in which this can be done. If SSL is not being used to protect
communication between the application and the LDAP server, a network
sniffer can be used to view the application’s queries as well as the
LDAP server’s responses. The application’s logs or LDAP server logs are
also places where the generated queries might be available.
3. Attempting Log Injection Interactively
3.1. Problem
Although log injection does not allow an attacker to gain
unauthorized access to systems, it can be used to forge entries in log
files to make forensics difficult, to hide valid log entries such that
evidence of other attacks is concealed, or even to steal an
administrator’s or operator’s session if the log files are viewed in a
web application.
3.2. Solution
If log files are viewed in xterm using commands such as cat and tail, insert malicious input like
%1B%5B41m%1B%5B37m into input fields that are likely
to get logged (e.g., username on login page).
If log files are viewed in a web application, insert XSS test
inputs like
<script>alert("XSS!");</script> into
input fields that are likely to get logged.
Then, view the log files. If the application is vulnerable to log
injection, in the first case, when viewing the log files in an xterm, the text after the injected test input
will turn white with a red background. In the second case, when the log
file is viewed in a web browser, a dialog box containing the text
XSS! will appear.
The test inputs just shown make it easy to determine whether the
application is vulnerable to log injection in two different scenarios.
Actual malicious test inputs might be as follows:
The first one will clear the entire screen when the log file is
being viewed in an xterm, making the
entries preceding the injected string disappear.
The second one will insert a new line into the logs such that when
viewed in an xterm, a forged entry
that indicates “User admin logged in” such as is shown Example 4.
Example 4. Example of forged log entry
Authentication failed for user: jsmith at 08:01:54.21
Authentication failed for user: mjones at 08:01:55.10
Authentication failed for user:User admin logged in at 08:01:55.93
Authentication failed for user: bbaker at 08:01:56.55
|
The third one will inject arbitrary JavaScript code into the logs,
which will give the attacker full control over what the operator or
administrator sees when viewing the logs.
3.3. Discussion
There are several types of log injection depending on the log
files’ formats and on how log files are viewed by operators and
administrators. In all of the instances discussed, the attacker gains
some control over what is seen by the person viewing the log files. Log
injection is an effective way to hide evidence of an attempted or
successful attack and to execute a stored XSS attack against operators
and administrators.
In the authors’ experience, most web applications are vulnerable
to some form of log injection. Perhaps it is because the problem is not
visible in the application’s front end, and therefore, it is easy to
neglect it both during development and during testing. However, many
applications are required to maintain complete and accurate logs due to
regulatory issues. An attacker having control over the logs violates
many standards and regulations such as the Payment Card Industry Data
Security Standard (PCI-DSS), the Health Insurance Portability and
Accountability Act (HIPAA), and the Sarbanes-Oxley Act (SOX), and could
lead to hefty fines or worse. That impact is in addition to the added
complexity of tracing attackers using unreliable logs.