Wings of Hermes – Berin's Infosec Blog

Infosec the world and everything

I was forwarded an article today from the BBC news website - Zurich Insurance fined £2.3m over customers’ data loss .  It’s a fairly standard article about a financial institution being fined for  losing customer data.

What really struck me though was a comment in the article from the FSA – “Firms across the financial sector would do well to look at the details of this case and learn from the mistakes that Zurich UK made…“.  That’s true.  But what concerns me is the real focus on fincos with this stuff.  There are so many other companies now holding our private data – and in many cases they are holding more than the financial institutions do.

Shouldn’t we be maturing this argument now to extend beyond financial institutions?  There should a duty of care for any company holding my data.  Financials can lead the way – but we need to hold other companies accountable as well.

Network World have an interesting article based on a Forrester research report on iPhone and iPad security, arguing it’s good enough for most cases.

I seem to be struggling with lots of things lately that should be easy, but I just can’t find an easy way to do them. My latest struggle has been using NSURLConnection to connect to an SSL site that is secured using my root certificate. There is no easy reference anywhere for how to do this without loading the root cert into the user’s general key store – which is fiddly and not the best in some circumstances.

In my case I use cacert.org as my root cert and I don’t want to force the end user to trust all sites signed by cacert.org, I just want my SSL connection to work inside my app.

So it turns out there are two methods that you need to use in the NSURLConnection delegate class. Both are referenced in many places, but it’s generally to tell you how to completely bypass any check. You can also use them to check against your own root cert.

