Slack, a brief journey to mission control

Oct, 20th 2016


In this blog post I will describe my thoughts while performing a blackbox pentest during Slack bug bounty program.

Thanks to the Slack security team

I want to thank Leigh Honeywell and Max Feldman of the Slack security team for the gentle, professional communication and coordination in the bug reporting process.

Information gathering

In order to understand the infrastructure and to gain information about the used framework I started to check the HTTP response header and saw that Slack is using an Apache httpd server. So I tried to identify common Apache directories and directives like /icons/README, /manual/, /server-info and /server-status.

May I access your internal data, please?

Slack runs mod_status on the web server. The Status module allows a server administrator to find out how well their server is performing and which resources have been requested by which ip addresses. An attacker may make use of this information to craft an attack against the web server.

When I tried to access server-status directive, the server redirected me to a login page located on the * domain. So this path has been protected.

Out of scope domain! Now what?

If you are lazy, be warned that brute-force is not permitted by the rules of the Slack bug bounty program. So one would now try to bypass the login page with some injection techniques, but unfortunally the login page itself is located on a FQDN outside of the allowed scope, so this was not an option. I had to find a way to stay within the allowed scope of

Routing? Filter? - Blackbox testing

First of all I thought, that if they are using Apache httpd and mod_status, the redirect could be triggered using the rewrite module. The mod_rewrite module is a powerful module for Apache used for rewriting URLs on the fly. However with such power come associated risks; it is easy to make mistakes when configuring mod_rewrite, which can turn into security issues. Take for example one of the configurations in the mod_rewrite documentation:

RewriteRule ^/somepath(.*) /otherpath$1 [R]
If this is the case, they could probably have misconfigured the RewriteRule and therefore I could bypass it by simply adding a slash. Why? Requesting
will redirect and return the page http://yourserver/otherpath/secalert as expected. However, requesting
will bypass this particular RewriteRule. In case of Slack it was not possible to bypass it this way. So I had to think outside the box.

I was playing around with representations of a slash in order to potentially bypass a simple string based filter protection.
I played around with the RTLO sequence in order to bypass the filter by submitting the RTLO sequence followed by the reversed string.{u+202e here}sutats-revres
which did not work at first.

Access control bypass!

After a few tests I thought, that they could use a Route Map in their framework and that I potentially could bypass the routing mechanism or access control by adding multiple forward slashes in case that the applied filter checks if the string starts with a particular string and does strip a forward slash, but eventually miss to strip all slashes recursively, and this finally worked.

Bounty as low as $50?

While writing the report for Slack on hackerone I decided to add some screenshots as proof of concept. At this point I thought that I would earn the minimum bounty of $50 for reporting this misconfiguration issue, because the server-status file usually would not expose any sensitive information to me if the requested resources are part of my own Slack workspace, right? Well, i logged out of my Slack account and requested the server status without being logged in! That means that an attacker would potentially gain unauthorized access to the requested resources of ANY Slack site by accessing the server-status directive of a given workspace!

Secrets exposed, increased bounty!

I realised that there are some requests listed like /callbacks/chat.php?secret=... and /users.list?token=... ,which definitely are sensitive data. So I added some screenshots, which most probably increased the bounty I finally received. Thanks again to Slack for that generous bounty.

Google indexing

After receiving the first bounty from Slack which has been generous I was motivated to hunt for further issues. I googled for common file extensions located on the Slack web sites and found cached urls, which indicates that Slack does have or had a backend admin panel, which Google indexed in the past. When i tried to access these pages I got redirected to the login page once again. But since Slack resolved the prior reported issue, chances were low, right?

Access control bypass part II

Well, after a couple of requests I found that on the particular path to the administrative panel I could bypass the restriction if I use exactly 4 slashes, which only worked on this particular controller!

Backend access -> second bounty!

The Slack employees have access to a backend admin panel called mission control. In the mission control panel authorized people are able to read lots of meta data related to Slack user and Slack workspace by passing an id to the correspondingly controller. Since the needed "id" is being exposed in the rendered html of my own Slack workspace I read the meta data associated to my own account and sent these screenshots to the Slack security team. Besides that it was identified that an attacker would be enabled to reset the password of any user by guessing their "id" and passing a request to the associated reset controller in the mission control panel. This would allow an attacker to take over any account! For this issue I received an additional bounty.


