How NOT to build your client-server security architecture

By: Patrick Toomey

Traditional client-server and web applications aren’t that different from a security standpoint.  Sure, native UI controls are great for a nice look and feel, and access to native OS APIs is great for creating a high performance application that integrates well with the target platform.  But, from a security standpoint, they are on equal footing.  Neither should trust the client, requiring that developers place all of the security relevant logic on the server.  By and large most web application developers seems to understand that the browser is not to be trusted.  That isn’t to say that all web application developers get it.  There are definitely those web apps that delegate a  too much to the browser, using hidden form fields inappropriately, depending on client-side JavaScript a bit too heavily, amongst other things.  But, on the whole, I have yet to see nearly the number of web applications that were designed with as many fundamental architectural flaws as seems to be common amongst niche vertical market client-server applications.  Wow, did I just say “niche vertical market client-server applications”? What does that mean?  I am talking about the types of client-server applications that were either developed in house, or were bought commercially, but serve a very specific task.  Before I get into trouble for generalizing, yes, I concede that my views are shaped by my experiences.  I am absolutely sure that there are scores of “niche vertical market client-server applications” that are rock solid from a security standpoint.  But, my experiences with these types of applications, combined with recent war stories of some colleagues, compelled me to rant…just a little.

The vast majority of the applications we assess are web based.  Sure, we look at our fair share of client-server applications, but I would say the ratio is probably on the order of 10 to 1.  For whatever reason, we had a string of more traditional client-server applications on our plate in the last few weeks.  Looking at the types of vulnerabilities identified in these applications, as well as other similar applications we have reviewed in the past, it seems as though there is fundamental gap in how a fair percentage of these developers are approaching security.  To illustrate, let’s listen in on a couple of web developers discussing a few pieces of their security architecture for a new web app they are about to deploy.

Web Dev 1:  So, we need to check to make sure only authenticated and authorized users are allowed to access our app.

Web Dev 2:  Yeah, it seems like this whole username password thing is pretty popular.  I vote we go with that.

Web Dev 1:  Ok, yeah, no need to reinvent the wheel here.  So, how should we go about validating the user’s username and password?

Web Dev 2:  Well, we could send an AJAX request to the server, passing the user’s username, and get back all of the user’s information, including their password, and simply validate it in JavaScript.  That way we can keep the logic really clean and simple on the server side of things.

Web Dev 1:  Yeah, that is awesome; with a little more effort we almost don’t need an application server.  We can do everything client-side.

Web Dev 2:  Yeah, we can do all the logic on the client in JavaScript and simply make calls to the backend to store and retrieve data.

Web Dev 1:  Wow, I think we have hit on the next big thing.  All we really need is to make some sort of direct ODBC connection to our database via JavaScript and we’ve nearly collapsed an entire tier out of the three tier architecture…incredible.

Web Dev 2:  Hmmm, yeah, it sounds pretty great, but we are putting a lot of our eggs into one basket.  What if someone figures out how view or manipulate traffic as it traverses the network.  They might be able to do bad stuff.

Web Dev 1:  Yeah, true, there must be some way to prevent our users from mucking around with the network traffic.

Web Dev 2:  I got it!!  We can use SSL.  That uses top notch cryptography that nobody can break.

Web Dev 1:  I think we have it.  But, I thought I remember reading about some sort of tool that lets user’s man in the middle their own SSL traffic, something to do with proxies and self-signed certificates or something?

Web Dev 2:  Hmmmm….that could be a problem, but it sounds like it would be really hard for users to do.

Web Dev 1:  Yeah, nobody will figure it out.  I think we are good to go.

Ok, the above conversation is obviously hyperbolic for effect, but can you get what I am saying here?  The above conversation just wouldn’t happen in a web app world.  Almost every sentence is filled with principles that are antithetical to the web security model.  Validating passwords on the client-side in the browser, connecting directly to the database from the browser (thankfully this doesn’t exist…I googled it just to make sure there wasn’t some inept RFC I wasn’t aware of), or treating SSL like it is some sort of magic crypto juju you can sprinkle over your application to protect yourself against users that have full control of the execution environment.

I have seen some web applications in a pretty sad state of disrepair, but I have never seen a web application that was architected with all of the above fundamental flaws.  Sadly, on the client-server side of things I have seen each of the above approaches used with regularity.  Applications that validate passwords by requesting them from the server, applications that treat the server simply as an ODBC connection, and applications that depend on SSL as their sole security control for preventing malicious user input and/or the disclosure of highly sensitive information (ex. those passwords being send back to the client from the server).  So, in short, if you are writing a client-server application, think of your client as the browser, and treat it with the same degree of trepidation.  The client cannot be trusted to enforce your security policy, and any expectation that it will do so is likely to result in an architectural flaw that may very well subvert the entirety of your security model.

2 thoughts on “How NOT to build your client-server security architecture

  1. Hello Patrick,

    I have been waiting for long to someone to make this kind of post. The things you are listing here are pretty self-evident, but as a RIA software architect there is one thing that has been troubling me for a very long time. In our application I have made the decision to hash the users password in client-side before passing it to server. The reason for this is to secure the password from man-in-the-middle -attack. Of course, if the attacker can falsify the RPC-calls he can still get to the data, but users password is not compromised (as it is hashed) and the attacker cannot still login using the real application.

    To put it bluntly: the password authorization and authentication is made in the server side, but the password string is hashed in client. Now the real question is, am I missing something here? For me this feels like more secure way to do the authentication than passing the password in clear text format and hashing it only when it hits the server, but I’m no way a security expert. I have had many times problems with sleeping because of this question. Maybe you can finally give me some answers whether or not this is a good thing to do and put my mind in rest.

    • Hey,
      So, while your thoughts around hashing to prevent a man in the middle attack sound like a good idea, in practice this isn’t advisable. You have, in effect, turned the password hash into the password. Hashing on the server allows the server to decouple the information being authenticated (the user’s password) from the way that information is being stored (the hash of the user’s password in the database). You haven’t prevented a man in the middle attack, as an attacker only needs to capture the user’s password hash to authenticate to the server using the scheme you described. One would be best to stick with preventing man in the middle attacks using SSL/TLS (since it was designed explicitly for this) and sticking with something like bcrypt on the server for password hashing.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s