62

Over the last few years, the trend for client-side (browser) applications has really taken off.

For my latest project, I have decided to try and move with the times and write a client-side application.

Part of this application involves sending transaction emails to users (for example, validate signup, password reset emails, etc.). I am using a third-party API to send the emails.

Normally I would have my application running on a server. I would call the third-party API from code on my server.

Running a client-side application means this now needs to happen on a user's browser. The third-party API provides the necessary JavaScript files to achieve this.

The first glaring issue I can see is I need to use an API key. This would normally be safely stored on my server, but now presumably I will need to provide this key to the client browser.

Assuming I can get round this problem, the next problem is what stops a tech-savvy user loading up the JavaScript developers tool on a browser and using the email API anyway they like, rather than say adhering to any rules I have set in the application.

I guess my general question is - how can we prevent malicious use of a client-side application?

GWed
  • 3,243

8 Answers8

200

You can't, and the more people understand this, and the deeper they understand, the better for the world.

Code that runs on a device under the user's control cannot be controlled. Smartphones can be jailbroken. Set-top boxes can be cracked. Ordinary browsers don't even attempt to prevent access to JavaScript code. If you have something worth stealing or abusing, a determined attacker will be able to do that unless you validate everything you cherish server-side.

Obfuscation is of very little help; the kind of opponent you will attract as soon as anything remotely financial is involved reads assembly language like classified ads. Encryption cannot help you, because the device that would guard the key is the same device you have to assume is cracked. There are many other, seemingly-obvious countermeasures that don't work, for similar reasons.

Unfortunately, this is a very inconvenient truth. The world is full of small-time and big-time operators who think they can somehow get around the fundamental brokenness of remote trust, simply because it would be oh so nice if we could assume that our code will be run the way we assumed. And yes, it would make everything so much easier that it isn't even funny. But wishing doesn't make it so, and hoping against hope that you are the one smart cookie who can avoid the unpleasantness will only burn you and your clients. Therefore, get into the mindset that the Internet is enemy territory, include that added cost in your estimates, and you'll be fine.

That said, of course there is such a thing as defense in depth. Obfuscating your JavaScript doesn't put off a determined attacker, but it may put off some less-determined attackers. If your assets are worth enough to protect, but not at any cost, any of those measures may add business value to your system; it just can't be perfect. As long as you are fully aware of the trade-off you are making, that may be a reasonable strategy.

Kilian Foth
  • 110,899
69

The rule here is:

Do everything client-side that doesn't affect anyone else if the user tampers with it. In particular, that means graphical effects.

Do everything server-side that needs to be secure, and just send UI events from the client (eg. then client just says "the user tapped the Buy button" while the server actually carries out the transaction). In particular, that means financial transactions.

jhocking
  • 2,631
28

This is exactly the case where making it a completely client-side application is not appropriate.

You can make the logic and basic validation of forms client-side (you still have to revalidate on server, because someone may try to fake the request) to improve responsiveness, you can do HTTP requests from JavaScript passing data there and back in JSON to avoid re-sending page decorations and such, but if the transaction itself needs to be authenticated and authorized, it should still happen on a server.

Jan Hudec
  • 18,410
17

Your middle paragraph is the heart of the problem:

Running a client side app means this now needs to happen on a users browser. The third party API provides the necessary js files to achieve this.

Why does a client side app mean you cannot have server-side work? The push towards client-side programming isn't about eliminating servers, but leveraging newer technologies that browsers finally support to make better user interfaces.

As for the .js file you received, are you sure it is meant for a browser? Could it be a node.js library?

Brandon
  • 4,575
11

Let's step back from this and take a higher level look.. shall we.. Did Eudora or outlook (a client side app, not even needing a browser) ever cause a financial loss for any company? No. Anyone could write to the POP/SMTP API's and be the client. But no loss to the server. The server didn't limit client actions, computations, storage, temperature, disk size, ram size, monitor DPI, GPU, FPU yada yada of the client but exactly specified what it would answer to and no more. Did you ever hear of quicken or MS-Money being used to break to a bank?

Your browser (i.e. client side) app can use the same architecture.

  1. You build your server with an API (which BTW, always boils down to derivatives of GET POST HEAD etc.).
  2. On the server, ensure that the API only talks with an authenticated and identity verified client for each and every call.
  3. Then you don't care who the client is.
  4. And then you don't care if it's a browser, jailbroken device, Google glass, DOS 3.1, or a brand new Nexus in the hands of a technophobe great-great-great-great-grandpa who has time traveled to 2014 and missed all the technology that's been flooding our lives in the last 15 decades.
  5. Now you can start off-loading everything else to client side.

SoapBoxBegin

@KilianFoth raises an important awareness point for the naive and the reckless, mainly those who read the headlines all the time but never think it will happen to their app, their code, their employer, their client, their own bank account. Even more reckless are their employers (especially the CTO's) who would allow apps to get out that expose any systems to unmanaged/uncontrolled exposure. However I'm always puzzled at how it seems "we never learn".

SoapBoxEnd

So to summarize. Make a solid and tight server side API. Offload everything else to client based on whatever the client can handle.

LMSingh
  • 277
6

I'd argue that you really can't. If you're willing to send the data to the client, you must expect that it will be abused - however possible. Your example regarding the API key is illustrative of the point, and I would not include that in your client side JS - it will be stolen and abused.

You definitely will still need some amount of server code to keep things secure. Even something as simple as retrieving just the data related to the logged in user. That authentication can't all be done client side or again you will be taken advantage of and your data is not secure.

I would always view the JS client side experience to be an addition to server code. Validation on client provides a nice user experience, but if you don't verify that POST data on the receiving server as well, you're opening yourself up to attack. Anything from the client should be considered suspect.

Matt Klinker
  • 179
  • 4
4

It's quite simple, really. Assume that the client computer and all software running on it is under complete control of a clever malicious hacker.

That means that any information that you send from the server to the client will be known to the malicious hacker, so you must make sure to send out no information to the client that could be used to attack your server or your business.

It also means that anything sent from the client to the server has been produced by the malicious hacker, so your server code must make sure that nothing the client could send would be capable of successfully attacking your server.

Admittedly, the implementation is a problem, but the important thing is the mental attitude, the assumption that the "client" you think your server is talking to isn't a client but an active attacker.

(You also need to assume that the user is a clever conman who will try to attack your business methods, but that has nothing to do with client-side programming).

gnasher729
  • 49,096
0

Client-Side application, in my opinion, is mostly about the UI. For example, all your UI system will be sent once to the client, and then the client would do whatever it wants with it.

Normally I would have my application running on a server. I would call the third-party API from code on my server.

Running a client-side application means this now needs to happen on a user's browser. The third-party API provides the necessary JavaScript files to achieve this.

If you have an API Key, then it's not intended to work on the client side. If you give the API Key on the client side, then anyone has access to it, and can then use it for it's own purpose. Store it and use it server-side when the client needs it, then send the result using Ajax/WebSockets.

It's like if your bank was saying : "Well, I'm going to put the password of the main database client side so that the client can request it himself and he will not bother our servers anymore."

Depado
  • 101