Be patient! Sometimes you may identify a flaw that seems to be trivial from technical point of view, but may raise a high business impact or an increased data privacy issue to the affected company, so that they could rate the risks different than you initially thought.



Apr, 11th 2016: issue identified and reported
Apr, 11th 2016: verified by slack
Apr, 13th 2016: issue fixed
Apr, 13th 2016: received a bounty
Apr, 14th 2016: identified and reported second issue
Apr, 14th 2016: issue verified by slack
Apr, 24th 2016: issue has been globally fixed
Apr, 24th 2016: received an additional bounty on top
Oct, 20th 2016: this write-up has been published

CVE-2016-4977: RCE in Spring Security OAuth 1&2

Oct, 13th 2016

Affected version

  • Pivotal Spring Security OAuth 2.0 - 2.0.9
  • Pivotal Spring Security OAuth 1.0 - 1.0.5


A couple of months ago I performed a pentest against a web application which used the Spring Security OAuth framework for authorization. During my research I have identified some issues, including remote code execution flaws. The web application had implemented the Spring Security OAuth framework which comes by default with a template that is prone to RCE! One would believe that this one is secure by default, but indeed it was not. During my research i realized that there are a couple of well known websites that also implemented the vulnerable code.

Spring Boot Demo

If you want to verify the issue yourself, you can download the spring boot demo application as a maven project from

Let's get started

Usually one would run the demo application by passing a legit request like:

Everything works as intended. I then started to look for common issues like XSS:

This led to an error which showed the Whitelabel Error Page. Surprisingly there are lots of well-known websites which still use the Whitelabel Error Page instead of having configured a custom error page. The Spring Security OAuth example shows the Whitelabel Error Page by default whenever an error occurs. The Whitelabel View reflects parts of the given parameter values, which leads to XSS at first glance. After finding the XSS during blackbox testing I reviewed the source code to identify the vulnerable code before I report the issue to upstream. While reviewing the source code I realised that there is a more dangerous issue there.

Error handling calls "SpelView" endpoint

Let's review the source code of

/* Lines 137-148 of: */

private final SpelView defaultErrorView = new SpelView("Whitelabel Error Page"+ "This application has no explicit mapping for /error, so you are seeing this as a fallback."+ "${timestamp}"+ "There was an unexpected error (type=${error}, status=${status})."+ "${message}");
@Bean(name = "error")
@ConditionalOnMissingBean(name = "error")
public View defaultErrorView() {
        return this.defaultErrorView;}

The user supplied values are passed to the Class which is using the SpelExpressionParser of oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/

Source code: /spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/
import org.springframework.expression.spel.standard.SpelExpressionParser;
private final SpelExpressionParser parser = new SpelExpressionParser();
private final StandardEvaluationContext context = new StandardEvaluationContext();
this.helper = new PropertyPlaceholderHelper("${", "}");
Expression expression = parser.parseExpression(name); ...

This is interesting. The Spring Expression Language (click here for detail) is the syntax used by spring for configuration and code place in annotations. To check if the param is also prone to Spring Expression Language Injection I then passed:


The response message shows "666" which means that the proof of concept code has been evaluated!

Exploiting the RCE (on Linux)


Exploiting the RCE (on Windows,null_ref)


The hotfix

The maintainer released a hotfix:

Race condition in the hotfix may be exploitable

If one reviews the applied bug fix one may conclude that the fix looks some kind of a partial fix. They try to prevent recursive placeholders in whitelabel views by using the class in order to replace the "{" prefix.

    /* Source code: "": */
