Advisories regarding Leed and Secure Entry Server (SES)

Today I’m happy to release the following security advisories:

I would take the opportunity to thanks Valentin CARRUESCO aka Idleman for the timely patches he implemented within Leed.

Of further interest is the vulnerability which affected the SES as it was due to a common mistake made when validating URLs. Let’s illustrate the issue with another occurrence of the same flaw, which affected LinkedIn and was reported back in November 2012.

Back then, attempts to visit a page reserved to LinkedIn members only triggered a redirect to the following login page:[original_page]

Variable session_redirect was used to keep track of the initially desired page. Once successfully logged in, the web application would redirect us straight to this page using the following AJAX response:


Attempts to misuse this mechanism and inject a full URL in parameter session_redirect (e.g. would fail, presumably because the developers ensured that the first character of value session_redirect had to be a slash (or its URL-encoded hex value %2F).

But what about partial URL // Based on the aforementioned logic, such an URL would be considered as safe by the code, as it starts with a slash. But modern browsers don’t interpret a redirection to // as being http(s)://[victim]//, but in fact as a redirection to http(s):// This behaviour is RFC conform and commonly used over the Internet to embed resources regardless of the URL scheme (http if the initial page was called over http, https if called over https).

Was it possible to abuse LinkedIn and the SES with such a trick? Yes, here’s an illustration of it:

Attempt to login on LinkedIn using forged URL (note the double slash – %2F%2F)

2013-12-04 12_52_00-Clipboard

Pressing button “Sign In” would submit the entered credentials. An extract of the AJAX response is shown below:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
[removed various Set-Cookies directives]
X-LI-UUID: B[base64_stuff]nsg==
[removed various Set-Cookies directives]
Pragma: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Cache-Control: no-cache
Cache-Control: no-store
Vary: Accept-Encoding
Content-Type: application/json;charset=UTF-8
Content-Language: en-US
Date: Sat, 10 Nov 2012 11:45:45 GMT
Age: 1
Connection: keep-alive
Content-Length: 52


The browser would then interpret this redirection as being meant for [scheme]://test/phishing.html and perform the according request as seen below:

GET /phishing.html HTTP/1.1
Host: test
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:16.0) Gecko/20100101 Firefox/16.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive

2013-12-17 11_58_10-Clipboard

The issue was reported to LinkedIn in November 2012 and fixed without further acknowledgement.

As a conclusion, do not assume that a partial URL value starting with a slash will always represent a path on your website. It may as well be a valid URL representation pointing to another domain. Furthermore, always perform redirections using a full qualified domain name and don’t just rely on a partial URL representation.

ASFWS slides and OWASP meeting tomorrow

As announced a while ago, I had the chance to organize both a workshop about our and present my talk “Advances in secure (ASP).NET development – break the hackers’ spirit” at the AppSec Forum Western Switzerland in Yverdon-les-Bains last week. I hope to soon summarize the conferences I attended in an upcoming blog article.

In the meantime, the Swiss French television RTS was part of the workshop and did a reportage aired during the 12:45 Téléjournal:


As the slides are not yet published by the conference, you can already download them from this blog:

For those interested in seeing my talk live, join us tomorrow evening at 18:00 for the OWASP Zürich meeting. Registration is required and further details are available on

Compass Security at ASFWS in Yverdon-les-Bains


Compass Security is proud to be part and sponsor of the Application Security Forum – Western Switzerland (ASFWS), a conference about application, identity and cyber security which will be take place in a week’s time in Yverdon-les-Bains (15-16 October 2013).

I will run the AppSec Lab 1 (featuring the Hacking-Lab), on Wednesday 16 October in the morning. The Lab will feature various different in-depth lab cases, with the primary focus on OWASP top 10. Everybody can join in and hack, either to learn, or to compete against other participants.

In the afternoon, I will also give a talk with the title “Advances in secure (ASP).NET development – break the hackers’ spirit”. The presentation includes a discussion of security features in the cutting edge (ASP).NET 4.5, and key security points of the application lifecycle.

As sponsor, Compass Security is happy to offer 3 tickets for the conferences held Wednesday 16 October from 13:30 on. To participate, be the quickest to send me a short email in French (as the conferences being mainly held in this language) at: alexandre [dot] herzog [at] csnc [dot] ch. Winners will be notified individually via email. Good luck!

