Friday, April 15, 2011

HP disclosed but didn't fix printer security holes

HP released a bulletin covering CVE-2011-1531, CVE-2011-1532, and CVE-2011-1533 on April 12 that acknowledges these security issues I reported to them exist, but will not be providing a patch to address them.  Instead, they have provided some recommendations and workarounds.


Some of the recommendations are not very practical in real life, such as avoiding XSS by "Exposure can be reduced by avoiding untrusted URLs".  This is not because they didn't understand the problem, but because there was nothing much else to say when they weren't going to fix the issue.  


The main issue that I was hoping they would fix is an XSS in the embedded web server of the printer.  By default, the printer is not protected by a password, and that could result in a malicious website being able to explore your printer/network settings or reconfigure it in various ways.  The XSS is reflective and I imagine it is not that uncommon for printers to have DNS within the company domain, allowing it to be used to steal/set cookies, pivot into your network to access private data, and all the other run of the mill nasties that you could do with malicious Javascript on an internal network.


HP's advisory is here:


http://h20000.www2.hp.com/bizsupport/TechSupport/Document.jsp?objectID=c02267197


There's more than one place to XSS this but I like the error page of the printer because it is accessible even with authentication enabled.  You can trigger it with a POST to refresh.htm, which will result in unescaped output provided to it in the "refresh_rate" variable.


I appreciate that HP took the time to disclose the bugs, but it makes me wonder what my expectations should be for them to fix any other HP products.  Perhaps XSS is just below their threshold, or maybe they think printers are not worth fixing.  It's hard to tell what they would care enough to patch.  

Sunday, March 27, 2011

Man-in-the-middle attacking Mozilla Firefox updates

Earlier today I was proved wrong when I claimed it was not possible to update from Firefox 3.x to 4.x securely.  I'm not quite sure what happened when I originally tested it -- potentially it was something to do with one of their security updates going out, but in any case, this got me looking at how their updates work.

The latest Firefox 3.x actually pulls update information from an SSLized URL, and it verified the binary package before installing it.  I was pretty happy when I saw that, but I started wondering how the update box below was rendered:


It turns out that the user-readable details about the new version are pulled as plaintext HTTP from Mozilla's servers.  I wondered what would happen if I added a meta refresh to another download in this page.  Below is the edited HTML using Charles Proxy but clearly any man-in-the-middle attacker could do the same thing. 



The result of this is an arbitrary file being pushed to you at the time you are trying to update.  I personally think this could be convincing enough to get people to run malicious code.  An attacker could also edit the HTML directly to make it seem like you should click a button in the untrusted frame instead of the "Get the New Version" button or be even more creative.



I think it is important for software vendors like Mozilla to keep these kinds of attacks in mind when mixing application chrome and untrusted content in the same view.  It is important for us to think of the barely computer literate user who is just trying to safely browse the web.  I'm pretty sure more badness could be done with this, and the fix is relatively simple -- all they needed to do was serve this over SSL and the threat would be greatly reduced.

Monday, March 21, 2011

Apple fixes Installer bug, CVE-2011-0190


Mac OS X v10.6.7 addressed a bug I reported in Installer:
From Apple's advisory: 
Impact: Visiting a maliciously crafted website may lead to the installation of an agent that contacts an arbitrary server when the user logs in, and mislead the user into thinking that the connection is with Apple
Description: A URL processing issue in Install Helper may lead to the installation of an agent that contacts an arbitrary server when the user logs in. The dialog resulting from a connection failure may lead the user to believe that the connection was attempted with Apple. This issue is addressed by removing Install Helper.

Some additional details:
- A web page could open a url with the x-mini-installer:// scheme, with a host and path of where to attempt to load files.
- It attempts to download a plist pointing it at an update server at every login
- When an update package fails to process properly, the UI displayed instructs a user to run something from their ~/Downloads folder, where a malicious file could have been dropped.
- I did not succeed in getting it to automate the install of arbitrary content.  
- This bug could be used to trigger this format string bug