public SpelView(String template) {
    this.template = template;
    this.prefix = new RandomValueStringGenerator().generate() + "{";
    this.context.addPropertyAccessor(new MapAccessor());
    this.resolver = new PlaceholderResolver() {
      public String resolvePlaceholder(String name) {
            Expression expression = parser.parseExpression(name);
        Object value = expression.getValue(context);
          return value == null ? null : value.toString();
    String maskedTemplate = template.replace("${", prefix);
    PropertyPlaceholderHelper helper =
    new PropertyPlaceholderHelper(prefix, "}");
    String result = helper.replacePlaceholders(maskedTemplate, resolver);
    result = result.replace(prefix, "${");
This looks like a quick win solution, but if an attacker makes a sufficient amount of requests the RCE could still be exploitable due to a race condition since the RandomValueStringGenerator (click here for API docs) Class generates a string with the default length (6).

Whitelabel Error Page on production environment

As web developer or web admin you should consider disabling the whitelabel error page or use a custom error page with a generic text. Please refer to Point < code>77.2 Customize the whitelabel error page on


Feb,  8th 2016: vulnerability discovered and reported to upstream
Feb, 14th 2016: upstream verified the issue
Mar, 12th 2016: upstream deployed a hotfix
Jul,  5th 2016: initial vulnerability report published by upstream
Oct, 13th 2016: this write-up has been published

A tale of an interesting source code leak

Mar, 27th 2016


Lately, while participating in Bug Bounty Programs, I came across an interesting issue which was classified with the highest severity yielding a potential bug bounty. Due to it's terms, i am compelled not to disclose the name of the company.

Information gathering

I started with some information gathering and footprinting. I noticed that the files ends with the ".jsp" extension which often runs with Apache Tomcat. First I reviewed the http response header in order to gain some information about the target system:

HTTP/1.1 200 OK
Date: 16 Mar 2016 15:15:33 GMT

If the http status code is followed by the date response header in the second line it usually means that it the page is using an Apache httpd as web server. In this case I assumed that an httpd is used in front of an Tomcat web server. If i am right then they could probably be using some module to dispatch the files between the httpd and the Tomcat web server which means I could potentially trick the routing to expose the source code of any ".jsp" or ".inc" files by appending specific lower ascii characters - depending on whether they are using a Connector or Handler.

Connector, Handler, File Descriptor

1) The Apache Tomcat Connectors: If Apache httpd and Tomcat are configured to serve content from the same filing system location then care must be taken to ensure that httpd is not able to serve inappropriate content such as the contents of the WEB-INF directory or JSP source code. This could occur if the httpd DocumentRoot overlaps with a Tomcat Host's appBase or the docBase of any Context. It could also occur when using the httpd Alias directive with a Tomcat Host's appBase or the docBase of any Context.

2) Well, let's have a look on the Apache web server handler. A "handler" is an internal Apache representation of the action to be performed when a file is called. Generally, files have implicit handlers, based on the file type. Normally, all files are simply served by the server, but certain file types are "handled" separately. If you want to handle ".jsp" files you may for example use the Apache module "mod_mime" in order to associate the requested filename's extensions with the file's behavior (handlers and filters) and content (mime-type, language, character set and encoding).

What will the httpd do if you try to access file which is not explicitly associated with a handler or filter? Httpd will serve the file as plain text without further actions which means that we can potentially exploit this behaviour.


In the case of my research of this particular target system i knew from the information gathering analysis that they were handling ".jsp" files, so i assumed that they are using an Apache httpd in the front and an Tomcat or similar web server in the back end of the architecture. So i tried to append some character to the file extension like this in order to get some information by forcing the system to run in some uncaught exceptions and show up with any anormally behaviour:
This, however did not work as expected. I was expecting the system to expose a stack trace or to run into a web application firewall, but instead if came it up with the following message:
Problem accessing /password.jsp%00. Reason:
    The request contains an illegal URL
From several pentests I performed in the past i knew that the apache httpd would usually strip the %00 and raise a message like this one:
Not Found
The requested URL /password.jsp was not found on this server.
Therefore I assumed that the error message is not originated by the httpd but from a connector. From past pentests I know that there were some connectors which led to unusual behaviour when passing lower ascii characters to them.

During my research related to Tomcat connectors I found that i may manipulate the routing of the data stream by using the SOH (start of header, 0x01) transmission control sequence. The start of heading (SOH) character was to mark a non-data section of a data stream which is the part of a stream containing addresses and other housekeeping data.

As i have been successful with this trick in past with several modules such as mod_proxy_ajp, mod_jk, some spring boot implementations and a few other i tried:

What I assumed

In this case I assumed the target system had following implementation in place:
1) Send request to Apache httpd
2) httpd uses it's file handler/filter to pass the request to Tomcat for processing
3) Tomcat uses it's file handler to open the".jsp" file because it handles
the %01 as the start of a new header and not as part of the file extension
4) Tomcat passes the content of the requested file to the httpd
which now has the content of the ".jsp" file with the requested extension ".jsp%01".
5) httpd does not find the ".jsp%01" extension in it's file
handler's extension list and therefore decides to serve the file as plain text
6) The same also works for ".inc" files on the target system

