Archive for February 24, 2017

Friday, February 24, 2017

Cloudbleed: Cloudflare’s HTTPS Traffic Leak

Tavis Ormandy (via Hacker News):

On February 17th 2017, I was working on a corpus distillation project, when I encountered some data that didn’t match what I had been expecting. It’s not unusual to find garbage, corrupt data, mislabeled data or just crazy non-conforming data...but the format of the data this time was confusing enough that I spent some time trying to debug what had gone wrong, wondering if it was a bug in my code. In fact, the data was bizarre enough that some colleagues around the Project Zero office even got intrigued.

It became clear after a while we were looking at chunks of uninitialized memory interspersed with valid data. The program that this uninitialized data was coming from just happened to have the data I wanted in memory at the time. That solved the mystery, but some of the nearby memory had strings and objects that really seemed like they could be from a reverse proxy operated by cloudflare - a major cdn service.

Cloudflare:

It turned out that in some unusual circumstances, which I’ll detail below, our edge servers were running past the end of a buffer and returning memory that contained private information such as HTTP cookies, authentication tokens, HTTP POST bodies, and other sensitive data. And some of that data had been cached by search engines.

[…]

It turned out that the underlying bug that caused the memory leak had been present in our Ragel-based parser for many years but no memory was leaked because of the way the internal NGINX buffers were used. Introducing cf-html subtly changed the buffering which enabled the leakage even though there were no problems in cf-html itself.

Once we knew that the bug was being caused by the activation of cf-html (but before we knew why) we disabled the three features that caused it to be used. Every feature Cloudflare ships has a corresponding feature flag, which we call a ‘global kill’. We activated the Email Obfuscation global kill 47 minutes after receiving details of the problem and the Automatic HTTPS Rewrites global kill 3h05m later. The Email Obfuscation feature had been changed on February 13 and was the primary cause of the leaked memory, thus disabling it quickly stopped almost all memory leaks.

Adam Clark Estes:

You might not be familiar with Cloudflare itself, but the company’s technology is running on a lot of your favorite websites. Cloudflare describes itself as a “web performance and security company.” Originally an app for tracking down the source of spam, the company now offers a whole menu of products to websites, including performance-based services like content delivery services; reliability-focused offerings like domain name server (DNS) services; and security services like protection against direct denial of service (DDoS) attacks.

Jeff Johnson:

The scandal is not that Cloudflare exposed private info. The scandal is that Cloudflare has access to private info.

Nobody should ever use a third-party HTTPS proxy. You might as well not even use HTTPS. That’s not end-to-end encryption.

1Password’s hosted service uses Cloudflare, but it does use end-to-end encryption:

No secrets are transmitted between 1Password clients and 1Password.com when you sign in and use the service. Our sign-in uses SRP, which means that server and client prove their identity to each other without transmitting any secrets. This means that users of 1Password do not need to change their Master Passwords.

Your actual data is encrypted with three layers (including SSL/TLS), and the other two layers remain secure even if the secrecy of an SSL/TLS channel is compromised.

Dropbox and ChronoSync rely on HTTPS, only encrypting the user data after it gets to the server.

See also: this list of affected sites (via Hacker News).

iOS 10.2.1 Update Reduces Unexpected Shutdowns

Juli Clover:

For the last several months, iPhone 6, 6s, 6 Plus, and 6s Plus users have been dealing with a problem that causes their devices to unexpectedly shut down, an issue that Apple now says it has successfully addressed in the latest iOS 10.2.1 update, released to the public on January 23.

In a statement provided to TechCrunch, Apple says that the iOS 10.2.1 update has resulted in an 80 percent reduction of unexpected shutdowns on the iPhone 6s and a 70 percent reduction of unexpected shutdowns on the iPhone 6.

There’s still something going on. After updating to iOS 10.2.1, I went skiing and within two hours (during which all I did was take one photo) my iPhone went from 100% battery (charged in the car) to unable to turn on. After plugging it in to charge for a few minutes, it booted but showed nearly zero battery.

Previously: Apple’s Support Gap.

Let Your Swift XCTest Methods Throw

Brian King:

One place where the XCTest assertion utilities fall a bit short has been with managing Optional variables in Swift. XCTAssertNotNil doesn’t provide any mechanism for unwrapping variables, easily leading to assertion checks like this[…]

[…]

A nice solution is possible, due to an often-overlooked feature of XCTestCase. If the test function is marked with throws, any thrown exception will cause the test to fail. We can use this to fail our tests using normal Swift flow control mechanisms[…]

Unit tests are much more pleasant to read and write if you can get rid of the clutter. There are two key ways that I do this. First, I have an MJTTestCase subclass with convenience methods that wrap the XCTAssert functions. My methods have obscenely short names. For example, XCTAssertTrue() becomes t() and XCTAssertEqual() becomes eq(). Swift’s support for unnamed parameters and overrides really helps here. These are not features that I use much in regular code, but they really come in handy with tests, where there are a small number of methods that are called many times, and I want the focus to be on the parameters rather than the methods themselves.

Second, as King describes, I take advantage of the fact that test methods are now allowed to throw. This is so much better than force unwrapping. My equivalent to his AssertNotNilAndUnwrap() is called unwrap(). It avoids having to write lots of guard statements, either returning the value in the optional or failing the test. If the test fails, it throws, which is how the return type can be T instead of T?. I also have variants like unwrapString(), which also do an as? to check the type.

The same technique works for checking errors. I have ok(), which takes an expression that can throw and fails the test (collecting the line number and error) if it does. If it succeeds, the return value is available for use. I also have e(), which makes sure that an NSError was thrown and returns it so that it can be inspected with further assertions. The XCTest equivalent is XCTAssertThrowsError(), which wants you to pass in an error handler closure. The closure has a number of drawbacks: it causes extra boilerplate and indentation, the closure’s body doesn’t auto-indent properly due to an Xcode bug, and my subclass convenience methods must be accessed through self. Instead, I can simply write:

let error = try e(codeThatShouldThrow())
eq(error.code, NSFileNoSuchFileError)

Previously: Proposal: XCTest Support for Swift Error Handling.

Update (2017-03-05): By request, here’s the source for my unwrap():

func unwrap<T>(_ value: T?, file: StaticString = #file, line: UInt = #line) throws -> T {
    guard let value = value else {
        fail("Unwrapped nil instead of \(T.self)", file: file, line: line)
        throw ExpectedNotNilError()
    }
    return value
}

Update (2019-10-13): Xcode 11 now includes its own XCTUnwrap (via Bas Broek).

Adventures in Siri Failures: Reminders Edition

Dan Moren:

Now, I use Siri to add stuff to my Shopping List in Reminders all the time, and that generally works fine. But for some reason when I tried to do the same thing here, I kept getting the same error: “Sorry, I can’t add that to your library. You don’t seem to be subscribed to Apple Music.”

This is infuriating, for a few reasons. First: What the hell about this query even remotely suggests that I’m trying to do anything with music? Secondly, I’m not subscribed to Apple Music, so why is that lack of a subscription interfering with something I legitimately want to do? It ticks me off to no end that a feature I don’t even use is interfering with something I want to accomplish.

Also, as I keep saying, Siri seems to be much better at turning speech into text than it is at acting on that text. So why isn’t there a way to make a reminder without having it try (and fail) to interpret the text within that reminder? Put another way, it’s frustrating that it can nail the hard part, but then it throws away the results (and my utterances) because it was reading too much into what should have been the easy part.

Previously: Apple Pushes iPhone 6s Pop-up Ads to App Store.