In-depth analysis of a PHP attack that lead to Apple information disclosure

Recently over 100,000 Apple customers were affected by an information disclosure attack on the AT&T website. Security experts blame this breach on “poorly designed software”. An analysis of the attack reveals that the hackers did indeed use a classic PHP attack, in fact the only tool used in this breach was a PHP script that enumerated all ICC-ID numbers, and launched an HTTP GET request for each ID. If an ID matched an Apple iPad subscriber, his or her email address was revealed.

The image below shows just a snippet of the information harvested by the attackers. You will notice that in this list exist many US Military and Government email addresses. This begs the question; why are users of the US Whitehouse, DARPA and army using their government email address for their iPhone subscriptions?

Sample of data stolen from AT&T website

Sample of data stolen from AT&T website

The flaw in detail

The mistake in the AT&T website software was subtle, but the results were very damaging. At the core of problem lies in a script on the AT&T website: https://dcp2.att.com/OEPClient/openPage

This script takes one parameter called “ICCID” and another, which apparently is ignored called “IMEI”. If a valid ICCID is passed, the script will respond with the email address of the ICCD subscriber. For those wondering, the ICC-ID stands for Integrated Circuit Card Identifier. It is a number that associates a SIM card with a subscriber, so every iPhone and iPad user has one. If you have an iPhone or IPad, you can find your ICC-ID number from the About screen as shown in the image below.

ICC-ID display in Apple iPhone about box

ICC-ID display in Apple iPhone about box

The script will be invoked remotely using a standard HTTP GET request, that will look something like this: https://dcp2.att.com/OEPClient/openPage?ICCID=89014103211479197174&IMEI=0

This request is legitimate, and therefore was not detected by AT&T when the breach occurred, allowing the hackers to harvest a huge number of email addresses before they announced the hack to the world.

The attack script

Goatse Security, the group behind this exploit revealed the PHP script that they used. This allowed security researchers to peek ‘behind the scenes’ and see what techniques were used.  Below is the script, titled “iPad 3G Account Slurper”.  I bolded the sections I found interesting, and which I will explain further down.

Click on script to enlarge image

This script is not a work of art (like most PHP code out there), but it does the trick. Here are the portions I find most significant.

$useragent=”Mozilla/5.0 (iPad)”; //Spoof as iPad

The line above sets the HTTP User-Agent header to the one that the iPad uses. This makes the AT&T website believe that the request came from an iPad. Generally, its a bad idea for web applications to rely on the user agent because this field can be spoofed very easily.

