Categories
iOS Security Uncategorized

Reverse Engineering the DirecTV App’s DVR Authentication

Disclaimer: The work below was done nearly a year ago. I have no way to test to see if the information is still accurate. I’m guessing it is, but if you’re able to check and see, feel free to let me know if you still get the same results I did.

A while back a friend came to me and they were interested in writing their own mobile app to control their DirecTV DVR. DirecTV already had its own mobile app, but this person wanted to be able to customize some of the behavior. The existing app gave us a good starting point to try and see how to communicate with the DVR.

The first place to start was to inspect the local network traffic between the mobile app and DVR. Any proxying tool should work; I went with Charles Proxy. When doing this, we observed an interesting pattern with the traffic. Every time the app sent a request to the server, the server would respond 401 Unauthorized. The app would then send a second request, identical to the first, but this time with an Authorization header. The server would accept this second request and respond. This wouldn’t just happen once at the beginning of a session. Every single request would get a 401 the first time, then would be resent with Authorization headers.

Inspecting the server’s 401 response, it contained a WWW-Authenticate header which included four keys: realm, Qop, Nonce, and Opaque. A quick online search of these keys revealed that the server seemed to be issuing a digest authentication challenge.

A digest authentication challenge is part of digest access authentication; an authentication method that can be used with web servers. The way digest authentication works is that the client and server each know a pre-shared secret (a password). When the server responds to a client with a digest authentication challenge, it’s telling the client how to authenticate itself. The client will generate two strings:

string1 = md5(username:realm:password)
string2 = md5(method:digestURI)

These two strings are then used by the client to generate the authentication response:

response=md5(string1:nonce:nonceCount:cnonce:qop:string2)

If we wanted to talk to this DVR server, we needed to figure out how to authenticate ourselves. In order to authenticate our response we needed a username, realm, password, method, digestURI, nonce, nonceCount, cnonce, and qop.

As mentioned above, the server’s challenge response gave us the realm, qop, and nonce. From the client’s plaintext HTTP response we were also able to obtain the username (c0pi10t), method (GET), and digestURI (path in the requested URL).

This left us still needing the password, nonceCount and cnonce. The cnonce is an arbitrary value chosen by the client (us!) and the nonceCount can just always be 00000001. So really all that was left was the password. The password is the very thing that makes digest authentication secure. The client and server ship with the shared password known to both of them, so they never have to transmit it over the wire.

In order to obtain the password, one option was to try brute force. Digest authentication is used with SIP, for which a couple of brute forcing tools already exist. However, if the password being used is sufficiently complex, brute force is impractical. I took an existing tool and tweaked it a bit to at least start a brute force script while working on some other ideas.

While that ran, I attempted to inspect the application binary itself. Sometimes developers do silly things and leave files around with interesting information, store secret values in insecure places, or don’t bother to obfuscate strings in their binary. Knowing the username gave me a known value to search for. Unfortunately, cursory searches didn’t reveal any clues inside the binary and couldn’t even find a match for our username, so they seemed to at least be doing something to obfuscate the strings in the application binary.

I also decided to start skimming through the digest access authentication RFC (RFC 2069). Looking through the table of contents, one section immediately jumped out: Security Considerations. This section covered some of the benefits that digest access authentication has over basic auth, as well as possible attacks.

Section 3.3 – Man in the Middle – A simple but effective attack would be to replace the Digest challenge with a Basic challenge to spoof the client into revealing their password.

https://tools.ietf.org/html/rfc2069

The RFC also goes on to explain how this could be combatted. The developers are likely to have coded the client to only respond to digest authentication challenges, and ignore challenges asking for basic auth. The client knows that the server will be using digest authentication and there’s no reason it should accept basic auth as a challenge, especially when an RFC that’s over 20 years old clearly outlines this attack. But it never hurts to try.

Once again using Charles Proxy, when the client tried an unauthenticated request and the server responds with a digest challenge, we modified the response to have a “WWW-Authenticate: Basic” header, indicating to the client that it should authenticate itself with Basic auth (base64 encoded username and password).

When we tried this, much to our surprise, the client actually responded to our spoofed request with Basic Auth. It’s a base64, colon-delimited string, which decoded gives us: c0pi10t:8th5Bre$Wrus. We already had the username (the first part), and now we also had the password.