I’m looking forward meeting you at this occasion, either during the “Soirée Château” network event, the workshop or the conferences!

Bypass File Download Restrictions in Content Filters

Companies battle with users who download files from the Internet at work and then execute them. Unsuspicious files are often infected with malware. A common procedure to decrease the amount of infections is to block common bad file types (for example .exe, .scr or .zip), before the files can enter the internal network. The preconditions are that users are only able to communicate with the Internet through a HTTP proxy and the internal email server. A whitelist on the email- and web-content filter, which only allows .docx to go through, can greatly decrease the amount of malware infections. Attackers will have to use exploits (e.g. in the browser, a plugin or office exploits) to perform code execution on the clients.

Sadly, in the case of web content filters, they can all be circumvented. They usually work by looking for HTTP responses whose content types are not safe, for example “application/octet-stream”. Here an example of a typical file download:


With HTML5, it is possible to create the file to download on-the-fly with JavaScript (by storing the binary as base64 encoded string). As no download request is generated when the download link is clicked, the content-filter can’t deny the download request. It is also possible to misuse Flash for the same purpose.


cf-1The initial request to retrive the page goes to a plain html file:


The response is plain HTML (content type text/html) with javascript:


The JavaScript code will extract the base64 encoded binary as a blob and provide a normal download dialog for the user.

There is no simple solution for this problem. Content filters may be able to catch certain pages which use this functionality, but this would break other pages like Google Docs.
The issue was identified at a discussion at the Compass Offsite Meeting 2013 in Berlin. The Proof-of-Concept code (as seen above) has been implemented first by Cyrill Bannwart and works for current versions of Chrome, Firefox and IE10.

Microsoft Security Bulletin MS13-067 – Critical

As part of today’s monthly patch day, Microsoft fixed an issue I reported in September 2012 around (ASP).NET and SharePoint.

The vulnerability opens a new type of attack surface on ASP.NET if a given precondition regarding the Viewstate field is met. The impact is at least a breach of data integrity on the server side resulting typically in a denial of service. Leveraging the flaw to achieve remote code execution cannot be excluded though. The default configuration settings of ASP.NET are safe and do not allow an exploitation of the flaw.

But before uncovering more technical details about the issue, we want to ensure everyone had enough time to patch their servers adequately. For this reason, we will withhold further details during a grace period agreed with Microsoft’s Security Response Center to ensure all involved parties have enough time to react. In the meantime, we encourage you to patch the relevant servers and ensure your web applications at least enforce the default protection of the Viewstate field.

XSS – The never ending story

Cross-Site Scripting (XSS) has lost one rank in the newly released OWASP Top Ten 2013 candidate. Compared to the 2010 version, it’s now on rank three, overtaken by “Broken Authentication and Session Management”. Has XSS become less common then? No, I don’t think so.

Compass Security has always been strong in web application security testing and not surprisingly, has a huge experience in identifying all kinds of web app related weaknesses, including Cross-Site Scripting. To wrap up quickly, here’s OWASP’s pretty decent definition:

“XSS flaws occur whenever an application takes untrusted data and sends it to a web browser without proper validation or escaping. XSS allows attackers to execute scripts in the victim’s browser which can hijack user sessions, deface web sites, or redirect the user to malicious sites.”

Just in the last two months, I’ve been releasing three advisories, all related to XSS:

So why is XSS still so wide-spread? Here’s my personal top three:

  1. Developers tend to care more about features than security. This might be driven by marketing or sales, time constraints or other well-founded reasons – but at the end, it doesn’t matter. Sloppy coding, not being well trained and cheap outsourcing complete this picture.
  2. People suffer from the NIH syndrome (Not-Invented-Here). Instead of building their product on a well-tested code base, e.g. some common framework, they re-invent software in an insecure matter, also due to point 1.
  3. People underestimate the effort of maintaining software, which is always dynamic per se. This often leads to unpatched Content-Management-Systems being used in the wild: set up once, forgotten forever.

So, what’s the solution?

