Tag Archives: bugs

CVE-2013-4339: Two Exploits for WordPress 3.6 URL Redirect Restriction Bypass

According to WordPress, version 3.6 is affected by a URL Redirect Restriction Bypass issue that allows an attacker to craft a URL in such a way that, should it be clicked, would take the victim to a site of the attacker’s choice via the Location: tag in a 302 Redirect. Current descriptions of the WordPress issue may be found at WordPress (1, 2), Mitre and OSVDB.

I can confirm that this issue exists in versions 3.1 and 3.6. Due to the range of versions, I assume that it exists in all releases in between but I have not confirmed it. If running an outdated version of WordPress please upgrade to the latest version, which is 3.6.1 at the time of this writing. The current 3.6.1 release fixes four additional issues (1, 2, 3, 4) as well.

There are two attack vectors: the first is a full URL redirect; the second is a partial redirect, as the victim is automatically taken to a WordPress error page with the attacker’s link embedded in a prominently displayed tag.

In order for either exploit to work (assuming the victim clicks on the link) two conditions must be true: first, the victim must be logged into the site (wp-admin); and second, they must have permission to the editing page (edit-tags.php or edit-comments.php). If either of these two conditions are false the vulnerable code will not be reached.

Exploit 1: edit-tags.php Full URL Direct

The above exploit URL will do a full redirect when the link is clicked on by the victim. It is important to note that in order for the exploit to work the string ‘edit-tags.php’ must be present in the _wp_http_referer parameter. For example:

In this case I chose to put it after a ‘?’ and by doing so I create a dummy parameter so that any valid URL before the ‘?’ executes on the attacker’s server. Under normal circumstances servers such as Apache and IIS will not view web application parameters (the stuff after the ‘?’) as pointing to valid server files to execute. On the application side, WordPress should discard the extra parameter.

Alternatively an attacker may create a URL such as:

This URL has a ‘/’ instead of a ‘?’. This means that the attacker would need to create a valid page named ‘edit-tags.php’ on the attacker’s server in order to have their code run.

The normal WordPress login code prevents access to any page under wp-admin if the user has not authenticated. After authentication, the code in edit-tags.php below prevents users without permission from accessing the page:

Exploit 2: edit-comments.php Embedded Link Partial Redirect

The above exploit URL will embed the attackers link in the error page of WordPress with the text “Please try again” as seen in the image below.


Similar to Exploit 1, the normal WordPress login code prevents access to any page under wp-admin if the user has not authenticated. After authentication, the code in edit-comments.php below prevents users without permission from accessing the page:

Malformed HTML & XSS Character Filtering: A Few Lessons

On a recent web app pen test I ran into the following issue: the application would escape (that is, add backslashes) before single and double quotes but not filter other characters. Upon review of the source it was clear the developer knew that not escaping these quotes would lead to issues (such as SQL injection) but they did not appear the grasp the larger picture.

For those who wish to avoid the technical discussion below, here are the talking points:

  • If you are a developer, filter out as many characters as possible without breaking your web app
  • If you are a pen tester, the fewer characters filtered the more likely the code has vulnerabilities

What I hope to show is how an assumption about syntax could prove untrue since the following two statements are valid:

  • Not enough filtering may allow the attacker to create “enough valid” HTML syntax to allow code injection
  • The browser’s disposition to interpret malformed or “bad html” as valid gives the attacker more surface area to attack

Below is a tutorial on basic malformed HTML in three parts. The first part shows how bad filtering can lead one to create valid (or semi-valid) HTML the developer did not intend. The examples will show that the browser will interpret partially malformed HTML as legitimate despite syntax errors. The second part shows that once the attacker creates “valid” HTML injecting attack code is made much easier by injecting additional malformed HTML. The third part is an exploit created from parts one and two.

The code below is a case of  a developer dynamically building a string to pin/post to pinterest. The code has been rewritten to hide the source of the material but it is a true and formally live case of the  logical errors described above.

My motivation for this basic tutorial is my response from another professional. While I was investigating this issue on-site another infosec professional said to me that if the quotes are escaped then the app can’t be exploited. It turns out this is the same incorrect assumption the developer made. Perhaps this will help explain this issue so that other professionals recognize instances of this issue.

Note: the syntax highlighting is not an accurate representation on how the browser will interpret the HTML. In fact, the syntax highlighting below is more strict.

Part 1 – Bad Filter, Bad HTML

The developer’s assumption was simply that if the attacker could not pass a single or double quote they could not create syntactically meaningful HTML or exploit the application. For example, the following valid HTML

after being run through the filter would be turned into:

which, due to the backslashes, is meaningless to the browser.

Unfortunately simple cases of only filtering double quotes is an assumption since we can sometimes: first, end tags meaningfully despite the escape; and second, do not need double quotes in our HTML in order to get some invalid HTML to be “properly” interpreted as valid.