At this point the door is pretty wide open for writing our own client that can talk to the DirecTV DVR. We have all the pieces we need to authenticate all of our requests to the DVR so that it believes it’s talking to the official DirecTV mobile app. And not just this specific DVR, but any DirecTV DVR that’s capable of working with the mobile app. Based on my (very novice) understanding of digest access authentication, the password must be the same for any DVRs that want to work with the mobile app.

Categories
iOS Networking Tools

Trusting Custom Root Certificates on iOS 10.3

TL;DR: Navigate to Settings > General > About > Certificate Trust Settings and turn the switch on for your custom certificate.

Like many, Charles Proxy has become an indispensable part of my daily toolkit. Every person on my QA team uses it daily for their projects. Recently while testing on iOS 10.3, one of my team members couldn’t get his SSL traffic to proxy. Usually when somebody runs into this, it’s because the person hasn’t installed the Charles Proxy root certificate on the device they’re trying to proxy. Then why you try to proxy SSL traffic in Charles you’ll the following error: SSLHandshake: Received fatal alert: unknown_ca

Charles Proxy will even offer a helpful suggestion:

You may need to configure your browser or application to trust the Charles Root Certificate. See SSL Proxying in the Help menu.

iOS is refusing the SSL handshake because the certificate authority that has issued the SSL certificate being used is not in its Trust Store. Previously to resolve this, we would just need to go to http://ssl.charles in Safari on the device, and we could then install the root CA from Charles and tell the device we want to trust it. In this case, the QA person had already taken these steps. After some digging around, he found the problem. Settings > General > About > Certificate Trust Testings

The Charles Proxy Custom Root Certificate that he had installed showed up in the list, but its toggle was turned off. While this section existed prior to iOS 10.3, by default when you would install a custom certificate, iOS would implicitly trust it. No further action required. As of iOS 10.3, the default for new custom certificates is to not trust them. If you want to trust the custom certificate you’ve installed (why else would you have installed it?), you’ll need to navigate to the section mentioned above and manually turn the switch on to trust the certificate. Any certificates installed and trusted prior to iOS 10.3 seem to be grandfathered in, so you won’t run into this until you’re trying to use a new root certificate.

Categories
iOS Networking Privacy Security

Network Security Changes Coming to iOS

Changes to App Transport Security

Last year, with iOS 9, Apple introduced App Transport Security; an enforcement of best practices for encrypted networking. By default, App Transport security requires the following:

  • NSURLSession and NSURLConnection traffic be encrypted
  • AES-128 or better and SHA-2 used for certificates
  • TLS v1.2 or higher
  • Perfect forward secrecy
In other words, it requires that your app keep your users’ network traffic reasonably protected.

While enabled by default in iOS 9, Apple recognized that may developers don’t control their backends, and included the ability to set exceptions for App Transport Security. The problem is many developers went right for the NSAllowsArbitraryLoads key, which disables ATS entirely, then never bothered to re-visit their configuration to get everything working nice and securely.

Last week, at WWDC 2016, Apple announced that beginning January 1, 2017, App Transport Security will be required (this topic starts about 1m20s into the What’s New In Security session). You should really watch the talk for the exact details from Apple, but in short, all of your app’s traffic needs to be secured with HTTPS and will need to use TLS v1.2 or higher.

Apple will still allow some exceptions, but the rules will be much less relaxed than they have been:

  • Most exceptions will now need to be justified to Apple. NSAllowsArbitraryLoads, NSExceptionAllowsInsecureHTTPLoads, and NSExceptionMinimumTLSVersion will all require a reasonable justification for use.
  • NSExceptionRequiresForwardSecrecy will not require a justification for now. If used, this exception will be granted automatic approval. Presumably this will change down the road as forward secrecy becomes more widely spread.
  • Streaming media using AVFoundation is exempt, but Apple says you should still encrypt with TLS if possible.
  • Content loaded inside of WKWebView does not have to be encrypted. This requires specifying the NSAllowsArbitraryLoadsInWebContent key as true in your Info.plist.
  • Data that is already encrypted does not have to go over HTTPS.
The specific example Apple uses in the talk for still needing exceptions is communicating with a third-party server where you can’t control their cipher suites. Even if this is your situation, it sounds like needing to justify exceptions may slow review time, so it’s probably worth talking to any third parties you work with to ensure they can meet ATS requirements.