Software development should always be embedded in a Secure Development Lifecycle, in order to ensure its quality in development, improvements and operation. Besides, professional software companies and communities need to treat security incidents seriously. A positive example of the three above has been the Drupal community, which has shown it’s a professional approach from day one I contacted them.

Cross-Site Scripting is so easy to fix but so powerful to exploit. However, XSS is either not treated as a concrete threat or its impact is underestimated. We can just hope that someday all web developers understand its impacts and care more about their software – and customers.

Meanwhile, we’ll stay calm and continue testing …

Why does Compass Security recommend HSTS?

Secure web communications using HTTPS isn’t anything fancy anymore these days. It ensures traffic from a user to your web application cannot be eavesdropped or tampered with, given it has been set up securely using SSL/TLS. But, do you trust your web application’s code to entirely disregard unencrypted requests? Are you sure your Apache/IIS is configured properly to redirect http to https all the time? How can you be sure your users, which never bother typing in explicitly the https:// part of your URL, won’t be affected by the SSLstrip attack?

Well, sometimes you may be pretty confident about your server configuration – but there are certainly occasions where you simply can’t. So, wouldn’t it be great if the user’s browser could be told to refuse unencrypted channels for a domain at all? And even remember that decision for a defined time span?
This is where HSTS comes into play. That acronym stands for “HTTP Strict Transport Security” and defines a fairly new HTTP response header that forces a user agent to solely interact with the server using HTTPS. It has been officially approved by IESG on 2nd October 2012 and is specified in RFC 6797. Let’s have a look at it:

Strict-Transport-Security: max-age=2628000

That response header causes a modern browser with HSTS support to never ever interact with the server in an unencrypted way for one month. So, in case your web application accidentally issues a non-https redirect (or anything else happens that would cause a non-https connection – e.g. a JavaScript or CSS resource loaded over http from the same domain), the user’s browser would simply use https instead. This web security policy mechanism can be enhanced by specifying the optional subdomains flag. That way, and not very surprisingly, all accordant sub domains are also put into the HSTS scope:

Strict-Transport-Security: max-age=2628000; includeSubDomains

Setting the max-age value to a month is the default recommendation, but this parameter should take the common usage pattern of your website into account. If your users connect themselves only once a month, you might want to extend the max-age period to avoid having the HSTS value expire.

Downsides? Sure.

The very initial request to a HSTS web site may still be http and thus exposed to a standard Man-In-The-Middle attack (Bootstrap MITM). In that phase, an attacker could tamper with the HSTS response header and inject invalid subdomains (DoS), disable HSTS (set max-age to 0) or poison the HSTS cache of the user agent otherwise. However, wrongly stored HSTS policies can be simply removed by clearing the local browser cache.

Another downside is rather an organizational one: once you have pushed an HSTS policy to your clients, you are no longer as free to switch back to non-https connections, of course. Their browser is configured to ignore http for the time span you have defined. Simple fix: Push a temporary policy with ‘max-age=0′ to disable it again. Also, the process of keeping your certificates valid must be properly implemented. With HSTS, there is zero tolerance for problems with respect to SSL certificates as the user is no longer able to bypass SSL warnings and “click through”.

Use it? Yes!

The advantages of HSTS clearly outweigh its downsides. It even defeats some issues it wasn’t planned for: HSTS helps in fixing mixed-content issues, defends against the cookie value being sent in plain text (in case you don’t set its ‘secure’ flag), and it may even reduce network latency by saving superfluous http-to-https redirects. Unfortunately, not all browsers support it yet, most prominently Internet Explorer. However, given HSTS was just officially approved, Microsoft will probably need to introduce it soon.


Risks of DOM Based XSS due to “unsafe” JavaScript functions


Several native JavaScript functions or properties like .eval() and .innerHTML as well as several jQuery functions like .html() and .append() are considered as “unsafe”, but why? The reason is that they allow DOM manipulation using strings containing HTML code (e.g.”<b>This text is bold</b>“), which can lead to DOM Based Cross-Site Scripting vulnerabilities. To be more specific: The usage of such functions is not a problem as long as no user input is directly embedded in an “unsafe” way. jQuery can help us to safely manipulate the DOM without executing XSS in user defined inputs. But do not by mistake assume jQuery is safe per se, it only provides us some helper function to manipulate the DOM more safely.