First of all, you implement -(BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace so that for server authentication requests the NSURLConnection class knows you can handle them.

Then you implement - (void)connection:(NSURLConnection *)conn didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge to actually handle the check. The code is pretty simple.

As a note – rootCert in the attached code is a reference to a certificate I loaded from a file (DER encoded).

#pragma mark -
#pragma mark Connection Authentication Handling

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {

    #pragma unused(conn)

    NSString * challenge = [protectionSpace authenticationMethod];
    if ([challenge compare:NSURLAuthenticationMethodServerTrust] == 0) {
        return YES;
    }

    return NO;

}

/* Look to see if we can handle the challenge */

- (void)connection:(NSURLConnection *)conn didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
    #pragma unused(conn)

    NSLog(@"didReceiveAuthenticationChallenge %@ %zd", [[challenge protectionSpace] authenticationMethod], (ssize_t) [challenge previousFailureCount]);

    NSURLCredential *   credential = nil;
    NSURLProtectionSpace *  protectionSpace;
    SecTrustRef             trust;
    int                        err;

    /* Setup */
    protectionSpace = [challenge protectionSpace];
    trust = [protectionSpace serverTrust];
    credential = [NSURLCredential credentialForTrust:trust];

    /* Set up the array of certs we will authenticate against and create cred */
    NSArray * certs = [[NSArray alloc] initWithObjects:(id)rootCert,nil];
    credential = [NSURLCredential credentialForTrust:trust];

    /* Build up the trust anchor using our root cert */    

    err = SecTrustSetAnchorCertificates(trust, (CFArrayRef) certs);
    SecTrustResultType trustResult = 0;
    if (err == noErr) {
        err = SecTrustEvaluate(trust, &trustResult);
    }

    [certs release];

    BOOL trusted = (err == noErr) && ((trustResult == kSecTrustResultProceed) || (trustResult == kSecTrustResultUnspecified));

    // Return based on whether we decided to trust or not

    if (trusted)
        [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
    else {
        NSLog(@"Trust evaluation failed for service root certificate");
        [[challenge sender] cancelAuthenticationChallenge:challenge];
    }

}

Again – I reckon there will be a quicker way to do this and probably some bugs in what I’ve done – feel free to comment and set me on the straight and narrow!


Strange.

com.sun.org.apache.xml.internal.security.utils.Base64 is a part of the base Java 1.6 runtime (it’s found in rt.jar). But Netbeans throws errors on it unless you include the METRO 2.0 jar file as a library to compile against (you don’t need to package it).

Or at least that’s the case on Windows. On OS X it just works.

What a waste of an evening

I’ve spent the last two days working through this – and couldn’t find any easy code at all on the net. So to save others the time here is what I found.

First off, when you export a key from the iPhone keychain, it’s exported in a cut down format – just the public key and exponent without any of the other ASN.1 stuff you’d expect in a fully encoded public key. The java crypto functions generally expect a fully encoded key (OID and all). So I quickly whipped up some Objective C code to take the exported key and expand it out to a fully interoperable key in the X.509 format.

I’m darn sure there is an easier way to do this, I just couldn’t for the life of me find it. Please let me know what I’ve missed or any bugs/errors/plain sillies in the attached following code

First off a simple function to encode ASN.1 length fields:

// Helper function for ASN.1 encoding

size_t encodeLength(unsigned char * buf, size_t length) {

    // encode length in ASN.1 DER format
    if (length < 128) {
        buf[0] = length;
        return 1;
    }

    size_t i = (length / 256) + 1;
    buf[0] = i + 0x80;
    for (size_t j = 0 ; j < i; ++j) {         buf[i - j] = length & 0xFF;         length = length >> 8;
    }

    return i + 1;
}

OK – with that in place, some code to actually do the encoding. The following is a full copy of a function from something I’m working on. The Base64 class is a very simple encoding/decoding class I built.

- (NSString *) getRSAPublicKeyAsBase64 {

    static const unsigned char _encodedRSAEncryptionOID[15] = {

        /* Sequence of length 0xd made up of OID followed by NULL */
        0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
        0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00

    };

    NSData * publicTag =
        [NSData dataWithBytes:_PWITC_PUBLIC_KEY_TAG
                       length:strlen((const char *) _PWITC_PUBLIC_KEY_TAG)];

    // Now lets extract the public key - build query to get bits
    NSMutableDictionary * queryPublicKey =
        [[NSMutableDictionary alloc] init];

    [queryPublicKey setObject:(id)kSecClassKey
                       forKey:(id)kSecClass];
    [queryPublicKey setObject:publicTag
                       forKey:(id)kSecAttrApplicationTag];
    [queryPublicKey setObject:(id)kSecAttrKeyTypeRSA
                       forKey:(id)kSecAttrKeyType];
    [queryPublicKey setObject:[NSNumber numberWithBool:YES]
                       forKey:(id)kSecReturnData];

    NSData * publicKeyBits;
    OSStatus err =
        SecItemCopyMatching((CFDictionaryRef)queryPublicKey,
                            (CFTypeRef *)&publicKeyBits);

    if (err != noErr) {
        return nil;
    }

    // OK - that gives us the "BITSTRING component of a full DER
    // encoded RSA public key - we now need to build the rest

    unsigned char builder[15];
    NSMutableData * encKey = [[NSMutableData alloc] init];
    int bitstringEncLength;

    // When we get to the bitstring - how will we encode it?
    if  ([publicKeyBits length ] + 1  < 128 )
        bitstringEncLength = 1 ;
    else
        bitstringEncLength = (([publicKeyBits length ] +1 ) / 256 ) + 2 ; 

    // Overall we have a sequence of a certain length
    builder[0] = 0x30;    // ASN.1 encoding representing a SEQUENCE
    // Build up overall size made up of -
    // size of OID + size of bitstring encoding + size of actual key
    size_t i = sizeof(_encodedRSAEncryptionOID) + 2 + bitstringEncLength +
               [publicKeyBits length];
    size_t j = encodeLength(&builder[1], i);
    [encKey appendBytes:builder length:j +1];

    // First part of the sequence is the OID
    [encKey appendBytes:_encodedRSAEncryptionOID
                 length:sizeof(_encodedRSAEncryptionOID)];

    // Now add the bitstring
    builder[0] = 0x03;
    j = encodeLength(&builder[1], [publicKeyBits length] + 1);
    builder[j+1] = 0x00;
    [encKey appendBytes:builder length:j + 2];

    // Now the actual key
    [encKey appendData:publicKeyBits];

    // Now translate the result to a Base64 string
    Base64 * base64 = [[Base64 alloc] init];
    NSString * ret = [base64 base64encode:[encKey bytes]
                                   length:[encKey length]];
    [base64 release];
    [encKey release];
    return ret;
}

As I said – I’m very sure there is an easier way to do this. If someone can tell me what it is I’d be most grateful!

And if you need some code to import into a Java key – the following is a cut from the java app I am building. Clearly you will want to get a bit prettier on the exception handling :) .

        byte[] decodedPublicKey;
        try {
            // Now lets encrypt the nonce
            decodedPublicKey = Base64.decode(d.getPublicKey());
        } catch (Base64DecodingException ex) {
            logger.log(Level.WARNING,
               "getDeviceInfo - error decoding public key for device:{0}",
               deviceId);
            return di;
        }
        PublicKey publicKey;
        try {
            publicKey = KeyFactory.getInstance("RSA").
                generatePublic(new X509EncodedKeySpec(decodedPublicKey));
        } catch (Exception ex) {
            logger.log(Level.WARNING,
               "getDeviceInfo - error importing public key for device:{0}",
                deviceId);
            return di;
        }


Read an interesting article Gartner: Companies shouldn’t bother banning Facebook, social networking
this morning around Gartner’s security guy Andrew Walls and his view on the value of blocking social media.