If the reason you haven’t supported ATS yet is because it seemed like too much work, now’s the time to start making changes. One of the difficulties you may face implementing ATS is diagnosing failures. On the surface, you’ll likely just see data fail to load in your app with no real indication as to why. What I’ve found most useful is the nscurl --ats-diagnostics https://example.com command. It will test different ATS configurations against the specified domain and report back showing which scenarios pass and which fail. The failed scenarios will make it much more clear what you need to change on your server to support ATS. Tim Ekl has some more helpful info about debugging in this blog post on ATS from last year.

If the reason you don’t yet support ATS is the cost or difficulty of getting set up with SSL certificates, be sure to check out the Let’s Encrypt project. Let’s Encrypt is a free, automated Certificate Authority that operates with support from a large number of sponsors such as Mozilla, the EFF, Chrome, and Cisco.

Certificate Transparency

Certificate Transparency is a standard for monitoring and auditing certificates (TLS certificates in this case). Its purpose is to help protect against fraudulently issued certificates. Last year when Apple went over App Transport Security, they also briefly covered the ability to require certificate transparency in apps using the NSRequiresCertificateTransparency key, though they said this functionality was off by default.

This year, certificate transparency is still not required, but Lucia Ballard spent several minutes discussing it in the same What’s New in Security session, announcing that Apple is “joining the effort for certificate transparency”. She also took some time to cover OCSP stapling—a method for checking to see if a certificate has been revoked—and presents it as a recommended practice. I think the verbiage used around Certificate Transparency and OCSP stapling is noteworthy. I’ll include the text of two quotes from the session here for your consideration:

We think now is the time for folks to move to it and start adopting [OCSP stapling].

And later:

It would be a great time to start experimenting with certificate transparency, find certificate authorities that are participating, and get integrated into this ecosystem. And please go enable OCSP stapling.

I strongly encourage everybody to go watch, at a minimum, the certificate transparency portion of the What’s New in Security session from WWDC 2016. It’s less than 10 minutes long, starting at 7m55s and ending at 16m00s (though really you should watch the entire session). The speaker gives a great overview of both Certificate Transparency and OCSP stapling. They also recommend certificate-transparency.org as a developer resource on the subject.

Updating your apps

Your first priority should be to get your app ATS compliant before the January 1st deadline. Really you should start now because many developers are going to encounter obstacles in doing so. Don’t procrastinate.

Once you have ATS working, it seems like it will be worth your time to start getting familiar with certificate transparency and OCSP stapling. Not only will this benefit the security of your users, but it may make your life easier down the road should Apple choose to encourage its adoption more strongly.

Categories
iOS Mac Privacy Security

Working with Apple’s App Transport Security

Update 6/23/15: Apple now has official documentation for App Transport Security.

With iOS 9 and OS X El Capitan, Apple has introduced App Transport Security. In a nutshell, App Transport Security enforces best practices for secure network connections — notably, TLS 1.2 and forward secrecy. In the future, Apple will also update these best practices to ensure they always reflect the latest security practices that will keep network data secure.

App Transport Security is enabled by default when using NSURLSession, NSURLConnection, or CFURL in iOS 9 or OS X El Capitan. Unfortunately for many developers this may mean that things break as soon as they build for iOS 9 or OS X 10.10. Fortunately Apple offers some configuration options to leverage App Transport Security where possible, while disabling it in places where you cannot support it.

You can opt-out of ATS for certain URLs in your Info.plist by using NSExceptionDomains. Within the NSExceptionDomains dictionary you can explicitly define URLs that you need exceptions for with ATS. The exceptions you can use are: NSIncludesSubdomains
NSExceptionAllowsInsecureHTTPLoads
NSExceptionRequiresForwardSecrecy
NSExceptionMinimumTLSVersion
NSThirdPartyExceptionAllowsInsecureHTTPLoads
NSThirdPartyExceptionMinimumTLSVersion
NSThirdPartyExceptionRequiresForwardSecrecy
Each of these keys allows you to granularly disable ATS or particular ATS options on domains where you are unable to support them.

Sample ATS plist