The subsequent sections show the difference between safe and unsafe usage of JavaScript and jQuery functions in the following scenarios:

Unsafe DOM manipulation using eval():

var txtField = "field1";
var txtUserInput = "'';alert(1);";
   "document.forms[0]." + txtField + ".value =" + txtUserInput

The last double quote causes the user input to be treated as JavaScript. This results in the following JavaScript code being executed by eval():

document.forms[0].field1.value = '';alert(1);

Therefore the user input is executed:

Safe DOM manipulation using eval():

var txtField = "field1";
var txtUserInput = "'';alert(1);";
   "document.forms[0]." + txtField + ".value = txtUserInput"

The double quote at the end causes the user input NOT to be treated as JavaScript. This results in the following JavaScript code being executed by eval():

document.forms[0].field1.value = txtUserInput

Or in other words:

document.forms[0].field1.value = "'';alert(1);"

This results in the following HTML code:

<input type='text' id='field1' name='field1'
       value="'';alert(1);" />

Therefore the user input is not executed:

However, this snippet shows again how small the difference is between safe and unsafe usage of eval():

"document.forms[0]." + txtField + ".value =" + txtUserInput
"document.forms[0]." + txtField + ".value = txtUserInput"

Therefore it is recommended to completely ban this function from your JavaScript code.

Unsafe DOM manipulation using jQuery html():

var txtAlertMsg = "This is bold: ";
var txtUserInput = "test<script>alert(1)<\/script>";
   txtAlertMsg +"<b>" + txtUserInput + "</b>"

Or in other words:

   "This is bold: <b>test<script>alert(1)<\/script></b>"

This results in the following HTML code:

<div id='message'><b>test<script>alert(1)</script></b></div>

Therefore the user input is executed:

Safe DOM manipulation using jQuery html() and text():

var txtAlertMsg = "This is bold: ";
var txtUserInput = "test<script>alert(1)<\/script>";
   txtAlertMsg +"<b><div id='userInput'></div></b>"

Or in other words:


This results in the following HTML code:

<div id='message'>This is bold: <b>
   <div id='userInput'>test&lt;script&gt;alert(1)&lt;/script&gt;</div>

Therefore the user input is not executed:


  • eval() is evil
  • jQuery does not solve all your problems
  • When using JavaScript or jQuery functions to manipulate your DOM you always need to know if your content may contain user input. If yes you must only use functions which encode HTML / JavaScript strings like jQuery text().


Secure XML Parser Configuration

Most XML parsers are vulnerable for XML external entitiy attacks (XXE) by default. So what’s your mitigation?

The easiest way to prevent XXE is to disallow the Doctype declaration completely:

import org.jdom.Document;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

