Friday, January 24, 2014

Credit Card Authentication

As news continues to trickle out about the Target breach (and allegedly 6 other merchants, including Neiman Marcus), I continue to wonder why the credit card companies have not taken steps to provide more security at the point of purchase. Perhaps their cost of dealing with compromised cards is less than the cost of rolling out a whole new mechanism that would likely involve new cards, new POS terminals, training everyone involved, etc? Personally, I am hoping that the magnitude of these most recent incidents will serve as leverage to make such changes.

Regardless of why it has not been done, I wanted to understand more about the current security mechanisms. When I make a credit card purchase in person, I swipe my card in the POS terminal and then possibly sign the transaction receipt (either on paper or digitally on the POS terminal screen, if it has one). That's it. Rarely am I asked to present a photo ID. And in the last few years, some merchants have stopped requiring the receipt signature if the purchase total is less than some amount. The amount seems to vary, but the limit is typically between $25 and $40. Also consider purchases made at automated kiosks including most gas pumps, where you do not have to sign at all.

So if someone could steal my card (or clone it using information stolen electronically), they would likely be able to make purchases with it. Especially if they know which stores typically do not ask for additional proof of identification and/or make small purchases and do not get greedy with it. The mechanisms of photo ID and receipt signature are pretty weak. The probability of the clerk knowing you personally is very small. And the clerk is unlikely to have been professionally trained at spotting fake IDs or handwriting analysis. So comparing the signature on the credit card with the receipt and/or ID is not going to get a lot of scrutiny. Also, the merchant will err on the side of making profit and permit most purchases by default. A merchants public image would be damaged if they became know for turning down valid transactions (i.e. false positives). And the merchant is not liable for the fraud. Neither are you. Federal law limits your liability to $50 and that is typically waived by the major credit card vendors.

Even if these mechanisms were not so weak, is the merchant required to implement them? The answer varies with card type and the policies have changed over time. An internet search turns up several articles exploring this same question, but they are all several years old with outdated or broken links to the credit card merchant sites. So I did a fresh search as of January 2014.