PoC and reporting

I would potentially gain access to the whole source code but decided to access a few ".jsp" and ".inc" files as a proof of concept. I then immediatly reported this issue to the company and within 3 hours they gave me feedback that they verified the issue and triaged it with the highest severity. They then deployed a hotfix within 48 hours. Respect!

Web server handler/filter/modules with similar issues in the past:
CVE-2007-1860: mod_jk double-decoding:



IBM Websphere:

Netscape Web Server:

Allaire JRun Root directory disclosure:

Apache httpd artificially Long Slash Path Directory Listing Vulnerability:[1-4096 slashes here]/admin/*

BEA WebLogic Directory Traversal with %00, %2e, %2f and %5c:
(via: RCE using CCS

Dec, 13th 2013


Once again i have been hunting security issues on ebay's web sites. This time I've identified a controller which was prone to remote code execution due to a type cast issue in combination with complex curly syntax. Since this techniques are less known and less discussed I found it interesting enough to blog about it. The vulnerable sub domain id the same where I've identified an exploitable SQL injection last year, which is located on .

Information gathering

A legit user request looked like:

One of the very first tests I perform against php web applications is to look for type cast issues because php is known to raise warnings or even errors when the value of a given param is an array rather than being a string which it is expected to be. So obviously my next step was to perform the above request using [] to submit it as an array:[]=Dave&catidd=1

The web application served me the same response as in the prior request which surprised me a bit. From my experience I know that php has several ways to handle strings. For example if the string is enclosed in double-quotes, the php parser will allow code evaluation if some circumstances are given.

PHP complex syntax

Well, if we use php's complex curly syntax we could possibly have some success. Never heard of complex syntax?

Let's give it a try:{${phpinfo()}}&catidd=1

PHP code evaluation circumstances

This had no success. So let's rethink which circumstances may lead to code evaluation in php.

Which of these is ebay using?

Since it's been a blackbox test I assumed that eBay was using preg_replace() for filtering bad words in combination with the eval() function afterwords because of 2 observations i made:
1) they were using a spellchecker. I have seen a bunch of spellchecker in web apps working with eval() function in the past
2) they are using some filter which I guess to be a blacklist of words that are being replaced with the preg_replace() function.

Blackbox analysis

For example when I submitted my handle 'secalert' it was stripped and as a result it returned 'sec' in the response of the search query. So obviously they are filtering words like 'alert' from the user supplied string, maybe in hope to prevent XSS, which is a very bad idea! It didn't work. Okay, seems like they are not using user-supplied values within double-quotes. So what can we do now?

PHP's internal string handling

How does php internally handle strings?

PHP complex syntax + http parameter pollution + array indexing

So let's try to submit an array rather than a string and try to echo the values of the param 'q' by accessing the array indices.[0]=Dave&q[1]=secalert&catidd=1

It works. The search controller parsed that request and I got the last instance as part of the result, in this particular case it returned valid entries which matched to the keyword 'sec'.

My assumption

But why? As mentioned prior I was assuming that eBay is using preg_replace() for filtering bad words and afterwards doing some eval() stuff with that return values. So what happens here could be that they are trying to enforce that user supplied values are always of the type string. That means if it's not a string they try to make a string out of it, i.e. they try to cast the values of the array into a string before doing the string comparison for the list containing bad words.

Exploiting the RCE

Okay, good. But how can we exploit that? We will put all this stuff together and submit an array with 2 indices containing arbitrary values, one of them will be supplied in complex curly syntax to trick the parser.[0]=Dave&q[1]=secalert{${phpinfo()}}&catidd=1
Success! Now let's verify this by submitting two more requests.[0]=Dave&q[1]=secalert{${phpcredits()}}&catidd=1[0]=Dave&q[1]=secalert{${ini_get_all()}}&catidd=1

Verified! We can evaluate arbitrary php code in context of the ebay website.

From my point of view that was enough to prove the existence of this vulnerabilty to ebay security team and I don't wanted to cause any harm. What could an evil hacker have done? He could for example investigate further and also try things like {${`ls -al`}} or other OS commands and would have managed to compromise the whole webserver.



December,  6th 2013: vulnerability discovered and reported to ebay
December,  9th 2013: ebay solved the issue and deployed a hotfix
December, 13th 2013: this write-up has been published