In this case I found the developer was building strings dynamically from values in the URL. The offending URL looked like this:

So putting “test” in the badparm as so:

resulted in the following dynamic HTML

So you’ll note that we have the ability to get our input — the string ‘test’ — into the middle of the dynamically built string. Given that this code is intended to be “pinned”, there are two forms of attack here. Once we can get our code to be injected via a URL if we can get it pinned on pinterest– either through us manually pinning it or through social engineering the end user — it will be stuck there. Quite interestingly, it’s possible for our reflected XSS injection attack to become a stored injection attack (as long as pinterest does not filter the characters in our URL). Then anyone who clicks on the pinterest link will run the code when it comes back to badsite.com. The other way is to simply leave our attack as a reflected attack and inject our code into badsite.com through a URL on which we get an end user to click. In either attack, to be successful, we will need to end (or close) the tag otherwise our code will remain as part of the URL and not as code to be parsed and interpreted in the next block.

Let’s test out the filter. If we add a double quote to the end of badurl.com as such:

We have the following output (slightly abbreviated from the longer version above):

So far, the string is escaped properly. But what if we put in a > after as such:

All of a sudden we get the following code:

To be more explicit the following snippet from above is “valid” html:

Yes, despite the mangled \”> it is treated as a valid ending to HTML. The escape backslash added by the developer’s filter is not counted!

In all fairness, the two code snippets above is not valid but no matter. Since we’ve successfully closed the tag according to the browser we can now put our code after to be executed as a new tag.

Part 2 – Bad HTML, Bad Filter equals Good Exploit

In the prior section we learned about how escaping can be bypassed if the HTML end tag is seen as valid. In this case we will see how malformed HTML can be interpreted as valid.

Here is a valid image tag:

But did you know the following is also interpreted as valid by the browser?

That’s right. An image tag without double quotes! So, here’s the important point. If the image tag does not need double quotes, when we encounter filters that only filter the quotes we will bypass it. Who needs quotes anyway?

In this simple example I loaded Google’s homepage image via an img tag. I leave it to the reader as an exercise to understand how the img tag may be used to inject javascript and other malicious code. In short, if a researcher can inject the img tag into a dynamic URL displayed on a webpage (as shown above) they can do damage. So, pretend the Google image is really an exploit.

Part 3 – The Exploit!

If we go back to our bad url from Part 1:

and put a “> and then our malformed image tag without double quotes we get the following URL:

If we execute the URL we get the following code as a result:

The browser will now run our mangled/malformed injected img code (without the dquotes) since we’ve closed off the HTML and our injected code is seen as the next tag for the browser to interpret.

To be more explicit, the following snippet parsed from the code quoted just above will be treated as valid HTML:

Lesson: filter out those extra characters!

Vulnerability: CVE-2013-1422 – WebCalendar 1.2.5 & 1.2.6 Valid User Determination

WebCalendar versions 1.2.5 and 1.2.6 allow an attacker to determine a valid user id on the system. After submitting an invalid ID the software, “Invalid Login: no such user.” Please see screen shot below.


Publicly Disclosed Vulnerabilities & Exploits between 2000-2006

Here is a list of my publicly disclosed vulnerabilities from 2000 through 2006. I figure these should be added to my public OSVDB profile. (I actually have two!) It’s 2013. These were found a long time ago. Still, I did the work; why not receive the credit?

It should be emphasized that these are vulnerabilities that were publicly disclosed and not the totality of those that I’ve discovered between 2000-2006.  If I can find additional ones I will update this as necessary. This page is more for historical accuracy and record keeping than anything else.

Date CVE / CAN / BID Vuln Name and Link
08/25/00 CVE-2000-0777 MS00-061 : Microsoft Money Password Vulnerability
11/01/01  CAN-2001-0721 MS01-054: Microsoft UPnP Denial of Service Vulnerability
11/08/01 BID: 3518 IBM HTTP Server Source Code Disclosure Vulnerability
02/07/02 BID: 4059 OS/400 User Account Name Disclosure Vulnerability
02/18/02 CVE-2002-0291 Dino’s Webserver Denial of Service Vulnerability
02/21/02 CVE-2002-0298 Nombas ScriptEase:WebServer Edition GET Request Denial of Service Vulnerability
03/22/02 CVE-2002-0479 Gravity Storm Service Pack Manager 2000 Directory Permissions Vulnerability
06/25/02 BID: 5094 Microsoft Internet Explorer CLASSID Denial of Service Vulnerability
06/30/02 BID: 5357 Microsoft Windows mplay32 Buffer Overflow
10/08/02 CVE-2002-1529 SurfControl SuperScout Email Admin Server XSS
10/08/02 CVE-2002-1530 SurfControl SuperScout Email Admin Server Data Integrity
10/09/02 CVE-2002-1531 SurfControl SuperScout Email Admin Server Content-Length: DoS
10/09/02 CVE-2002-1532 SurfControl SuperScout Email Admin Server Incomplete Get Request DoS
08/29/05 CVE-2005-2787 Vulnerability and Perl Exploit: SimplePHPBlog
05/17/06 CVE-2006-2531 Ipswitch WhatsUp Professional 2006 Authentication Bypass Vulnerability

