Friday, February 14, 2014

How is it with URL encoding + XSS

Correct URLs

All URIs need to be encoded using percent encoding as specified in rfc3986.

URLs may consist of:
* reserved characters - when used with their special meaning: !*'();:@&=+$,/?#[]
* unreserved characters - don't need to be encoded: a-z A-Z 0-9 -._~
* any other characters must be encoded using %xx hex escaping sequence using UTF-8 bytes

This means:říliš/žluťoučký;kůň=úpěl?ďábelské=ódy is a nice invalid URL.

Correct is:;k%C5%AF%C5%88=%C3%BAp%C4%9Bl?%C4%8F%C3%A1belsk%C3%A9=%C3%B3dy

Question: Are URLs in my web app broken?
Answer: Unless you always go with ASCII ... probably yes :)
Better answer: It doesn't matter, browsers are smart enough to correctly parse the simple ones

Semantics of URL parts

Important to know ⁉
  • URL = decode(encode(URL))
  • encode(URL) != encode(decode(encode(URL)))
Decoding depends on correct knowledge of the parts being encoded! ⇝ ⇝
=> ENCODING is responsible to transfer the knowledge into correctly constructed URL
=> only then DECODING is able to correctly identify the parts

Exercise from [2]:!$&'()*+,=;:@-._~!$&'()*+,=:@-._~!$&'()*+,==?/?:@-._~!$'()*+,;=/?:@-._~!$'()*+,;==#/?:@-._~!$&'()*+,;=

The important are delimiters - reserved characters.


URLs in HTML = replace & for & But what about URLs and XSS?

Q: Can there be a XSS in URL? 
A: Inside not encoded URL ... YES!
Example URL: http://localhost/'"><img src=x onerror=alert(1)>
⇝ <a href="http://localhost/'"><img src=x onerror=alert(1)>">link</a>

Q: Can there be a XSS in correctly encoded URL?
A: Yes!
Example URL: http://localhost/'+alert(1)+'
Correctly encoded: http://localhost/'+alert(1)+'


Q: Does it matter when I don't encode URLs using percent-encoding syntax?
A: Only when parts contain reserved characters.

=> ENCODE user-supplied parts of the URL + encode("3+2/5") ⇝

Q: Can there be a XSS in URL?
A: Yes.

=> ESCAPE user-supplied URLs based on the surrounding context (see OWASP cheet sheet)!

⇝ <a href="http&#x3a;&#x2f;&#x2f;localhost&#x2f;&#x27;&#x22;&#x3e;&#x3c;img&#x20;src&#x3d;x&#x20;onerror&#x3d;alert&#x28;1&#x29;&#x3e;">link</a>


Where to continue...

(for serious readers, ordered by simplicity)

Tuesday, January 28, 2014

Install MariaDB for Liferay @ Ubuntu



Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.


sudo echo 'binlog_format=row' >> /etc/mysql/conf.d/mariadb.cnf && sudo /etc/init.d/mysql restart

Thursday, December 5, 2013

My XSS Locator / Vector

toString()+alert(/xss/)+function(){/*'+alert(/xss/)+'"+alert(/xss/)+"--></style><img src=x onerror=alert(/xss/)>*/}

URL Encoded:

  • Able to exploit most places (the list is below)
  • Trying not to break JavaScript syntax
  • Easy to identify the vulnerable field (e.g. alert(/userMiddleName/))

Cons - too long for values which have length limit

List of exploitable places:
  • JavaScript/DOM XSS
    • var x="asdf<%= xssLocator %>xxx";
    • var y='asdf<%= xssLocator %>xxx';
    • opener.<%= xssLocator %>(some, arguments);
    • element.html(xssLocatorInput.value);
  • CSS XSS:
    • <style>a:after { content: '<%= xssLocator %>';}</style>
  • HTML Attribute XSS:
    • <a href="#" alt="<%= xssLocator %>">test</a>
    • <a href='#' alt='<%= xssLocator %>'>test</a>
  • HTML Body and Comments XSS
    • <%= xssLocator %>
    • <!-- <%= xssLocator %> -->

Thursday, March 21, 2013

Liferay Theme & SASS cache problems during build

Extending themes using Liferay Plugins SDK is simple.

Extending Classic theme is not - there is css/.sass-cache folder to cross your plans.

How to fix? Change build.xml file in your theme folder and override build-css target:

<?xml version="1.0"?>
<!DOCTYPE project>

<project name="test-theme" basedir="." default="deploy">
  <import file="../build-common-theme.xml" />

  <property name="theme.parent" value="classic" />

  <target name="build-css">
  <delete file="docroot/css/.sass-cache/main.css" />
            target="build-css" />

Tuesday, February 19, 2013

HTTP mod_proxy + Liferay @ same server = security problem

Liferay use remote IP check for Web Services authorization. This check can be bypassed with wrong environment configuration.

The wrong configuration:
1, the web server is on the same machine as the app server (has same localhost / server IP)
2, the web server use HTTP proxy

What happens - HTTP request goes to the web server, which proxies the request to Liferay. Now remote IP = IP of the web server = localhost.

* Anyone can access remote web services
* Anyone can execute public remote methods, other methods require authentication. (Note: Starting with Liferay 6.1.1 / 6.1.20 all methods require authentication.)
* Anyone can execute brute-force attack on users' portal credentials to break the authentication, SSO settings are bypassed

Quick workaround - change:

There is one drawback - you can't access Liferay Web Services from anywhere :)

Solution - move the web server into another machine or use AJP:
* load mod_proxy_ajp
* rewrite configuration to use ajp and port 8009 everywhere (8009 is Tomcat default). Example:
ProxyPass / ajp://localhost:8009/

Applies to Apache HTTP Server, nginx and, in fact, to any HTTP proxy server in this configuration.

Monday, November 19, 2012

How to correctly escape webapp output

1, Escaping must be performed in the last possible place = when writing HTML output

Only when writing a java variable content to the output stream we know if we write the content into a javascript variable, html attribute or as a plain text (html body).

2, Every variable of a String type deserves escaping. Don't escape output only in case you NEED to print HTML.

You may never know how a possibly malicious content got into your variable. It may be persistent
XSS from DB, session attribute, request parameter.

3, Use the right escaping for the right situation. 

See OWASP's XSS_Prevention_Rules_Summary

Side note: Don't mix URL encoding with URL escaping. 

See HTML appendix B.2.1 and B.2.2

URL encoding
Though there can be UTF-8 characters in the URL, URLs should be transmitted in US-ASCII encoding.

Valid URL follows percent encoding of characters, described in Percent encoding of URI characters.

When URL is not encoded, UTF-8 characters are translated into US-ASCII OOTB by browsers. But if you want to be sure (you can't lose here) you can use new In javascript there is a similar function window.encodeURI().

What MUST BE encoded is a URL parameter name and value. It's confusing but to encode the parameter use Javascript has better name: window.encodeURIComponent().

Don't use URL encoding to perform HTML escaping! (Yes, I've seen that :) )

URL escaping
Let's say we already have a valid (correctly encoded) URL which we want to write into HTML.

Then there are 2 important steps:
1, Ampersand character (&), which may be a part of URL, is used to prefix html entity references. When writing a valid HTML we should escape it the same way as any other ampersand you want to write there. Use ampersand entity: &amp;

2, To write safe HTML = to be sure that URL won't escape from HTML attributes or JavaScript variable (it is allowed to contain apostrophe character) it's good to escape the URL as described in  XSS_Prevention_Rules_Summary, not only the query string part.

When we don't have the URL properly encoded we must escape the whole URL - perform the step #2.

Sunday, November 4, 2012

Theme Template For a Specific Portlet

If you want to have your own template for Sign In portlet, you can simply:

  1. Go to your templates directory (theme/docroot/_diffs/templates/)
  2. Copy portlet.vm into portlet.58.vm (58 is a portlet id for Sign In portlet)
  3. Now, Sign In portlet will use portlet.58.vm, other portlets will use default portlet.vm
The same applies for instanceable portlets (e.g. you can have portlet.101_INSTANCE_ABCDE.vm).

You can find the nice piece of logic for loading a portlet template (both VM and FTL) inside com.liferay.taglib.util.ThemeUtil. It's simple:

  • Let's render portlet portlet with Id: 1_WAR_samplejsonportlet_INSTANCE_UgOvIB6Y3Ppb
  1. Portal first tries to find portlet.1_WAR_samplejsonportlet_INSTANCE_UgOvIB6Y3Ppb.vm
  2. Then tries portlet.1_WAR_samplejsonportlet.vm
  3. Finally use portlet.vm