In the first beta of iOS 9, these keys are incorrect and instead you’ll need to use the following: NSTemporaryExceptionAllowsInsecureHTTPLoads
NSTemporaryExceptionRequiresForwardSecrecy
NSTemporaryExceptionMinimumTLSVersion
NSTemporaryThirdPartyExceptionAllowsInsecureHTTPLoads
NSTemporaryThirdPartyExceptionMinimumTLSVersion
NSTemporaryThirdPartyExceptionRequiresForwardSecrecy

These keys will undoubtedly be fixed in a future seed. If you can, you should use the first set of keys above that Apple is officially supporting, though if you’re using the temporary keys, they should continue to work in future betas. Thanks to Juan Leon for bringing this to my attention—I was told the same in the labs.

Below are examples of different scenarios developers may encounter.

Example A: ATS for all

This is the easiest one. The only thing you need to do is use NSURLSession, NSURLConnection, or CFURL. If you’re targeting iOS 9 or OS X El Capitan or later, ATS’s best practices will apply to all of your NSURLSession, NSURLConnection, and CFURL traffic.

Example B: ATS for all, with some exceptions

If you expect all of your domains to work with ATS, except a few that you know will not work, you can specify exceptions for where ATS should not be use, while leaving all other traffic opted in. For this scenario, you’ll want to use an NSExceptionDomains to specify the domains for which you wish to override ATS’s default settings. To opt-out an entire domain or sub-domain, create a dictionary for the URL you want to opt-out of ATS, then set NSExceptionAllowsInsecureHTTPLoadsto true. You can also specify more specific rules you wish to override with NSExceptionRequiresForwardSecrecy and NSExceptionMinimumTLSVersion if you don’t want to completely disable ATS on those domains.

ATS for All

Example C: ATS disabled, with some exceptions

Conversely, you may only want ATS to work on domains you specifically know can support it. For example, if you develop a Twitter client, there will be countless URLs you may want to load that may not be able to support ATS, though you would want things like login calls, and other requests to Twitter to use ATS. In this case you can disable ATS as your default, then specify URL which you do wish to use ATS.

In this case you should set NSAllowsArbitraryLoads to true, then define the URLs that you want to be secure in your NSExceptionDomains dictionary. Each domain you wish to be secure should have its own dictionary, and the NSExceptionAllowsInsecureHTTPLoads for that dictionary should be set to false.

ATS Disabled with Exceptions

Example D: Downgraded ATS

In some cases you may want ATS on all, or some, or your URLs, but are not ready to fully support all of ATS’s best practices. Perhaps your servers support TLS1.2, but don’t yet support forward secrecy. Rather than completely disabling ATS on the affected domains, you can leave ATS enabled, but disable forward secrecy. In this scenario you would create an NSExceptionDomains dictionary, a dictionary entry for each domain you need to override settings for, then set the NSExceptionRequiresForwardSecrecy value to false. Similarly, if you wish to have forward secrecy enabled, but need the minimum TLS version to be lower, you can define your supported TLS version with the NSExceptionMinimumTLSVersion key.

Downgraded ATS

Example E: NSA-friendly Mode

If you want to opt-out of ATS entirely (which you really shouldn’t do unless you fully understand the implications), you can simply set NSAllowsArbitraryLoads to true in your Info.plist.

NSA-friendly Mode

Third-party keys

You may have noticed a few keys that appear to be duplicates of others keys with the addition of “ThirdParty” in the name. NSThirdPartyExceptionAllowsInsecureHTTPLoads
NSThirdPartyExceptionMinimumTLSVersion
NSThirdPartyExceptionRequiresForwardSecrecy
Functionally these keys will have the same result as the keys that don’t have “ThirdParty” in them. The actual code being invoked behind the scenes will be identical regardless of whether you use the ThirdParty keys or not. You should probably use whichever key best fits your exceptions, but no need to overthink it.

Certificate Transparency

While most security features for ATS are enabled by default, certificate transparency is one you must opt-in to. If you have certificates which support certificate transparency, you can enable certificate transparency checks with the NSRequiresCertificateTransparency key. Again, if your certificates don’t yet support certificate transparency, by default this check will be disabled.

If you need help debugging issues that arise from having App Transport Security enabled, setting CFNETWORK_DIAGNOSTICS to 1 will log all NSURLSession errors including the URL that was called and the ATS error that resulted. Be sure to file radars for any issues you encounter so that ATS can be improved and flexibility expanded.

All of the above information was provided in Apple’s Networking with NSURLSession session at WWDC 2015. Finally, Apple emphasized in the talk to report any issues that you run into and keep any eye out for any changes that may be coming in future betas.