Friday, March 18, 2011

Quick note on LWP and Perl security - CVE-2011-0633

As a follow-up to this post on how most LWP-based scripts can be man-in-the-middled, I contacted Jesse Vincent, Gisle Aas, and the Perl security team about this LWP issue.  They immediately saw the issue and began fixing it.  I would strongly recommend using LWP 6.00 for anything that needs to handle an HTTPS URL.
CVE-2011-0633 
The libwww−perl (LWP) module Net::HTTPS did not fully validate SSL certificates by default prior to version 6.00. Multiple Perl modules (such as WWW::Mechanize and LWP::UserAgent) do not enable full validation of SSL certificates when using libwww-perl, leaving software that uses them vulnerable to man-in-the-middle attacks. This issue was addressed by changing the default behavior of libwww-perl to enable full validation of SSL certificates.
The LWP 6.00 changelog includes the following about the change:
For https://... default to verified connections with require IO::Socket::SSL and Mozilla::CA modules to be installed. Old behaviour can be requested by setting the PERL_LWP_SSL_VERIFY_HOSTNAME environment variable to 0. The LWP::UserAgent got new ssl_opts method to control this as well.
Thanks to all of their hard work, lots of projects that previously did not validate certificates will begin to do so, once LWP is updated.

Wednesday, March 9, 2011

Safari Errorjacking - CVE-2011-0167

Intro:

Today's Safari update addresses a rather serious issue (CVE-2011-0167) that I found and reported to Apple.  This issue allows Javascript from any website to jump into the local zone and access any files accessible to the user running Safari.  This bug actually exists in WebKit, so other browsers could be affected.  This is why it's good when browsers do what Chrome did, and heavily limit what can be done by local HTML. . Check out the related reading at the end of this post for more on that.

Here's a quick video of the bug in action.  Only HTML and JavaScript are required to accomplish this.






Bug description:

The problem is that when internally generated pages (such as error pages) are loaded, they are loaded from the local "file:" zone, but the window's location can still be set by all scripts that have a reference to the window, such as an attacker's website.

Why remote-to-local matters:

Safari normally blocks loading of local content from remote sites for a ton of reasons.  One reason is that local content in Safari has a fair bit of power*, including the ability to read any file accessible to the current user.  This can be accomplished a number of ways.  The easiest is using XMLHttpRequest()s in order to read files by "file:///" URL.  Once loaded, the content can be sent anywhere.  

*To read about the many other things that local HTML can do, check out the related reading links below.

How remote-to-local restrictions normally work:

You can see remote-to-local restrictions in action by trying to load the following HTML from a web server in Safari:


Click on the link and you will get the following error in the Javascript console:

Not allowed to load local resource: file:///tmp/foo.html

Sometimes remote-to-remote turns into remote-to-local:

I noticed something interesting occurs when trying to load a web page that doesn't exist, cannot be reached, or any other action that results in an internally generated page being displayed.  The page is loaded from a file on disk  and the current window location points at a "file:///" URL.  For example, execute the following javascript from a web page:

var x = window.open("http://www.thisisamadeupdomain4321.com:9876","bogusWin")

After the page load fails, the Safari error page is displayed:



Because of how Safari displays its error pages, we now have a window in the local "file:///" zone, but triggered by a load of an "http://" URL.  

Exploiting this behavior:

The vulnerability exists in the fact that this window, with full access to the "file:///" URLs, can be navigated by its parent window, when it should be blocked by a security check.  We can navigate this child window by setting x.window.location, and can set it to any URL including those in "file:///".  All we need in order to exploit it is some malicious HTML to point at using a "file:///" URL.  

There are numerous ways to get a local path to point at remotely originating payload content.  It's a little silly, but here's what I did.  This proved to be reliable enough for a proof of concept that works with the default configuration of Safari on Mac OS X:

1. When you launch the proof of concept by clicking the submit button on thing.html, we start by mounting a disk image with our local payload
2. If you have the default Safari settings, Mac OS X will mount the disk image in /Volumes/poc
3. We then attempt to load http://127.0.0.1:7/ in a new window.  Since port 7 (tcp echo) is on the port block list, an error page in the "file://" zone is loaded
4. We then tell the window that is displaying this error page that it should load a different file, /Volumes/poc/ds.html.  The fact that we can do this is the bug itself
5. Safari loads the Javascript in ds.html in the local zone.  The Javascript opens a SQLite3 file, /var/db/dslocal/indices/Default/index, because it contains the names of local users
6. We use Javascript to rip some usersnames from the SQLite3 database file using a regular expression, and then attempt to access the target file in each of their accounts
7. File contents (if we have the right user) and usernames are communicated back to the parent window using postMessage (direct communications between the windows)

Some questions and answers about this bug:

1. Does the pop-up blocker stop this bug? 
No.

2. What if I changed my preferences so that 'Open "safe" files' is not selected? Am I safe against this?
No.  The slightly more technical explanation for this answer is that my proof of concept is using a disk image just to get malicious content at a known local path.  There are a lot of other ways to accomplish this task.  For example, my original proof of concept used an "ftp://" URL, and triggered Finder.app to automatically mount the site in /Volumes.  I felt like setting up a public FTP server was a bit of a hassle so I switched to this easy and portable version.  There are also less obvious ways to do this, including methods that involve no user-visible clues that a malicious file is now accessible through a "file://" path.

3. Will the Mac OS X file quarantine feature stop this exploit?
No. While we're using a disk image that came from Safari and this file is therefore quarantined, we are not launching our payload.  Instead we are loading it from an active HTML document that has already been loaded into the "file://" zone.

4. Your proof of concept did not work for me. Does that mean I am not vulnerable?
No. In the proof of concept I'm basically grepping a binary SQLite3 database file with Javascript. I am going to assume this isn't a terribly portable way of grabbing usernames.  There are a bunch of other ways we could get the username of our visitor.  For example, my original version of this proof of concept used a rather simple method of gathering usernames by parsing monthly.out.  The monthly.out file is generated once a month and contains active usernames as part of system accounting.  I got annoyed that my proof of concept wouldn't work on a fresh system, so I switched to the new method.  Here's how I was grabbing usernames from the monthly.out file:

                function process_log(monthlog) {
                 var gathered_users=new Array();
                 var line_pos = 0;
                 var in_block = 0;
                 var month_lines = monthlog.split("\n");
                 for (line_pos=0;line_pos<=month_lines.length-1;line_pos++) {
                  if (month_lines[line_pos] == "Doing login accounting:") {
                        in_block=1;
                  } else if (in_block==1 && month_lines[line_pos] == "") {
                        in_block=0;
                  } else if (in_block) {
                        var user_line = month_lines[line_pos].split(/[\t ]/);
                        if (user_line[1].length>0 && user_line[1] != "total") {
                                // user_line[1] is a potential username
                                gathered_users[user_line[1]]=1;
                        }
                  }
                 }
                 var victim = "";
                 for (victim in gathered_users) {
                                do_something_bad(victim);
                 }
                }

[Note: I apologize about how gross that Javascript is, but I figured someone might have a use for it. You can replace the proof of concept i posted to use this one pretty easily.]

5. Will this work on Windows?
Good question.  I suspect that it will, and that using a UNC path you might be able to point at remote files for your payload.  However I have not had a chance to test this.  If you have a test system and a moment to port this to Windows, I'd appreciate it if you would post a comment.  I'd also like to know if you can launch programs from this local window by using document.location or by loading a JAR in the "file://" zone.  That could be interesting.

6. Is Safari the only browser affected?
No. Safari is the only browser that this proof of concept was designed to work with, but the bug itself is in WebKit and affects other WebKit-based browsers.  If you are testing your WebKit-based browser, remember that if you use a different URL scheme for things like these error pages, you may need to modify the test case to attempt to access resources using that scheme instead of "file://".