All of the big four vendors require the signature check for in-person purchases, but what about requesting photo ID?
Visa (page 431) says no.
Mastercard (page 3-2, #7) says yes.
American Express (page 22, section 4.4) says no.
I could not locate the Discover manual, only a fraud FAQ.
It looks like you may need to be a registered merchant to access their documents.
the FAQ suggests that refusal of showing photo ID is "suspicious", but does not mention any policy of asking to see it.

I don't have a Mastercard, but have used some of the others and can count on my two hands how many times in over twenty years that I've been asked to show my photo ID.

There is an interesting meme floating around that says you can "sign" your credit card with the statement "See ID". The idea is that the merchant would then be forced to ask for your photo ID. This has been debunked. Not using your actual signature means the card is technically invalid. This may actually work for you if the clerk agrees with the meme, but it has no legal validity.

What about the PIN or the CVV2 code on the back of the card? Yes, credit cards have a PIN. When you first got your card, there was a separate envelope mailed to you from a different, seemingly unrelated address that contained the PIN. So why are we not using that like we do for debit card transactions? The only place it is required is if you use your credit card at an ATM to get a cash advance (i.e. high-interest loan).

The CVV2 code on the back is not required for in-person purchases, but is used by a few merchants. At Best Buy, for example, they usually ask to see my card, flip it over and type the code into the cash register. So that makes it more like an online purchase where it is often (but not always) required. Of course, this does not matter if someone has acquired your physical card. Then they have that number too.

In my opinion, it is only a matter of time now before we see some new payment processing infrastructure rolled out en masse. It will likely be EMV (chip and PIN), i.e. smart cards that can do some cryptographic calculations all by themselves. Powered by the POS terminal, they would be given transaction session information and only emit encrypted packets back through the merchant's system to the payment processor. This is analogous to the Secure Shell protocol where public/private keys are used to securely exchange the session key and all traffic is encrypted the entire time. And in order for a thief to clone your card, they would need to compromise all the way into the card itself to extract your keys. If they steal your physical card, then they have to crack your PIN and these cards can be configured to lock themselves down after so many incorrect attempts. I have no doubt that someone can engineer a way around all that, but at what expense? Just like the merchants and credit card vendors, the thieves also have to balance the cost vs reward ratio. If it costs them more time and effort than they get out of it, then it is not worth the time to crack your card. These guys are just as business savvy as anyone else, they just choose to do things that are considered illegal.

This post maps to CompTIA SY0-301 exam objectives 2.1 and 5.2.

Sunday, January 19, 2014

Content Filtering and Analysis

I work in a "high-security" facility and we have all manner of policies and rules to follow to be considered worthy of a simple Internet connection at our workstations. Our facility is just one building on a much larger campus and all the network traffic to the outside world goes through a single gateway. As part of their security apparatus, they have set up an HTTPS proxy at this gateway. The proxy allows them to break open every HTTPS connection with a deliberate man-in-the-middle (MITM) "attack" for the purpose of analyzing it to make sure it's "OK" by their definition. On top of this, they also subscribe to a content analysis/filter service that categorizes various sites and pigeon-holes them into one or more labels. Then certain labeled categories are denied as a whole.

Both of these mechanism introduce some rather severe usability issues. In several previous posts on this blog, I have brought up the subject of usability. In my experience, usability is about the last thing that security folks consider. It really ought to be part of the availability side of the security triangle. If something becomes too difficult or impossible to use, but it is a legitimate need, then it has become unavailable. Then users are tempted to seek workarounds or "other means" of getting to their resources. Security FAIL.

Let's look at some specific issues.

The MITM HTTPS proxy wreaks all kinds of havoc. It causes a noticeable increase in download speed for the extra time it takes to establish a second HTTPS connection with whomever you actually intended to reach. Remember this one system is doing this for every connection on the entire campus which is several tens of thousands of systems. I sometimes download software via  svn or git servers. Wireshark is a good example. This is a fairly lengthy operation, much larger than a typical single web page. It often breaks down in mid-download for no apparent reason. If I download it from outside the facility (e.g. at home) it works fine every time.

The content analysis/filter frequently prevents access to legitimate resources for the wrong reasons. The facility subscribes to a third-party filter service. They just get a regular filter definition update and install it. Job done as far as they're concerned. Unfortunately, the granularity of the filter is pretty big and lots of sites get lumped into a general category of "bad" with no further distinction made. A great example is a site being declared a "blogging site". That is way too broad. We are doing software engineering and solving a lot of technical problems about Linux, C++, etc. Many times, a web search will turn up someone talking about the exact, specific issue that we are having, but... the discussion is on a "blog" site (<gasp>). So you end up emailing the URL to yourself at home and looking it up from there later. Progress is delayed. Part of our application makes use of OpenGL doing all kinds of fancy graphics stuff. A lot of discussion about those types of issues is found on gaming development forums, but they're all blocked because they are lumped into the "gaming site" category. Shame on you, programmer, for looking at gaming sites instead of working!

I have also encountered sites that are blocked for seemingly no logical reason. A good example is http://libssh.org. When I got denied access to that one day, I decided to try challenging it and requesting an exception. I explained what it was, why I wanted access and how it was not in any way qualified to be in the "known spammers" category. After escalating it to the "tier 2" guy, I was told that yes, that site was OK, but unfortunately the IP of its hosting service was in a range of addresses that host known spammers. So the entire range of addresses was just blocked wholesale. And since they just subscribe to this third-party list and it had the range listed, they could not or would not make any change for it. So once again, I download it at home later.

So how could this situation be improved? If I were in charge of the whole thing, I would have a few folks appointed to be the local point of good judgement and discretion. They would be tasked with evaluating all requests for exceptions and making local tweaks to the content filter definition. I think a subscription-based service is fine as the starting point, but if you just accept that as-is, you will end up hurting the usability for your particular, local users. And that reduces availability which can hurt security more than it helps sometimes.

This post maps to CompTIA SY0-301 exam objectives 1.1 and 2.8.

Saturday, January 18, 2014

Public key authentication with libssh

Continuing my previous post about libssh, the next question was how to handle authentication.
The library (version 0.6.0) allows for several methods, including passwords, public keys, keyboard interactive and GSSAPI. For my use case, I knew passwords were right out because once the shared key was passed around, it would be worthless with no way to control access. I didn't like the sound of keyboard interactive and don't know a thing about GSSAPI. I've been using public key authentication with ssh for many years, so that seemed like a good choice.

Once a session has been established and keys exchanged, you are ready to accept the authentication.
Set your public key authorization callback in the server callbacks struct.
   struct ssh_server_callbacks_struct cb = {   
      .auth_pubkey_function = auth_pubkey
   };
Tell it that you only want public key authentication. It will automatically deny all attempts to use passwords and other methods for you.
  ssh_set_auth_methods(session,SSH_AUTH_METHOD_PUBLICKEY);
Create the event loop that will take care of all the I/O for you and simply invoke your authentication callback at the appropriate time to let you decide what the answer will be.
    mainloop = ssh_event_new();
    ssh_event_add_session(mainloop, session);

    while (!(authenticated && chan != NULL)){
        if(error)
            break;
        r = ssh_event_dopoll(mainloop, -1);
    }
The public key authentication callback looks like this. You are given a pointer to the session, any username that was used, a pointer to the public key that was offered, the key's signature state and your own application user data (if any).
   int auth_pubkey( ssh_session session,
                               const char *user,
                               struct ssh_key_struct *pubkey,
                               char signature_state,
                               void *userdata );
So what do we do with all this? I had a brief moment of initial confusion about being handed a public key instead of a private key. Well duh, you don't ever send the private key anywhere or it would not remain private for long, would it? Referring to RFC 4252 - The Secure Shell (SSH) Authentication Protocol, section 7, we see what's going on. Back on the client side, the SSH client uses your private key to sign a copy of your public key. Then the public key and signature get sent to the server and show up in this callback. Actually, the library has already evaluated the validity of the signature and simply gives you the signature_state enumerated value. You need the whole public key, however, because you're likely going to compare that to one or more public keys already installed on the server side to see if this one is a match. Using OpenSSH, for example, you would have your public key installed on the server side in the $HOME/.ssh/authorized_keys2 file. The server sees you attempting a login as user 'fred' and compares the public key offered from the client side to all the keys in user fred's authorized_keys2 file. If the signature is valid and there is a match, you're in. If not, then you are rejected.

In my use case, there is no relevant username because we're not logging into a system. So I just ignore that value. It can even be omitted on the client side. I chose to simply have a directory within my application's data area that is the designated location for authorized public keys. This is equivalent to the authorized_keys2 file. There is little difference between keeping them all in one file or having separate files in one directory. So my auth_pubkey function logic looks like this (error-checking elided for clarity).

   if ( signature_state == SSH_PUBLICKEY_STATE_NONE )
      return SSH_AUTH_PARTIAL;

   if ( signature_state != SSH_PUBLICKEY_STATE_VALID )
      return SSH_AUTH_DENIED;

   // valid signature received
   // loop through the keys directory, for each key file 'f'
   ssh_key k;
   ssh_pki_import_pubkey_file( f, &k );
   int result = ssh_key_cmp( k, pubkey, SSH_KEY_CMP_PUBLIC );
   ssh_key_free(k);
   if ( result == 0 )
      authenticated = true; // to exit the event polling loop
      return SSH_AUTH_SUCCESS;

  // if no matches
  return SSH_AUTH_DENIED;

This works but leaves me with one open question. Why does it get called twice? Once with a signature state of NONE and then again with VALID after the client has given the private key passphrase. In fact, if you don't return PARTIAL in response to NONE, then the client side never prompts for the passphrase at all. With this logic, the client side (at least OpenSSH) shows an extra line of verbose output stating "Authenticated with partial success". That's harmless but I will continue to investigate and see if I can clean that up.

Note that there are two mechanisms at work here to denote that authentication is complete. You return SUCCESS/PARTIAL/DENIED for the sake of the library logic that is taking care of so many things for you. You also set the 'authenticated' boolean to true to break out of the application-managed event loop. Are these two controls redundant? Not at all. Suppose you wanted to be extra secure and use multiple authentication mechanisms. They all get processed off this one loop with all the respective method callbacks firing. Each one of them is telling the library if that particular method is successful or not. Then you still need something like the authenticated boolean to reflect your application's overall success state, i.e. once all the methods have succeeded.


It does not get much easier than this. Many thanks to the authors of libssh for encapsulating so much of the work.

This post maps to CompTIA SY0-301 exam objective 1.4.

Thursday, January 2, 2014

Embedding SSH Service

Some network appliances (routers, firewalls, etc) support a remote command-line interface. This can be a good way to provide a user interface to a device that doesn't have video and isn't connected to any peripheral. It's just there on the network. Traditionally, this interface uses the TELNET protocol. The origin of this feature predates SSH and HTTP. Most newer items tend to use an HTTP-based interface where you just point your web browser to it. Some devices may have SSH instead or in addition to the TELNET option for better security.

I work with a proprietary application that runs like a system service and has no user interface. However, there are a number of performance-related parameters and status values that are useful to inspect and possibly modify at run-time to perform diagnostics or help create particular test conditions. In this applications environment, low-security interfaces are, shall we say, frowned upon. And we did not have the resources to implement a full-blown HTML interface using HTTPS or anything like that. So recalling the simple TELNET command-line interfaces that some devices use, I thought that would make a good option.

The first version made use of a very handy library called Libcli created by David Parrish. This library is easily included with your application and takes care of setting up the socket and handling the whole TELNET part. You register as many different commands as you want, each mapping to a callback function that you provide. The library takes care of parsing the user input and invoking the registered callback. From the callback you can do whatever you want and print output that goes back to the client side for display.

That was great until the security folks said, "hey, you can't run a TELNET service". They were not willing to draw a distinction between a TELNET service allowing a user login to the system and an application allowing access to some diagnostic information. Their network scanner just saw "something" respond positively to a TELNET request. Compliance check failed. End of story.

So we had to disable it in deployed configurations and can only use it in the test lab. So my next logical thought was using SSH instead of TELNET for the authentication and transport but still let Libcli handle all the command processing after that. I didn't want to have to reverse-engineer the OpenSSH code to pull out what I needed. Had anyone written a library that made implementing the SSH protocol simple for embedding in other applications? Of course they have. I'm not the first person to think of any of this.

I found two obvious candidates, libssh and libssh2. So which one should I try first? The libssh2 folks already did my homework for me with this comparison chart of their library vs libssh. This made the decision very quick because libssh2 does not have server-side functionality, where libssh does. Done.

libssh takes care of almost every necessary SSH function for you. It sets up the socket, listens for connections, handles authentication (using host keys you provide), lets you set up a pty and open a secure channel. After that, you have a secure "pipe" to read/write data, whatever that data might be. That part is your business.

So the next question was how to meld the two libraries together? I wanted to use libssh to do all the SSH part but still let Libcli handle all the command processing over the secure channel. In order to read/write the secure channel you use the ssh_channel_read() and ssh_channel_write() functions. Other than the channel parameter, you just give them a pointer to your buffer and length and its just like a plain read()/write() as far as you're concerned. Now in Libcli, once you set up all your commands, you normally just call the cli_loop() function. But in this use-case, we cannot do that because cli_loop() encapsulates too much stuff we don't want. It handles accepting socket connections, all the TELNET stuff and then executing the appropriate callback function. We just need to parse the command and invoke the callback. Most of that is encapsulated in cli_run_command().

So that just leaves our code with the duty of processing the raw user input from the secure channel and assembling a line (until 'enter') and passing it to cli_run_command(). But how will output from the callback functions get back to the client side? All output from Libcli callback functions is done by calling cli_print(). Since that's part of the library, it has direct access to the file descriptor of the socket and sends your output back to the client for you. But in our case, we have to call ssh_channel_write(). Fortunately, Libcli has foreseen this type of situation and provided cli_print_callback() which, if set, will be invoked from cli_print() instead of trying to write to the internal file descriptor (which is NULL because we didn't use cli_loop() to accept a connection). So the command callback invokes the print function which calls my callback with the output text. Perfect. My print callback just passes the buffer on to ssh_channel_write().

So that's it in a nutshell.  As my initial proof-of-concept demonstration, I simply modified one of the examples provided with libssh. Note that this uses the release candidate version 0.6.0 of libssh. The current stable release (0.5.5) does not have as many examples of SSH server code.

sshcli.c

A single, trivial command of "show stuff" is set up with Libcli and then the rest of the modification is in the do loop that reads from the channel. To build it, just compile with gcc and link with both Libcli and libssh.
gcc sshcli.c -o sshcli -lcli -lssh
To run it, you'll need to provide SSH host keys. I just copied the ones on my system. Also specify which port to listen on. The default port 22 is taken by your system's sshd service, of course. Your application will be listening on something else.
sshcli -d host_dsa_key -r host_rsa_key -p 2000 127.0.0.1
Then from another shell, just connect with ssh. The example program uses password authentication with username "user" and password "password".
ssh -p 2000 user@127.0.0.1
After authenticating, you'll get the welcome banner and the prompt. Note that I had to implement those too because they are normally taken care of by cli_loop(). Then start typing commands. Done.

This post maps to CompTIA SY0-301 exam objective 1.4.