Categories
iOS Mac Privacy Security

Security & Privacy Changes in iOS 8 and OS X Yosemite

I’ve been sifting through this year’s WWDC videos looking for all of the interesting bits around security & privacy. I’m not anywhere close to being done. Fortunately Luis Abreu has done the hard work for all of us and compiled his findings into a very handy post. The post has a lot of great info for developers, QA, and designers around what’s new and what’s changing. Of course you’ll still want to go do your own research before implementing any changes, but Luis’ post serves as a great quick-start guide.

Link: lmjabreu.com
Source: iOS Dev Weekly

Categories
iOS Tools

What Developers Should Know About Apple’s TestFlight

When Apple acquired Burstly, makers of TestFlight, earlier this year, many were hopeful that Apple was finally ready to provide developers with an easy way to manage beta testing. So naturally, developers responded to Apple’s official announcement of the (re)launch of TestFlight at WWDC with great applause. Since then, many (including Apple) have rejoiced that the days of dealing with UDIDs and provisioning profiles are over. Many already believe that TestFlight spells the end for HockeyApp. But looking at what we know so far about TestFlight, I’m not so sure that’s the case.

The Promise

TestFlight will bring two big changes to ad hoc app distribution as we know it. First, test devices are now managed using email addresses, rather than UDIDs. Second, the test device limit was drastically increased from 100 devices per account to 1,000 users per app. Many developers have been frustrated for some time now with Apple’s 100 device limit, and this has only gotten worse over the years with more new devices being released. The current system of UDIDs and provisioning profiles unnecessarily wastes a lot of developer time, requiring close monitoring and management of test devices and troubleshooting esoteric error messages.

With TestFlight, developers won’t need to ask testers for UDIDs anymore—they will simply send them an email invite from iTunes Connect. Once a user accepts the invite and installs the TestFlight app, they’ll be able to view details for apps, install betas, and provide feedback to developers. Developers will be able to use iTunes connect to upload builds, manage users, and even get insights into how testers are using the app. So far, so good, but here come the caveats.

Internal Testers vs. Beta Testers

TestFlight users will fall into two buckets: internal testers and beta testers. Beta testers will be the ones invited via email and, as previously mentioned, you will be able to have up to 1,000 of them per app. Internal testers will be managed in iTunes Connect by creating an account for each tester; you are limited to 25 of these. Builds for beta testers will need to be reviewed and approved by Apple before testers will have access to them, while internal testers will have access to builds as soon as they are uploaded. As others have already pointed out, reviews will only be required for the initial submission and any builds that contain major changes to the app—minor changes won’t require another review. But this is already a hurdle that developers didn’t previously have to deal with. And for many companies, 25 internal tester slots simply won’t be enough. It’s great to see Apple get rid of the 100-device limit, and for a lot of developers it may be sufficient, but for many the hassle of dealing with the 100-device limit isn’t going away, it’s just being replaced with a similarly frustrating limitation of 25 internal testers.

Supported Platforms

Not surprisingly, TestFlight is only available for iOS 8. While TestFlight originally worked on Android, that support was dropped shortly after Apple acquired Burstly and there’s no indication it will return. There also hasn’t been any mention of TestFlight supporting Mac apps (which Hockey does). So if you’re planning on making an iOS 8-only app, then you’re in good shape. But anybody supporting older iOS versions, Android, or wanting to have a Mac app will need to look elsewhere.

Build History

The demonstration shown in Apple’s iTunes Connect session seems to suggest that testers will only be able to install the latest version of a beta. When a new build is uploaded, the previous build is marked as Inactive. Most of the time this is perfectly fine, but it’s not uncommon for developers and testers to need to install previous builds of an app. You may need to go back and reproduce a bug in an old build, or go back to compare a design element that has changed, or check old builds to determine when a regression was introduced, or to test database migrations from old builds… there are plenty of perfectly valid reasons for needing the ability to install previous builds. Perhaps I’m reading into Apple’s demonstration too much, but if this winds up being the case, Hockey will be able to add this to the list of features it has over TestFlight.

Automated Builds & Continuous Integration