I tend to agree with his argument that security people risk loosing credibility if they keep saying these sites are dangerous when people use them freely at home and don’t seem to get badly hurt. A real case of the history not supporting the risk statement. And people do keep saying it’s a massive malware risk – letting people browse the Internet is a Malware risk full stop. We haven’t stopped that yet!

I also like his thinking about the relative value to the organization of people with large social networks. They are probably the people who will provide the most value. I think the value it brings is a key input to the risk reward equation that companies use when making these decisions.

But the bit that really struck me was that last year the percentage of Gartner client companies blocking social media was 75%. This year it is at 60%. That’s a big jump in a short time. The absolute percentages won’t represent the broader community – I’m not sure that many companies really filter the Internet. But the relative values still say a lot.

Maybe us security peeps need to “just get over it”.

It’s interesting to watch the changing attitude to patching on workstations. I’m probably a bit behind the eight ball on this stuff – patching has never been a favorite subject of mine (I get frustrated with the amount of time and effort patching can take up with no real visible value created). But what’s interesting is the move from patching being something that has to be done very carefully to something that is just “par for the course”. Organisations expect to have to do it so you no longer get the push back we used to get.

It’s a bit like AV – when it first became commonplace, there was an update once a week (or even once a month!) and change control was required to get it out there. Now it just happens as often per day as is necessary. The danger of course is that it’s now easy to forget about it. The first you know that something isn’t working right in your organisation is when you get an outbreak of something nasty. (Welcome security metrics!)

I wonder how long it will be before patching is as invisible on workstations? We must be getting close – I’m watching apps on the iPhone update very regularly – not that big a jump to see it be that regular (and transparent) on Windows.

Or is that wishful thinking?


Isn’t the iPad phenomenon interesting! I’m firmly in the camp that it’s a “good thing”, and having played with one I think it’s wrong to compare it with a laptop – the whole concept is different. It’s not about having a small form factor fully functional computer – it’s about having a small device that is instant on and gives you access to web/cloud services and media.

I find the instant on is important. In the house I tend to avoid turning on the computer if I have to look up something quickly. It’s too much hassle. The iPad/iPhone (or similar devices) are instant on – net access conveniently and quickly.

From a security perspective I find the iPad/iPhone fascinating. On one hand the in built security functions are ordinary. Device lock is a 4 digit PIN, there is no automatic encryption of flash and if you’ve tried to program one (I have) things like the cryptographic libraries are somewhat hard to find any information on.

On the other hand, the construction of the application environment is great. I love the fact that each application is sandboxed from the others. I think in version 4 of the OS there will be shared data of some kind – but I’ve not got my head around that yet. It starts to make the perfect access device.

I’m using my iPhone now for all my banking needs. Why?

  • The only virus I’ve seen was the the Rick Astley concept virus. I’m sure there will be others, but at the moment there is less of a focus on the iPhone for malware. (And I’m not planning to jailbreak any time soon.)
  • The sandbox environment makes it less likely a badly behaved/insecure application can undermine the entire phone. Not by any means infallible, but not a bad start.
  • The device is simpler than a computer running a full operating system. Simpler = less to go wrong = easier to secure.

So on one hand you have a device that has little in the way of enterprise security features you might expect in a laptop (full disk encryption, password management etc.). But on the other you have a simple device that for accessing cloud or web type services – where the data is not stored on the device – which is perfect.

So all in all – I’m in favour. I like the whole concept and I think the more iPad like devices we see, the better it’s going to be for security – with the caveat that the device is about access not storage. So to sum it up:

  • If your need is access to sensitive information/data/applications without local data – the iPad is a great device.
  • If your need is storage and local handling of sensitive data/applications – stick with a laptop for now!


And this is interesting as well. The old question of how do you know the person you are talking to online is who you think they are.

Although you gotta ask – why would anyone just hit accept on a friend request from someone they didn’t know? Education in this space just has to get better I think.


I’ve been following the whole Facebook privacy saga with great interest. It’s good to see that Facebook are about to put in some fixes. Some would argue a little too late – but then the business of Facebook is about dealing in people’s private information, so I would have been surprised if they jumped to action any quicker than they absolutely had to.

As a security practitioner, the whole Facebook (and social media) phenomenon scares me a little. At the moment the bulk of the discussion is about how people don’t want their personal information shared. But the reason it scares me is that the personal information being discussed is what web sites for large organisations (e.g. banks) have been using to authenticate people for a long time. The average password reset questions are things like “what is your mother’s maiden name” or “what is the colour of your car.

Well you can find the answers to these questions (and more!) on social media sites. And with members in the 100s of millions, that’s a lot of information for fraudsters to mine.

So my doomsday scenario – what happens when someone hacks the Facebook database?