It's instructive to take the time and have a look at PHP-Nuke's list of vulnerabilities (see Table 23-1). Even a superficial inspection reveals some common vulnerability patterns:
Cross-site scripting (Section 23.3.1)
SQL injection (Section 23.3.2)
Path disclosure (Section 23.3.3)
Cross-site tracing (Section 23.3.4)
In the following we will examine them in more detail.
Table 23-1. List of PHP-Nuke security vulnerabilities
Description | Date |
21.10.2003 | |
19.07.2003 | |
19.05.2003 | |
02.05.2003 | |
25.04.2003 | |
01.04.2003 | |
26.03.2003 | |
19.03.2003 | |
18.03.2003 | |
07.03.2003 | |
25.02.2003 | |
04.02.2003 | |
23.12.2002 | |
17.12.2002 | |
17.12.2002 | |
25.11.2002 | |
01.11.2002 | |
10.10.2002 | |
Cross Site Scripting holes in Xoops, PHP-Nuke, NPDS, daCode, Drupal and phpWebSite | 24.09.2002 |
A CSS vulnerability is caused by the failure of a site to validate user input before returning it to the client s web-browser. The essence of cross-site scripting is that an intruder causes a legitimate web server to send a page to a victim's browser that contains malicious script or HTML of the intruder's choosing. The malicious script runs with the privileges of a legitimate script originating from the legitimate web server (see Cross-Site Scripting Vulnerabilities). By failing to validate user input, the vulnerable site makes it possible for a malicious user to execute (“inject”) a script in the context of that site's process.
Here are some known examples of cross-site scripting with PHP-Nuke:
When a user posts messages, special characters are not stripped making it possible to inject malicious script code. The user types in a forum message
Some test text for fun <script>alert(document.cookie);</script> some more text.. |
the text is not checked for the presence of a script - and the script is executed in the victim's browser, who thinks it is a safe forum text from a trusted PHP-Nuke site. (see Splatt Forum Cross Site Scripting).
In a search field, the user types
<script>alert(document.cookie);</script> |
The search text is displayed in the results page without being validated. The result: a script is again executed in the victim's browser (see Splatt Forum Cross Site Scripting, PHP-Nuke Cross Site Scripting).
In a forum post, a user types
<html> <body> <script> <!-- Modify here --> var address='http://www.splatt.it/gate.html?mop=modload&name=Forums&file=newtopic'; </script> <!-- Exploit form --> <script> document.write("<form action="+address+" method='post' name='coolsus'>"); </script> Forum Number: <input type=text name=forum value=1 size=3><br> Username: <input CLASS=textbox TYPE="TEXT" NAME="username" SIZE="25" MAXLENGTH="40"><br> Password: <input CLASS=textbox TYPE="PASSWORD" NAME="password" SIZE="25" MAXLENGTH="25"><br> Subject: <input CLASS=textbox TYPE="TEXT" NAME="subject" SIZE="75" MAXLENGTH="75"><br> Message:<br><textarea name="message" rows="10" cols="75" wrap="VIRTUAL"></textarea><br> <input type=hidden name=bbcode value=0> <input type=hidden name=smile value=0> <input type=hidden name=notify value=0> <b>Inject code:</b> <input type=text name=image_subject value='icon1.gif">HTML CODE<!-- "' size=100><br> <input type="submit" name="submit" value=submit class="Button"> </form> </body> </html> |
The input is not checked if it contains malicious code, the script is executed in a user's browser when viewed. Successful exploitation can result in disclosure of various information (eg. cookie-based authentication information) associated with the site running Splatt Forum or inclusion of malicious content, which the user thinks is part of the real website (see Splatt Forum Cross-Site Scripting Vulnerability).
Due to insufficient validation of user input used in an attribute inside a tag, arbitrary script code can be executed by a malicious user. The characters < and > are filtered, but PHP-Nuke neglects to filter out “ characters. A malicious person can exploit this to execute arbitrary script code in a user's browser session by including it in either the profile, comments, or a private message, where one has only to type something like
<a href="http://" onclick="alert('test')">http://" onclick="alert('test')</a> |
to provoke this behaviour (see PHP-Nuke Cross-Site Scripting).
By posting a forum message with a title like:
"><script>evil_code;</script> |
the title will be returned by blocks/block-Forum.php as valid html or script code to the users viewing the message (see PHP-Nuke Cross-Site Scripting).
Input supplied to the $referer variable is not filtered when inserted into the backend database, which makes it possible to include arbitrary script code. When viewed by an administrator, the script code will be executed automatically in the administrator's browser session and could eg. steal the authentication cookie associated with the website, which contains the administrator's username and password (see PHP-Nuke Referer Cross-Site Scripting).
Using the following manipulated addresses
modules/Forums/bb_smilies.php?name=code modules/Forums/bb_smilies.php?Default_Theme=code modules/Forums/bb_smilies.php?site_font=}--></style>code modules/Forums/bb_smilies.php?bgcolor1=">code |
where "code" is a malicious code, a user can execute this code in a viewer's browser (see PHP-Nuke Cross Site Scripting).
As you can see from the above examples, the only remedy to cross-site scripting problems is to write PHP code that validates user input (or, if you are the “viewer”, disable scripting altogether, although even this will not prevent the injection of malicious HTML, see Cross-Site Scripting Vulnerabilities).
Interaction with relational databases takes place through a textual language, the Structured Query Language ('SQL'). The most recent standard is ANSI SQL-92 and forms the basis around which most SQL dialects are based today. See SQL syntax diagrams for a visualization of SQL syntax. Data extraction from the database takes place through a 'query', which is a collection of SQL statements. An SQL query returns the data in a so-called 'result set'.
SQL statements are divided into two general categories: those that can modify the structure (Data Definition Language statements, or 'DDL') and those that can manipulate the contents of databases (Data Manipulation Language statements, or 'DML'). SQL Injection occurs when an attacker is able to insert a series of SQL statements into a 'query' by manipulating data input into an application (see Advanced SQL Injection in SQLServer Applications).
The typical scenario of an SQL Injection goes like this: an SQL statement like (taken from mainfile.php)
SELECT active FROM ".$prefix."_modules WHERE title='$module' |
is used to retrieve the 'active' column from the 'nuke_modules' table (assuming that $prefix is set to 'nuke' in config.php, see Section 3.7), returning in the 'result set' only the row that matches the module $module. An important point to note here is that the string literal '$module' is delimited with single quotes. Presuming that $module is taken from the URL or from user input and was not subjected to further scrutiny, one could use a “module name” of
' UNION ALL SELECT user_password FROM nuke_users WHERE "=' |
and the 'query string' would become:
SELECT active FROM ".$prefix."_modules WHERE title=" UNION ALL SELECT user_password FROM nuke_users WHERE "=" |
The database server would execute the first part
SELECT active FROM ".$prefix."_modules WHERE title=" |
and would find no modules with empty title. It would then combine[1] this empty result set with the outcome of
SELECT user_password FROM nuke_users WHERE "=" |
which selects all passwords (since the WHERE clause is tautologically true, comparing an empty string with itself), returning the “cartesian product” (UNION) of the two - i.e. the set of all passwords. If the outcome of such a query is supposed to be printed somewhere, the user will be able to see sensitive information.
If the “module name” passed on unchecked were
' ; DROP TABLES WHERE "=' |
the consequences would be catastrophic: the database server would execute
SELECT active FROM ".$prefix."_modules WHERE title=" ; DROP TABLES WHERE "=" |
Depending on the actual SQL query, you may have to try some of these possibilities for the WHERE clause:
' or 1=1-- " or 1=1-- or 1=1-- ' or 'a'='a " or "a"="a ') or ('a'='a |
instead of
"=' |
The general rule is that to "break out" of the quotes and manipulate the SQL query, while maintaining valid SQL syntax, your query string must start with a quote and end in a WHERE clause that needs a query appended to it (see SQL Injection).
In PHP-Nuke, SQL injection has been reported in the following vulnerabilities:
The "cid" parameter isn't properly verified in the "Downloads" module. This can be exploited to manipulate the SQL query and may potentially allow bypassing authentication or reveal sensitive information (see PHP-Nuke SQL Injection Vulnerability).
Numeric values in the Web_Links module aren't validated before they are used in SQL queries. Example:
/modules.php?op=modload&name=Web_Links&file=index&l_op=viewlink&cid=2%20malicious_SQL |
(see PHP-Nuke SQL injection). You wonder how malicious_SQL might look like? Here is a real world example from my web server logs:
/modules.php?name=Web_Links&l_op=viewlink&cid=2 %20UNION%20select%20counter,%20pwd,%20aid%20FROM%20nuke_authors%20 |
Several input validation errors, which could be exploited by malicious people to manipula te existing SQL queries by conducting SQL injection attacks against the application, see PHP-Nuke SQL Injection.
Input validation errors in the modules "Members_List" and "Your_Account", which can be exploited by conducting a SQL injection attack, see PHP-Nuke Multiple SQL Injection Vulnerabilities.
Vulnerabilities can be exploited to manipulate existing SQL queries, which can result in disclosure of the Admin user's password hash. This can afterwards be used to gain administrative priviliges for PHP-Nuke, see PHP-Nuke Multiple SQL Injection Vulnerabilities.
Path disclosure is a vulnerability that enables a user to gain knowledge of the internal path structure of an installation. It affects not only PHP-Nuke, but almost all PHP scripts too. A typical path disclosure scenario goes as follows:
A user enters deliberately a value which is passed unchecked to the script. The value is crafted so as to cause an error in the PHP interpreter or the database server. The user's speculation is that the error message will contain valuable information about the paths of the given software installation.
As an example, the error could be something like:
Fatal error: Cannot redeclare theindex() in /mnt/be1/02/738/0004711/w3/htdocs/www.yoursite.net/index.php on line 7 |
Typically, error reporting is set to display the errors on the served page and the user would gain knowledge of the full path of the index.php script on the server. This may or may not worry you, but it is a good idea to keep undisclosed to malicious users. To achieve this, once a script is in production and displayed messages are no longer needed for debugging, they should be disabled.
Path disclosure with PHP-Nuke has been reported in the following cases:
The search module can't handle certain characters such as """, ">" and "'". This causes PHP-Nuke to return an error m essage that discloses the installation path (see PHP-Nuke Path Disclosure Vulnerability).
The PHP script "print.php" used by the modules "News" and "AvantGo" does not verify user input supplied to the "$sid" variable. A malicious person could exploit this to gain knowledge of the full path to the installation directory by sending a HTTP request including invalid input to the "$sid" variable (see PHP-Nuke Path Disclosure).
A new vulnerability has been found in Microsoft's Internet Information Server (IIS) which allows the reading of cookies. This is potentially possible also on Apache. Since PHP-Nuke relies on the cookie mechanism (Section 23.4.5) for user authentication, it is important to know the risks emanating from this type of vulnerability. Here is the way it works, according a CERT advisory (see Microsoft Internet Information Server (IIS) vulnerable to cross-site scripting via HTTP TRACK method):
Microsoft IIS servers support the HTTP TRACK method. The HTTP TRACK method asks a web server to echo the contents of the request back to the client for debugging purposes. The TRACK request is not RFC compliant and not well documented.
The complete request, including HTTP headers, is returned in the entity-body of a TRACK response. This leads to a Cross-site Scripting attack. Using features that provide client-side HTTP protocol support, such as XMLHTTP ActiveX or XMLDOM scripting objects, a web site can cause browsers to issue TRACK requests. The site can read the TRACK response, including sensitive header information such as cookies or authentication data.
Because the TRACK method is similar to the TRACE method, when combined with cross-domain browser vulnerabilities (VU#244729, VU#711843, VU#728563), HTTP TRACK and client-side HTTP support can be leveraged by attackers to read sensitive header information from third-party domains. This technique has been termed "Cross-Site Tracing," or XST, in Cross-Site Tracing (XST), a report published by WhiteHat Security. Cross-site tracing is also described in a CERT advisory about Cross-Site-Tracing.
As noted in the report of WhiteHat, the technique can be used to bypass the HttpOnly cookie attribute introduced in Microsoft Internet Explorer 6.0 SP1. HttpOnly blocks script access to the cookie property (document.cookie), but does not prevent a scripting object from reading the cookie out of an HTTP TRACK response. In the White Paper of WhiteHat Security, this new method of Cross-Site-Scripting is explained in detail. The essence is that this technique
...is able not only to bypass the httpOnly mechanism present in i.e. 6 service pack 1, but in addition the ability to xss just about anything from just about anywhere. This technique allows client-side scripting languages, such as javascript, and possibly other client-side technologies like vbscript, flash, java, etc., the ability access http web authentication credentials, with the added bonus of achieving this result over ssl.
Normally, the cookie is sent back to the domain it belongs. But with this TRACE or TRACK HTTP method, it is possible to request a trace and the web server will send back all data, including the cookie! This is especially important for PHP-Nuke, since it relies on cookies for the authentication of its users.
To protect yourself, you should deactivate the TRACE HTTP method , if you are using Apache, and the TRACK HTTP method, if you are using IIS:
For Apache, you should put the following in the .htaccess file (Section 25.4) of your document root (or, for performance reasons, directly in the configuration file of Apache, if you have access to it):
RewriteEngine On RewriteCond %{REQUEST_METHOD} ^TRACE RewriteRule .* - [F] |
Of course, this assumes that you have mod_rewrite (Section 25.2) installed.
For IIS, you should filter out the TRACE and TRACK methods with the URLScan filter. The only methods allowed should be GET, HEAD and POST.
There is nothing you can do in the code of PHP-Nuke to avoid this vulnerability, however you should bear in mind when we talk about cookies Section 23.4.5 that a Cross-Site Tracing attack may steal the cookies of your PHP-Nuke too. See also Cross-site tracing attack via HTTP TRACK / TRACE method.
[1] | this kind of SQL injection needs a database capable of understanding the UNION clause (for MySQL at least v. 4.x) |