TestFlight builds will be uploaded and managed through iTunes Connect. Unless Apple provides command line tools for this (which there has been no hint of), any developers who use any sort of continuous integration environment for automating builds and uploads will be out of luck. Each update for testers will require a developer to manually build and upload through iTunes Connect. Obviously there are plenty of developers who currently do manual builds, and for them this won’t be a big deal. But for the many of us using CI to upload multiples builds a day, this lack of functionality alone is enough to immediately rule out moving from Hockey to TestFlight.

Crash Reporting

Another big feature that TestFlight will have is crash reporting. Apple has provided crash reporting for App Store apps for a while now, but many have found it to be lacking and utilize 3rd-party solutions instead. Apple has only mentioned TestFlight supporting crash reporting for App Store submissions, not betas. It’s better than no crash reporting at all, but it’s not a complete solution and it’s still subpar to the many 3rd-party solutions currently out there. Oh, and one more thing. Apple said that crash reporting and symbolication will be available later next year.

Support

Last but not least, let’s talk about support. Hockey won me over early on with their beyond-stellar support. I frequently receive responses to my support requests in less than 15 minutes, and at all hours of the day and night. One time I submitted a support request to find out if I could aggregate crash information in a particular way through the Hockey website, but was told it wasn’t currently possible. The next morning Hockey support sent me a Ruby script to accomplish what I wanted using their API. Apple won’t be, and likely has no interest in, providing that kind of support.

Where TestFlight Fits In

Believe it or not, I’m not trying to talk anybody out of using TestFlight. I’m quite glad to see TestFlight; I think it’s a big step in the right direction. TestFlight will be entirely sufficient for many developers’ testing needs, and the fact that those developers will be able to utilize TestFlight instead of relying on, and having to pay for a 3rd-party service, is great news. Even developers who continue to use services like Hockey to fulfill needs unmet by TestFlight will likely benefit from TestFlight. Hockey may make the most sense during development when you’re cranking out builds and rapidly iterating, but as you’re getting ready to ship to the App Store, being able to get your app into the hands of a much larger group before finally shipping to the App Store is a huge plus. The more users you have testing your app on more devices, the greater your ability to catch strange edge cases and eventually ship a more polished app. That’s not only great news for developers, it’s great news for users who easily become collateral damage of insufficient testing.

Maybe down the road Apple will expand TestFlight to compete more aggressively with Hockey. Maybe they’ll even kill off manual management of distribution profiles for good. But looking at what we know about these upcoming changes so far, TestFlight and HockeyApp are two different services that serve two very different needs. TestFlight isn’t going to kill Hockey, it’s going to complement it.

Categories
iOS

iPhone Touchscreen Accuracy – A lesson in understanding test requirements and goals

Effective problem solving requires that you fully understand the problem you’re trying to address. This holds true in life and in programming. Effective testing requires that you have a good understanding of what you are testing and why. Without this solid foundation, at a minimum you’ll cause some confusion, and often times you’ll end up wasting time, money and energy investigating problems that aren’t really problems. This week, a company called OptoFidelity provided the perfect opportunity to discuss this challenge that engineers and testers commonly face.

OptoFidelity is a technology company that, among other things, provides automated test solutions. They recently performed a number of automated tests on the iPhone 5c, iPhone 5s, and Samsung Galaxy S3. One of the tests that was carried out is meant to measure the accuracy of a touch panel. This test is performed by a robot which has an artificial finger that performs hundreds of precise taps across the entire display. The location of the tap is compared against where the device registered the tap. If the actual location and registered location are within 1mm of each other, the tap is displayed as a green dot– a pass. If the actual location and registered location differ by 1mm or more, then tap is displayed as a red dot– a failure.

Touchscreen Accuracy Test Results

The image above comes from OptoFidelity and shows the results of the test. As you can see, the Galaxy S3 performs very well in this test, only losing accuracy at the very edge of the display. The iPhones show a somewhat alarming amount of inaccuracy, with roughly 75% of the touchscreen yielding inaccurate results. The obvious conclusion to draw here is that the iPhone 5c and 5s clearly have subpar touchscreen accuracy, at least when compared to the Samsung Galaxy S3. But something sticks out about the iPhone results.

