August 2011 - Posts

Another encouraging Mango update sign

Microsoft released an update to the Zune software. Of course, this hasn’t fixed any of my usual complaints about the inability to properly handle Podcasts, sorting and managing them, but it does make me convinced that we’re moving right along in the process to release a new version of the Windows Phone 7 OS.

To get your Zune software update, simply open your existing version of Zune, select Settings (in very small font on the top, towards the right-hand side), then under “Software” on the left, you’ll find an item “General”. Select this, and scroll the right-hand side until you see “Software updates” and “Check for updates” come into view. Click on “Check for updates”, and follow the instructions from there.


Encouraging Mango update signs for HTC HD7

I woke up this morning to a message on my phone that there is an update available.

This is hugely exciting, because I want the new “Mango” update that Microsoft released to manufacturing a week or two ago.

Something tells me that this probably isn’t Mango itself, but some pre-Mango update required by the hardware manufacturer to address driver requirements of the new version, which unlocks access to things like the compass and camera. Using devices in modes they previously weren’t operating in tends to reveal bugs in drivers, and so I am guessing that every phone will likely need a pre-Mango update to get its drivers and underlying SDKs / APIs into shape.

Here’s the image of the update trying to apply:


So, did any of you readers get a nice “gift” on your phone this morning? Is it the full Mango, or just a pre-Mango fix set?

Sadly, my update failed, with an error 0x801812c1, but a handy search on the Interwebs directed me to this KB article, which told me how to address this issue. I’m hoping this will now allow the update to be applied correctly.

Black Hat with–2011 Code Challenges II

The second day of Black Hat, and we’re showing three coding challenges. [Sorry this post took a while to make – but I hope you’ll agree that the new code formatting makes it easier to read]

As usual, the challenge is to figure out where the flaws lie, and for bonus points, to decide how you would prevent such flaws from happening throughout your own enterprises.

If you want to skip the code challenges, and get straight to the rewards, email or to get details on the job opportunities we have for all manner of security professionals in Seattle, Dublin, Virginia and Bangalore.

Challenge III – GetSignInResult

Here’s a short stretch of code from an authentication function – how long does it take you to spot the security flaw?

   1: SignInResult *getSignInResult(
   2:         const UserViewImpl *in,
   3:         const char *password )
   4: {
   5:     LdapAuthenticator *ldap = LdapAuthenticator::getInstance();
   6:     SignInResult *out = new SignInResult();
   7:     if( in == NULL || in->getUserId() == NULL ) { 
   8:         LogDebug( kFuncName.c_str(), "UserNotFound" );
   9:         out->setStatus( SignInStatus::UserNotFound );
  10:         return out;
  11:     }
  12:     if( !in->getAccountId() ) {
  13:         LogDebug( kFuncName.c_str(), "AccountNotFound" );
  14:         out->setStatus( SignInStatus::AccountNotFound );
  15:         return out;
  16:     }
  17:     out->setUserId( in->getUserId()->getId());
  18:     out->setAccountId( in->getAccountId()->getId());
  19:     AuthCodec *authCodec = AuthCodec::getInstance();
  20:     AuthToken authToken ( authCodec, in->getAccountId()->getId() );
  21:     out->setAuthToken( authToken.getEncodedAuthToken() );
  22:     CSRFToken csrfToken( authCodec );
  23:     out->setCsrfToken( csrfToken.getCSRFToken() );
  24:     if( !ldap->authenticateLdapUser(in->getUserName(), password)) {
  25:         LogDebug( kFuncName.c_str(), "LDAPBadPassword" );
  26:         out->setStatus( SignInStatus::BadPassword );
  27:         return out;
  28:     }        
  29:     out->setStatus( SignInStatus::Success );
  30:     LogDebug( kFuncName.c_str(), "Success" );
  31:     return out;
  32: }

Challenge IV – IsDifferent

This is a slightly modified version of last year’s “IsDifferent” challenge, mostly it’s the same thing, but if it’s new to you, it’s still new.

I’m embarrassed to say that at the conference, we briefly had a bug in our own code. That bug has been corrected below.

   1: bool isDifferent(
   2:     SomeClass const * newObject,
   3:     SomeClass const * oldObject) const
   4: {
   5:     // Returns true if newObject is different from oldObject.
   7:     // Shortcut if same pointer.
   8:     return newObject != oldObject &&
  10:     // Protect equals from being called on NULL.
  11:         newObject != 0 &&
  13:     // Return the result of "equals"
  14:         ! newObject->equals(oldObject);
  15: }

Challenge V – MultithreadRun

This was perhaps the one with the most extraneous flaws in it.

Yes, the cmd could be altered between the “is_user_admin” check and the cmd_copy line. That might happen, but the WRITE and DELETE commands still would be disallowed if the user is not an admin. Maybe this code operates in an environment where it’s safe for this to happen – perhaps admins only call WRITE or DELETE, and maybe WRITE and DELETE only execute queued operations that have already been approved and are merely waiting for an admin to choose the right time. OK, that’s a stretch, but the hint here is that this is NOT the bug we are looking for.