Vulnerability: OrangeHRM 2.7.1 Vacancy Name Persistent XSS

OrangeHRM 2.7.1 — the latest stable release as of this writing — suffers from a persistent XSS in the vacancy name variable. Steps:

  1. Navigate to following URL:
  2. Add or Edit a Vacancy
  3. In the Vacancy Name parameter put XSS script
  4. Save
  5. Navigate back to top Vacancy page (click back button)
  6. Witness XSS

Screen prints in the gallery below. The images should be self-explanatory.The direct URL to the list of vacancy page is below.

I contacted OrangeHRM but did not receive a reply.

PHP uniqid() – Entropy Analysis and Potentially Vulnerable Apps

This research started with my reporting a zero-day that Front Accounting’s reporting used uniqid() and it’s file names were non-random. Given where the application saves these reports by default they are retrievable by anyone who can guess the proper URL report name. OSVDB asked me to what extent does this issue overlap with a larger, previously reported PHP issue of non-randomness in the generation of PHPSESSIONID. Over the course of my research I discovered that, while both suffered issues of non-randomness, uniqid() and LCG were independent from each other after PHP3. As of PHP4+, uniqid() is not used to generate session cookies. While uniqid()  uses an LCG randomness routine it only does so when the more_entropy flag is set by the developer. LCG is not the cause of the lack of uniqid() entropy. In fact it is just the opposite. It helps it when the flag is set but not significantly. As such it is my humble opinion that CVE and OSVDB descriptions needed to be updated to reflect this information. In our tweets Steve Christey was still worried — and rightly so — that many applications use the uniqid() function and might be vulnerable. So, here we are.

It’s clear that uniqid() is non-random. This is even reported in the PHP documentation. The question is how non-random is it? Furthermore, what’s the impact? How many apps are using the function?

I tested the non-randomness by writing some sample PHP code taken almost straight from the documentation. I did this because I felt it best to use the sample code provided by PHP to their users. I assume here that it will be the way most people will use the function (copy and paste). Two apps were written: one to test the function regularly and one to test it with added entropy. Since I’m not a math geek, I used burp‘s Sequencer functionality to test the entropy. I have fairly smallish sample sizess but I believe I do not need a larger ones to change the general nature of the result. (I leave this to the next researcher.) I then used Search Diggity to scan through google’s project code as well as doing a direct search. I attached a gallery with annotations showing the testing procedure and results.


With or without the more_entropy option, uniqid(), as represented in the PHP sample code and documentation, results in poor entropy and should not be used. According to burp, with a sample size of 4016 tokens, uniqid() without more_entropy is “extremely poor” and has a effective entropy of 10 bits. With a sample size of 7515 tokens, uniqid() with more_entropy enabled is “poor” with an effective entropy of 29 bits. According to burp the reliability of the sample sizes were either reasonable or good. It is my opinion that if the tests were conducted over a larger sample size the effective entropy will only decrease: by how much I’m not certain.

The question remains: are there vulnerable applications and to what extent? Search Diggity returns 100 instances of uniqid() being used on google code. Google’s own search engine returns 60K+ strings matching uniqid(). Important:  google’s query is a bit of a false indicator since it returns results that matches the string including languages other than PHP. And, I didn’t scan other repositories such as Sourceforge or Github.

Lesson 1: heed the PHP documentation and do not use uniqid() when the need for a random string arises. Lesson 2: it seems that there is a decent amount of potential vulnerable code.

Below are the pictures to support the research. Many thanks to OSVDB and Steve Christy for an excellent exchange of tweets. Enjoy and happy hunting.

0-Day: Front Accounting 2.3.13 Predictable File Name and Public Path

Front Accounting (FA) had document storage capabilities. Three issues arise:

1) FA stores documents under the server root
2) FA uses a non-random way to generate the report names
3) these reports do not have any authentication, able to be retrieved by anyone

The known file locations are below where X is company number starting at 0 (zero).


The software uses the uniqid PHP routine which is known for being non-random:

Because it is difficult to show, please see the screen print below regarding the non-random name.

I emailed the software company through their website but did not receive a reply. This was also disclosed to securityfocus.com but I believe it was not publicly reported since the email contained the image below as an attachment (or the original email was HTML and not TXT).


Two New Columns and WordPress Bugs

I writing two new columns for bloginfosec.com. Hopefully I can get some more work done on the this weekend. They should be published on the next consecutive Mondays.

I was updating my profile and found that the HTML target tags were being automatically removed! Grrrr…