The green area for the iPhone results, where it registered taps within 1mm of the actual tap location, fall into an area that would be easily tappable with your thumb when holding your phone with your right hand. If you pick up your phone with your right hand, and try tapping with your right thumb, it’s easy to see that this area is easy to tap with a fair amount of accuracy. You’re not stretching your thumb as you would when you go for the top of the screen, or scrunching your thumb up too much like you would when trying to tap close to the right edge of the screen. You also wind up tapping with the same part of your thumb while in this area. Put more concisely, this is an area of the screen that you’re more likely to tap exactly where you mean to. So what about where the circles turn red? What’s going on there?

Let’s look at one specific red area that OptoFidelity calls out in their study– the left and right edges of the keyboard.

Keyboard Accuracy

In this image, you can see the results of the touchscreen accuracy test overlaid on the top row of the iOS keyboard. In the center, over letters like T and Y, the black circles of the robot’s tap show green dots nearly centered inside, indicating that the iPhone registered the taps very close to the center of where the tap actually took place. As you move left or right of the center, you see the dots start to shift in the same direction. As you move over to the letters E and W on the left, you see the green dot moving to the left side of the actual tap circle, and by the time you get to Q, the iPhone is now registering taps 1mm or more to the left of where the actual tap took place. The conclusion of the test indicates this is a failure in accuracy on the part of the touchscreen, but is this a failure or a feature?

Looking at the displacement of taps as you move away from the green area, there’s a definite pattern. The more you move away from the easily-tappable area, the greater the “inaccuracy” of the tap. But the inaccuracy skews in a way that would make the target slightly closer to starting position of your thumb (which is likely the most frequently used digit for tapping). As your thumb stretches out from your hand, likely positioned near the bottom of the phone, the portion of your thumb that actually comes into contact with the screen when you tap changes. Your perception of the screen also changes slightly, as when you move higher on the screen, it’s less likely that you’re viewing the screen at exactly a 90 degree angle. These are factors that this automated test does not account for. The robot doing the test is viewing its tap target at a perpendicular angle to the screen. It is also tapping at a perpendicular angle every time. This isn’t generally how people interact with their phones.

I haven’t been able to find official documentation on this, but I think this behavior is intentional compensation being done by Apple. Have you ever tried tapping on an iPad or iPhone while it’s upside-down to you, like when you’re showing something to a friend and you try tapping while they’re holding the device? It seems nearly impossible. The device never cooperates. If the iPhone is compensating for taps based on assumptions about how it is being held and interacted with, this would make total sense. If you tap on a device while it’s upside-down, not only would you not receive the benefit of the compensation, but it would be working against you. Tapping on the device, the iPhone would assume you meant to tap higher, when in reality, you’re upside down and likely already tapping higher than you mean to, resulting in you completely missing what you’re trying to tap.

Commentators across the Internet have already chimed in saying “I’ve noticed this too! I’m always tapping the wrong button!” It’s a touchscreen– you’re going to miss. If the report had revealed the opposite, that the Galaxy S3 was inaccurate, you would have had a swarm of S3 users also supporting the study, citing that they sometimes tap the wrong button or key. The bottom line is, the testing performed here bears no resemblance to real-world usage. OptoFidelity tested how closely each device maps a tap to the actual position of the tap. This accuracy would be extremely important if you had robot fingers tapping very small and close tap targets at a 90 degree angle. If you’re looking for a phone to use this way, steer clear of the iPhone. What the test didn’t show is the accuracy of taps on a device relative to a user’s intended tap target. I would not be surprised if this was exactly the sort of testing Apple did when they decided to skew the touch accuracy of their devices.

This comes up in testing all of the time. In order to properly test something, you need to understand what it is that you’re testing. If you don’t understand what you’re testing, then it’s easy to misinterpret the results. Every tester out there has filed a bug, only to have it explained to them why it’s actually the expected behavior for an app (and not in the joking “it’s not a bug, it’s a feature” kind of way). A critical part of our jobs as testers is not just reporting what something does, but asking why it behaves that way. Consider this real world example. You come across a light switch that when flipped down, the lights are on, and when flipped up, the lights are off. It could be that the switch was installed upside-down. Or it could be that it’s a three-way switch and there’s another switch elsewhere that controls the same lights. In the latter case, the behavior of the switch could not be considered a bug. Arriving at that conclusion requires an understanding of what you’re testing in order to know the expected result.