So, what is the bug we are looking for? Ask more questions, and I’ll answer them here – but of course, I won’t post the answer to any of these code challenges for a few weeks.

   1: #define READ      1
   2: #define WRITE     2
   3: #define DELETE    3
   5: int cmd;
   7: void multithread_update_cmd(int new_cmd)
   8: {
   9:     cmd = new_cmd;
  10: }
  12: int multithread_run(USERCONTEXT *pContext, CMDCONTEXT *pCmd)
  13: {
  14:     bool admin = is_user_admin(pContext);
  15:     // Copy the command so as to prevent it being altered
  16:     // by another thread.
  17:     int cmd_copy = cmd;
  19:     // Only admins can perform writes and deletes
  20:     if(!admin && (cmd_copy == WRITE || cmd_copy == DELETE))
  21:         return -1;
  23:     switch(cmd_copy)
  24:     {
  25:     case READ:
  26:         perform_read(pCmd);
  27:         break;
  28:     case WRITE:
  29:         perform_write(pCmd);
  30:         break;
  31:     case DELETE:
  32:         perform_delete(pCmd);
  33:         break;
  34:     default:
  35:         return -1;
  37:     }
  39:     return 0;
  40: }

Black Hat with–2011 Code Challenges I

As a part of my day job at Amazon, I get to spend time recruiting the brightest and the best of the world’s security professionals – especially those who are willing to move to Seattle, Virginia, Dublin or Bangalore. Every so often, we go out on the road to security conferences, and as well as being able to learn from other security professionals who are presenting, we have a booth whose chief purpose (aside from the usual networking) is to recruit security staff.

If you are interested in security jobs at Amazon, visit to see what’s available, and email to express your interest and submit your resume.

Black Hat 2011

We’re part way through the first day here at Black Hat in Las Vegas, and already the coding challenge is generating a lot of interest. Every morning, and every afternoon, we put up a piece of code – it’s a small piece of code, to make it readable and to make solving the challenge relatively quick and simple. But there’s something wrong with the code.

In my favourite samples, the flaw is a security flaw, but sometimes the flaw is something that, while not directly security related, may still cause a bug to trigger incorrect security behaviour.

Inevitably, we take down the coding challenge before some of the attendees have had a chance to read and work with it. Also, there is no way for non-attendees to get access to the code on the easel.

To fix that, I am uploading the code samples here to my blog. It’s important for readers to know that this is not an indication that anything in this blog is sanctioned or approved by, and it is not an indication that I speak for in any way whatsoever.

Having got that disclaimer out of the way, here’s the code we submitted for today, August 3rd, 2011.

Morning code sample: PerlForm

#!/opt/third-party/bin/perl –w
use strict;
use CGI qw/:standard/;
my $cgi = CGI->new;
my $name = $cgi->param("name");
my $item = $cgi->param("item");
my $count = $cgi->param("count");
print $cgi->header;
print $cgi->start_html('Form test code');
print $cgi->start_form;
print 'Name:',$cgi->textfield("name",$name),$cgi->br;
print 'Item:',$cgi->textfield("item",$item),$cgi->br;
print 'Count:',$cgi->textfield("count", $count),$cgi->br;
if (! $cgi->param) {
    # No values - show submit button
    print $cgi->submit;
    # CSRF protection - submit hidden nonce
    my $nonce = rand(100000000); # A bazillionty.
    print $cgi->hidden("nonce-value",$nonce);
} else {
    # Values - purchase item. Use cookie to identify session
    process_values($name, $item, $count);
print $cgi->end_form;
print $cgi->end_html;
exit 0;

Afternoon code sample: FixedPoint

bool fixedPoint(int nDecimals, const char *str, int &out)
// Converts string representation of decimal numbers
// to fixed-point integer representation, multiplying
// by 10 ^ nDecimals.
// Input has been sanitised and is trusted to be valid.

    char *point = 0, *end = 0;
    int frac = 0, digits = 0;

    out = strtol(str, &point, 10);

    if ( *point == '.' )
        frac = strtol(point+1, &end, 10);
        digits = end-point-1;
    } else if (point == str)
        return false;

    while (nDecimals—)
        out *= 10;
        if ( --digits == 0 )
            out += frac;

    return true;


Note that the comments here can be relied upon. When we say that the inputs are sanitised and can be trusted to be correct, that means that nDecimals is always greater than or equal to the number of digits past the decimal point. strtol starts at the first parameter converting a representation of an integer from character to integer, and when it finds a character not part of that integer representation, it stops, and stores the pointer to that invalid character in the second parameter. The third parameter is a base, or radix. Here, we use base 10. There is no integer overflow going on here, the numbers being passed in are relatively small.

So what are we doing here?

Obviously, I’m not going to provide answers here for some time, because that would reduce the