The proof-of-concept:

You should be able to uudecode this into a zip, that is ready to be dropped in a path
in your web server.


Thanks:

I would like to thank Cedric of the Apple Product Security team for the responsive and responsible handling of this issue.
I would also like to thank the Google Security Team for putting in the effort to harden WebKit against many of these issues and protect their users.
Also, thanks cstone.

Related reading:

Excellent work by the Google/Chrome guys:

This bug:
 Apple's advisory page, see CVE-2011-0167 in the latest Safari update

I found this bug a while ago -- before the following blog post was written, but I think people who find this kind of bug interesting would also be interested in lcamtuf's blog post:

Wednesday, February 2, 2011

Skype 5.0 Fixes Autodial and No-UI-dial Vulnerabilities

Well, it seems like Skype didn't bother to tell anyone to update to 5.0 for security reasons.  I've been waiting for this release patiently, for months and months, since I reported this bug to them.  Now that it is fixed, I'll disclose the bug myself.  It seems like Skype has a poor excuse for a security response team, though.  From people I have talked to, it seems like you cannot trust them to get back to security researchers, credit them for their findings, or disclose the vulnerabilities to their users.  This is bad for Skype and bad for Skype's users.

The first bug was really blatant: Any web page could cause you to dial a phone number by using Javascript to launch a 'callto:' URL.  This was tested on Safari.  This meant disclosure of your Skype name, along with unattended computers serving as audio bugs.  Imagine how easy it would be to make a web page that attempts to launch a callto:temporary_skype_name_that_was_made_up_for_attacking_people after a predetermined period of inactivity.  You could record everything going on at someone's house.

The second bug was weird: A callto: based call could be made such that even after you attempted to cancel it, it would remain in progress but with no UI.  You'd need to quit Skype in order to make it end.  This was tested on Skype prior to version 5.0 on the Mac.  To do it, you just need to dial using the recipients number twice.  For example, to call 5551212, you would use: callto://5551212&5551212

I found out that Skype 5.0 was released because I manually checked.  I don't think that most user's do this on a regular basis.  I bet there are a lot of people out there who are vulnerable to these issues.

Nitesh Dhanjani found a bug similar to this on the iPhone.  More information on his bug is available at [link].

Friday, January 28, 2011

1Password 3.5.4 addresses MITM Cookie Disclosure Issue

The 1Password update 3.5.4, released on January 28th, 2011, changelogs included the following note:
>> Updated thumbnail downloader to turn off default cookie operations and prevent fetching previews from sites with bad certificates.
This may not seem like a big thing, but it should be to 1Password users.  Prior to version 3.5.4, if a man in the middle attacker posed as a secure site that 1Password had a stored login to, the lack of certificate validation would allow cookies stored by Safari, and other applications like 1Password Agent that use the default cookie store to be leaked to attackers.
Your web browser normally warns you before connecting to a site with a bad SSL certificate, because there is danger in disclosing GET request arguments and Cookies to impostor websites. However, 1Password's agent did not fail as it should when encountering a bad certificate, even if the site had a valid certificate when you saved your login.  When 1Password Agent made requests, it did so with the default cookie store. This means that session cookies and other sensitive cookies could be leaked to any site that posed as a secure site you login to whenever 1Password Agent attempted to store or update a thumbnail image of the site.
This issue was addressed in the 3.5.4 release of 1Password by no longer allowing 1Password Agent to connect to sites with bad certificates.
The Agile Web Solutions team fixed this bug very quickly after I notified them of the issue and should be commended for their quick response. They responded to this issue within 1 hour (wow!), and had a fix available to the public within 2 weeks. Given that I reported this over new years, thats incredibly impressive. Good job guys!
1Password users should update to the latest version so they are no longer vulnerable to this attack.