I could be completely wrong about the accuracy of the iPhone. I am not a touchscreen expert, and have no proof to show what’s going on. I am in no better position than OptoFidelity to make claims about the accuracy of the iPhone touchscreen. My point is that they should be asking questions. Testers should always ask questions. Testers and engineers should always ask questions. By asking questions and trying to look below the surface, you gain a better understanding of the problems you’re trying to solve and the original questions you were trying to answer. As developers and testers, asking questions is how we build better products and yield the best results.

Categories
iOS

360iDev 2013 – How to Break Your Apps Before I Do

I had the wonderful opportunity to speak at 360iDev this year. My talk, entitled How to Break Your Apps Before I Do, covers some of the methods and mentality of a good QA person, as well as how developers can get the most out of testing.

The conference organizers, John and Nicole Wilker, have generously decided to make the session recordings available to everybody for free this year. Those interested can check out the recording of my talk, as well as all of the other sessions.

The slide deck is also available.

Categories
iOS

iOS Testing mind map 1.2 – Now with more stuff

Nearly a year since the last refresh of the iOS testing mind map, it seemed due for an update. The changes in this version are outlined below.

  • Hardware
    • Added iPhone 5s (64-bit)
    • Added iPhone 5c
    • Removed iPhone 3G
  • Network
    • Added LTE
  • Date
    • Time Settings
      • Added 24 hour clock
  • Software
    • iOS
      • Added 7.x
  • Functionality
    • Added Motion Activity
    • Added Restrictions
      • Added Disabled Safari
      • Added No IAP password caching
      • Added Disabled Camera
    • Added Privacy
      • Added Location Services, Contacts, Calendars, Reminders, Photos, Bluetooth Sharing, Microphone, Motion Activity, and Social Networking
    • Added Push Notifications

iOS Testing Mind Map 1.2

iOS Testing Mind Map 1.2

Once again, this mind map seeks to be thorough without getting so detailed as to become unmanageable or unhelpful. The mind map is not exhaustive, but helps serve as a template that you can customize to suit the needs of your apps. Anyone wishing to modify the mind map can do so by downloading SimpleMind Free and the SMMX mind map file (you may need to right-click to save), then dragging the file onto the SimpleMind app icon in your dock. Clicking on the image above will take you to a full-resolution PNG. You can also download this zip file which contains PDF, PNG, text, OPML, MM and SMMX versions of the mind map.

Categories
iOS

Vesper Beta Collaboration

Just about every beta I’ve participated in has been set up in a way that feedback is only sent back to the developers. Vesper is my first time on a beta where a collaboration tool was set up for testers, in this case Glassboard. For those unfamiliar with Glassboard, it’s a sort of social network that allows you to create private boards for groups of people to communicate. Its lightweight structure is well-suited for private communications amongst a small group, like during a beta. Brent Simmons explained to me that this is how he has always done betas. Whether it be email, Glassboard, or some other tool, Brent has always set up a way for testers to discuss the project with one another.

Not long after the first beta release, the Vesper Glassboard began to fill with feature requests, design feedback, and general comments. It was interesting to watch all the discussion taking place around design, features, and interactions, but my specialty has always been breaking things, so that’s what I did. This took an interesting turn one night after I emailed a list of about 20 bugs I had found in my latest run through the app. Dave responded with “How about I save myself the time and just give you Lighthouse access?”

This didn’t just make things easier on him, but easier for me too. Glassboard is a great collaboration tool, but by no stretch of the imagination was it set up to be a bug tracking tool. With direct access to Lighthouse I could open tickets for bugs as I found them, rather than trying to compile a large list of items to submit at once. It also let me better detail my tickets, as well as attach photos and videos for bugs that were more difficult to explain. Lighthouse access also meant that I could make sure everything reported by testers on Glassboard got tracked. Not to mention how much easier it made it to follow up on bugs once they were fixed.

The difference between a bad app and a good app is apparent to most. The difference between a good app and a great app is much more subtle. It’s the small details that 99% of users wouldn’t consciously notice were missing if they weren’t there. It’s the one or two out-of-place pixels that will cause a slight distraction to a user’s mind, even if they never realize it. I love helping with that refinement. Producing a seamless app that allows people to forget that what they’re actually looking at is software executing thousands and thousands of lines of code in order to display a sequence of colors onto millions of pixels that make up a screen. Creating that suspension of disbelief where users interact with an app as if it’s actually made up of physical components. Q Branch wants to ship the absolute best apps that they can, and I’m thrilled and honored to be a part of that.