public class XEE_Disallow_Doctype_Decl {
	public static void main(String[] args) {
		String element= null;
		SAXBuilder objBuilder = null;
		Document objDocXML = null;
			objBuilder = new SAXBuilder("org.apache.xerces.parsers.SAXParser");
			objBuilder.setFeature("", true);
			objDocXML = File("data\\test.xml"));
			element= objDocXML.getRootElement().getChild("TestElement").getText();
			System.out.println("Element: " + element);
		} catch(Exception e) {

If this is not possible, because the Doctype declaration is required in your application, you can disallow external entities:

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class XEE_Disallow_External_Entities {

	public static void main(String[] args) {
		String xmlFile = "data\\test.xml";
		MyHandler handler = new MyHandler();
		try {
			SAXParserFactory factory = SAXParserFactory.newInstance();
			factory.setFeature("", false);
			factory.setFeature("", false);
			SAXParser parser = factory.newSAXParser();
			parser.parse(xmlFile, handler);
		} catch (Exception e) {

To ensure if your configuration is secure, you should always verify the parser manually!

Want to learn more about XML external entity attacks and application security? Join our web application security trainings in Rapperswil/Jona next week:


AntiSamy to face XSS and XXE

The community hosts a neat little project called AntiSamy[1] which lends its name from the well known MySpace worm[2] and which comes in handy when trying to mitigate Cross-site Scripting[3] attacks. Whereby XSS is sometimes hard to mitigate when business is asking for HTML formatting in user supplied inputs. At that point, AntiSamy might become handy since it focuses to strip down user supplied input to a predefined set of allowed formatting (HTML tags and attributes).

The basic steps when working with AntiSamy are

  • Define a policy file (XML)
  • Sanitize user input according to policy 

The Java API code is pretty straight forward. Note, AntiSamy is to some extent also available for .NET

    AntiSamy a = new AntiSamy();
    CleanResults r = a.scan(userInput, policyPath);

    Thus, it all boils down to configure a strict policy. Samples are shipped with the AntiSamy framework. The file I copied snippets from is named antisamy-slashdot.xml[4] . AntiSamy policy files consist of the following major sections:


    A) Directives

    Directives describe the fundamental behavior of the framework and may also help to prevent XML External Entity Attacks XXE[5] with XML message based services. 

    <directive name="omitXmlDeclaration" value="true"/>
    <directive name="omitDoctypeDeclaration" value="true"/>
    <directive name="maxInputSize" value="5000"/>
    <directive name="useXHTML" value="true"/>
    <directive name="formatOutput" value="true"/>
    <directive name="embedStyleSheets" value="false"/>

    Hint: AntiSamy would prevent XXE when configuring omitDoctypeDeclaration ‘true’. However, I do not consider AntiSamy an appropriate variant to filter doctype declarations in a large-scale XML service environments. An application level firewall would probably better fit enterprise grade infrastructure needs. Note, the full list of directives is documented in the AntiSamy developer guide[6] and the source code.


    B) Common Regular Expressions

    This section lists expressions that describe contents of tags and attributes. It basically serves as a variable declaration.

    <regexp name="htmlTitle" value="[\p{L}\p{N}\s-',:[]!./\()&amp;]*"/>
    <regexp name="onsiteURL" value="([\p{L}\p{N}\/.\?=#&amp;;-~]+|#(\w)+)"/>
    <regexp name="offsiteURL" value="(\s)((ht|f)tp(s?)://|mailto:)[\p{L}\p{N}]+[~\p{L}\p{N}\p{Zs}-_.@#\$%&amp;;:,\?=/+!()](\s)*"/>

    Confused? It is indeed pretty difficult to write properly matching expressions. Take care not to weaken your policy in a way that would allow an adversary to pass malicious inputs. You have been warned.


    D) Attribute definitions

    These definitions declare potentially allowed HTML attributes and also define what values an attribute might take. Note, the value could also be any of the named regular expressions above. Note, by listing an attribute within this section does not automatically allow that attribute to be used in user input. See tags and global attributes section instead.

    <attribute name="align" description="...">
    		<literal value="center"/>
    		<literal value="left"/>
    		<literal value="right"/>
    		<literal value="justify"/>
    		<literal value="char"/>


    E) Tag rules

    The section specifies HTML tags and explicit actions to be taken by the framework when approaching a tag. A tag definition may also reference attributes declared in the attributes section. Tags that should be allowed in user input must be flagged with action=”validate”. Unspecified tags will be deleted whereby the tag itself is removed and the content between the opening and closing tag will remain. This action can be explicitly specified as ‘filter’. The truncate action will keep the tag but remove all attributes from the tag.

    <tag name="script" action="remove"/>
    <tag name="iframe" action="remove"/>
    <tag name="style" action="remove"/>
    <tag name="p" action="validate">
    	<attribute name="align"/>
    <tag name="br" action="truncate"/>


    F) Tags to encode

    The section lists tags that will not be removed by default but its contents are being HTML encoded.



    G) Global attributes

    Lists attributes that are globally valid for all tags without explicit declaration within the tags section.

    	<attribute name="title"/>
    	<attribute name="lang"/>



    Getting a strict policy is not an easy task. However, the developers guide[6] and the project sample files give a quick start at the framework and also give advice and provide examples of how large platforms approach HTML formatting of user input.

    Got more appetite on application security? Join us for the upcoming web application security trainings (held in Jona in German language).



    [1] OWASP AntiSamy
    [2] Samy is my hero
    [3] Cross-site Scripting (and XSS Shell)
    [4] antisamy-slashdot.xml example
    [5] XML External Entity Attacks
    [6] AntiSamy Developer Guide