A tale of an interesting source code leak (Mar, 27th 2016)

  • Routing bypass using SOH
  • High severity issue

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

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.
Why?
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 phase 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:
https://www.victim.tld/password.jsp%00
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:
HTTP ERROR: 400
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:
https://www.victim.tld/password.jsp%01
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

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!

References
http://httpd.apache.org/docs/current/handler.html
http://httpd.apache.org/docs/current/mod/mod_mime.html
https://tomcat.apache.org/connectors-doc/reference/apache.html
Web server handler/filter/modules with similar issues in the past:
CVE-2007-1860: mod_jk double-decoding:
http://www.cvedetails.com/cve/CVE-2007-1860/

WebLogic: http://www.example.com/index.js%70
(via: http://www.securityfocus.com/bid/2527/exploit)

Tomcat: http://www.example.com/examples/snp/snoop%252ejsp 
(via:http://www.securityfocus.com/bid/2527/exploit)

IBM Websphere: http://www.example.com/login.JsP
(via: http://www.securityfocus.com/bid/1328/info)

Netscape Web Server: http://www.example.com/login.jsp%20
(via: http://www.securityfocus.com/bid/273/discuss)

Allaire JRun Root directory disclosure:
http://server/%3f.jsp
(via: http://www.securityfocus.com/bid/3592/discuss)

Apache httpd artificially Long Slash Path Directory Listing Vulnerability:
http://www.example.com///[1-4096 slashes here]/admin/*
(via: http://www.securityfocus.com/bid/2503/discuss)

BEA WebLogic Directory Traversal with %00, %2e, %2f and %5c:
http://www.example.com/%5cadmin/
(via:http://www.securityfocus.com/bid/2513/discuss)

ebay.com: remote code execution using complex curly syntax (Dec 13th, 2013)

  • filter bypass using type cast and curly syntax
  • High severity issue

Once again i have been bug hunting on eBay websites. This time I found 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 subdomain was the same where I found an exploitable SQL injection last year which is located at http://sea.ebay.com .

A legit user request looked like:
https://sea.ebay.com/search/?q=david&catidd=1

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:

https://sea.ebay.com/search/?q[]=david&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(” instead of ‘), the php parser will allow code evaluation if some circumstances are given.

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:
https://sea.ebay.com/search/?q={${phpinfo()}}&catidd=1

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.
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?


How does php internally handle strings?
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.
https://sea.ebay.com/search/?q[0]=david&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”. 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.


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.
https://sea.ebay.com/search/?q[0]=david&q[1]=secalert{${phpinfo()}}&catidd=1
Success! Now let’s verify this by submitting two more requests.
https://sea.ebay.com/search/?q[0]=david&q[1]=secalert{${phpcredits()}}&catidd=1
https://sea.ebay.com/search/?q[0]=david&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.

references
http://www.php.net/manual/en/language.types.string.php
http://www.suspekt.org/downloads/DPC_PHP_Security_Crash_Course_06_IncludeAndEval.pdf
timeline
December,  6th 2013: vulnerability discovered and reported to ebay
December,  6th 2013: recorded a screencast as proof of concept
December,  9th 2013: ebay solved the issue and deployed a hotfix
December, 13th 2013: this write-up has been published

ebay.com: remote blind sql injection (Nov, 18th 2012)

  • blind sql injection
  • High severity issue

Lately, during bug hunting on sub domains of ebay I have identified a SQL injection which was a bit tricky to exploit. I decided to write this blog post to remind you to be creative when it comes to exploitation. The vulnerable page was located at http://sea.ebay.com/news.php. During the research I found that every time one submits SQL statements the web application will raise a common SQL error message warning that the syntax is wrong.

For example when I supplied:
...
POST /news.php?time=3&catid=31 HTTP/1.1
...
checkbox%5B%5D=(select @@secalert)
...
the web application replied with the message:
Unknown system variable ‘secalert
which indicates that user supplied values are parsed as sql statements within the legit query. Obviously the next step was to submit sql statements which would reveal some information like the database version, schemes and so on.

..
POST /news.php?time=3&catid=31 HTTP/1.1
...
checkbox%5B%5D=(select @@version)
This request showed no results. Then i tried couple other sql statements which had no results.

After a couple of sql statements I realised that I would only get results in cases where the sql syntax is either wrong or the variabled requested are unknown. This led me to the interesting part. I have to use a nested SELECT statement which would show me valid results when the main SELECT statement has any error and therefore raises a warning message.

POST /news.php?time=3&catid=31 HTTP/1.1
…
checkbox%5B%5D=(select+1+and+row(1%2c1)>
(select+count(*)%2cconcat(CONCAT(CHAR(68)%2C
(SELECT+USER())%2CCHAR(65)%2CCHAR(86)%2CCHAR(73)%2CCHAR(68))
%2c0x3a%2cfloor(rand()*2))x+
from+(select+1+union+select+2)a+group+by+x+limit+1))&
...

It works! In the result it shows the name of the DBMS user which is "ARV033@10.4.33.36".

To verify the issue I decided to make a second request which shows the DBMS version which is 5.1.39.

POST /news.php?time=3&catid=31 HTTP/1.1
…
checkbox%5B%5D=(select+1+and+row(1%2c1)>
(select+count(*)%2cconcat(CONCAT(CHAR(68)%2C
(SELECT+@@VERSION)%2CCHAR(65)%2CCHAR(86)%2CCHAR(73)%2CCHAR(68))
%2c0x3a%2cfloor(rand()*2))x+
from+(select+1+union+select+2)a+group+by+x+limit+1))&         
...

The conclusion of this blog post is to remind you that sometimes we have to be creative and chain a valid request with a forced error in order to get our results in the raised error or warning messages which means that context is key! As remediation ebay used “prepared statements” to prevent user supplied values to be parsed in the sql query.

timeline
October,  30th 2012: vulnerability identified and reported to ebay
November, 05th 2012: Vulnerability reported to ebay once again 
November, 05th 2012: ebay confirms the presence of the sql injection
November, 16th 2012: ebay replied that the issue is now fixed 
and they want to send me a little gift
November, 18th 2012: this blog post has been published 
December, 15th 2012: the gift ebay sent me finally arrived. Thanks :)

impress and contact

David Vieira-Kurz
Kemmannweg 26b
13583 Berlin, Germany
e-mail: david.kurz@majorsecurity.net