while (1) { //Continue FOREVER

This line instructs the script to keep running forever, or until a human turns it off. During this hack it was allowed to run at least 100,000 times, however there is no limit to how many email addresses could be harvested. This line also shows the programmer’s confidence in the fact that his attack cannot be detected, especially if he uses proxies to continuously change his IP address (another common technique used to avoid detection due to too much traffic from one source IP.)

$ICCID = $ICCIDroot.genluhn(strval($ICCIDroot)); //Generate checkdigit and attach it to the ICCID

This line creates a new ICC-ID, which will be used later. The ICC-ID has something called a “Check Digit”. This is a number derived and appended to the ICC-ID itself, and was supposedly created to detect ICC-ID corruption and to minimize spoofing. With a touch of ingenuity the programmer includes an algorithm in his script that re-generates the check digit for every ICC-ID attempted. This ensures the integrity and validity of the ICC-IDs he spoofs.

curl_setopt($ch, CURLOPT_URL, “https://dcp2.att.com/OEPClient/
openPage?ICCID=”.strval($ICCID).”&IMEI=0″);

This line is the ‘core’ of the script, and is the one that crafts the URL that will be used to harvest email addresses. It is strange to me, that the IMEI is always set to 0. I am only speculating, but it might have been possible to avoid or seriously thwart this attack if the IMEI associated with the ICC-ID was validated.

if (preg_match(“<input id=”email” name=”email” type=”email”
placeholder=”Required” value=”.*@.*” autocapitalization=”off”
autocorrect=”off”>”,
$output, $match)) {

The line above is a very crude (I repeat, very crude) way of parsing out the email address from the served HTML. It uses the powerful regular expression library (RegEx) in a very loose way, however it seems that it did the trick for the hacker. It does indicate, however that the script was written in a hurry.

Preventing this type of attack

This attack does not exploit and XSS (Cross Site Scripting), SQL Injection or CRLF injection techniques. In fact, looking at the PHP script reveals that the attack would have been impossible to detect, even if a Web Application Firewall was used. This type of attack can only be prevented by implementing proper quality controls.

Share this post
  • Headline looks like some in yellow press =)
    This attack is not *classic PHP* attack it is *really simple classic* attack and it does not depend on PHP.

  • Hi there,

    As the Lead Author of the OWASP Top 10 2007, the first to include direct object references, this issue is 100% DOR’s, and nothing whatsoever to do with SQL injection or XSS.

    This is an access control issue.

    Please update the recommendations to be one or more of:

    a) “Remember me” and “PII data form pre-fill” are ALWAYS dangerous. Don’t implement bad features.

    b) If you are going to implement dangerous features, add defense in depth. Let the user make the first move to “Remember me” rather than pre-filling. This pushes the risk to each user to make that choice, not marketing.

    c) Indirect object references could work here, in the same way they work for bit.ly and others – create a long lived random value AFTER the user has said “remember me”. Keep that and reference it. Make it hard to find the other values. As the web service is not for humans, it’s perfectly acceptable to use 128+ bit random numbers instead of six character strings like bit.ly.

    d) The User Agent string and other user settable headers are NOT trust worthy authentication tokens. Rinse and repeat.

    thanks,
    Andrew

  • Hi Andrew,

    Thanks for the comments and suggestions. In fact we did mention that this is not a typical attack that exploits well known vulnerabilities.

  • Hi Andrew,

    Your last comment is relevant – the User Agent string and other similar headers are good for statistics, and maybe also useful for enhancing the layout of the screens presented to the user, however they are easily spoofed so should not be used as a security measure. This point was mentioned in my article.

    I fail to see the relevance of your other comments to my article – maybe I am missing something – can you clarify?

    This type of attack was made possible because of poor quality code – proper QA procedures would have never allowed this. I hope that AT&T and Apple have adjusted their QA process to avoid this type of mistake. I wonder if there are other similar bugs on the AT&T website…. I wonder if someone is exploiting them right now…

    Jeremy

  • It’s not undetectable, but tricky. I made a framework ones for dealing with this myself, however as I am familiar with data scraping I cannot really protect against myself, 😀

    The script does not use proxies at the moment, however could easily be tweaked for this purpose. Also the script seems to hammer the target, possibly generating a lot of entries in the log – also for numbers that does not match.

    From the Apple side, you could check the last entries in the log. If theese are all from the same IP, and several tries within a timeframe, define this as an attacker and either log extra data or block.

    However changing the IP all the time makes this trick usesless, and you will have to start looking at the likeness of the previous requests. As all requests are identical, same parameters, this also becomes hard. As an example, scraping a directorysite would easily look like this:

    /someurl.php?letter=a
    /someurl.php?letter=b
    /someurl.php?letter=c
    /someurl.php?letter=d
    /someurl.php?letter=e

    If there were 5 different IPs involved it would look even more suspecious, again you can detect the attack.

    However – in this case – indeed hard!

    I would suggest the following protection scheeme:

    1. As soon as there are errors in the form (wrong ICCID), add a 5 second lag.
    2. If during period of lag even start logging max data possible and block all IPs generating error data, then que for manual check.

    The service using the service (iPad) should also be programmed in such a way that say, a captcha could be enabled instead of the lag, or even the device having some sort of animation to “obfuscate” the lag in action.

    Such a lag would for the occational user be of no problem, however for a service collecting the data render it more problematic, and maby useless since you need to much time to gather the data.

    Just some brainstorming.

  • Hi Kim,

    When writing this article, I also pondered on the same thoughts.

    Detecting the attack in real-time is possible, but as you say, highly unlikely.

    These are some mitigating factors:

    IP Addresses: Most hackers (and spies) today are using TOR as an anonymous p2p communications system. (http://www.torproject.org/). Traditional proxies also do the job.

    Predictable patterns: In this particular case, there is no a,b,c,d pattern because of the nature of the ICCID, which contains a check digit – see the PHP script:


    $ICCID = $ICCIDroot.genluhn(strval($ICCIDroot)); //Generate checkdigit and attach it to the ICCID

    This makes it very hard to detect serial brute force of ICCDs.

    I believe that security was in place, but for some reason got removed; look at the original URL of the web app:

    https://dcp2.att.com/OEPClient/openPage?ICCID=89014103211479197174&IMEI=0

    Why is the web app accepting my ICCID but allowing a 0 IMEI?

    If the ICCID was validated against the IMEI this hack would have been very hard, and would be easy to detect (too many failed validations).

    Thanks for your comments! I really appreciate your brainstorming… gave me a few new ideas..

  • Leave a Reply

    Your email address will not be published.