-1

I am not asking how to hide Javascript code. There are plenty questions on that topic.

I'm building a website that gathers information about the user, e.g. the time between certain key presses. The webserver uses this to do research on key presses.

However, I think the system is quite prone to simple modification of the values. So a user can manually send values for key presses to the server.

I thought of doing encryption, but my first intuition was that the user is in charge of the browser so they have access to the keys.

Is there any way I can create a secret connection between the webserver and the webbrowser, that blocks the user from reading and/or modifying the data that is sent/received without the server being able to figure out?

Thomas Wagenaar
  • 6,489
  • 5
  • 30
  • 73
  • so you want to create a secret connection from client machine to your server without letting end user know about it.... No not possible – Kumar Nitesh May 17 '17 at 18:37
  • 1
    Don't encrypt it yourself, use a secured connection to an HTTPS endpoint so the real parameters can't be sniffed – Alon Eitan May 17 '17 at 18:37
  • I don't think so, the console logs all interactions as far as I know, but you could create a way to sign the data you send from your JS, but as everything that runs on client side, it could be hacked... – DIEGO CARRASCAL May 17 '17 at 18:39
  • Use https/wss, you can also eval script which sets up connection – Reski May 17 '17 at 18:40
  • @Knitesh that's exactly what I want yes – Thomas Wagenaar May 17 '17 at 18:54
  • @AlonEitan sniffing by other users is not the problem, I just don't want the user to modify the data their sending, making the data unuseful to me – Thomas Wagenaar May 17 '17 at 18:56
  • @ThomasW If the data is unuseful then don't process it on the server, return an error and maybe a **400 Bad Request** response header, you can't control what will be sent, but you can control how to deal with it – Alon Eitan May 17 '17 at 18:59
  • You should write code for not against clients... – Jonas Wilms May 17 '17 at 19:14
  • @Jonasw the user is aware of this datascraping. The average user won't notice the code running. It's just that I don't wanted some black hat guy simulating fake data. How is that writing 'against' clients? With that logic, banks and other companies protecting their javascript application and data transfer is also writing 'against' clients. – Thomas Wagenaar May 17 '17 at 19:26
  • @Thomas W, theyre not. You need to authenticate before you can talk to the banks server. Thats how they prevent someoje doing crap... – Jonas Wilms May 17 '17 at 19:30
  • The user could easily write a program in C or Java to simulate keyboard keypresses. There's no way to ensure that input signals coming from a machine have been generated by a human. – Gershom Maes May 17 '17 at 19:30
  • @GershomMaes I said e.g., it's a simplified question. The data i'm actually collecting can in no possible way be affected by another program - unless the user has access to the communication channel. – Thomas Wagenaar May 17 '17 at 19:34
  • @reski I don't think using eval() will actually contribute to the security of the system. . It's called​ evil() for a reason. – therebelcoder May 17 '17 at 19:45
  • @thomas If your Javascript has access to the communication channel, the user has it too... But I get what you mean. – therebelcoder May 17 '17 at 19:47

4 Answers4

1

In general, the server has no way of determining if a request it receives was created by your application's javascript code, or if the user did it from the developer console (for example).

There are probably some creative solutions you can do to make it harder for a malicious user to send requests that look exactly like the requests your application is sending, but it might be tricky.

Do you think it is likely you will actually have a significant number of users who would be interested in sending malicious requests? If not, you may not need to worry about this too much.

One solution to limit potential damage would be to filter out requests from any client that sends requests at a speed that a human cannot possibly type at, or if they are coming at unnatural intervals. E.g. 1 request a second, every second, for many minutes in a row. No one types like that, so those requests are likely malicious.

Daniel Waltrip
  • 2,530
  • 4
  • 25
  • 30
1

Short answer is no. If it's a web application, a user will always have access to all client-side source code (even any keys you store client-side).

that blocks the user from reading and/or modifying the data that is sent received

You can hide one user's communication from other users (as some commenters have pointed out, for example, using https), but this does not hide a user's communication from his/her self.

In theory you can obfuscate your JavaScript using a minifier to make it harder for them to figure out what the source code is doing, but obscurity is not security.

Community
  • 1
  • 1
Josh Beam
  • 19,292
  • 3
  • 45
  • 68
1

You can set-up a secure connection and use token-based verification. So yes it is possible. If not, banks and other companies that work with highly sensitive data and using Javascript SPA's would have a "small" problem. ;)

That being said, i don't think your application warrants this approach, since you only want to prevent someone from messing up your stats.

I would build-in a simple verification that will prevent most users from messing with your system and probably discourage the others because your data is simply not interesting enough to invest time in.

Just make up a password (encode it if you want and/or incorporate the date so it changes) and set it in the header of your POST call. When you distribute your Javascript code, you do it minified and obscured, without sourcemap!

Server side just check the header if the correct password is there, so you know it's send by your code.

Unhackable? Nope... But should be enough.

therebelcoder
  • 929
  • 11
  • 28
  • "You can set-up a secure connection and use token-based verification." The request that tracks keyboard events must be generated on the frontend, thus the token must be found in the frontend, either in the javasript code or loaded somehow. This can be obfuscated, but there is no technical limitation preventing the user from accessing this token -- it just takes careful grunt work. With banking, it is a different problem. We don't want **other** users or entities accessing the information for a particular account. HTTPS, XSS protection, and other techniques are used for this. – Daniel Waltrip May 17 '17 at 19:47
  • @daniel That part of the answer clearly didn't have my focus. And the way I simply put it, you are right. But a bank will probably combine it with session tokens and a solid oAuth implementation. – therebelcoder May 17 '17 at 19:59
1

As already mentioned, there is no absolute security, but there are some ways to scare off many hackers.

First, there may not be any global variables, because these can be easily modified:

(function() {
    "use strict";
    // your code goes here
})();

When you send a request to the server, you should also send a timestamp that is verified on the server (a small delay has to be factored).

You should also encrypt and decrypt the request manually (even if you use SSL, the plain text can be read in the browser console). For example, the Vignère chiffre is quite strong and not too difficult to implement. It's also not very common, so hackers might not expect it.

Last, but not least, your javascript needs to be obscured. This is very important because with the source code, the encryption can easily be broken.

Probably the best way is to use Google Closure Compiler and then JSF*ck (http://www.jsfuck.com/) to obscure the code. After that, the code consists only of these 6 characters: []()!+. Using a trick, it can be converted back, so make sure that the password is obscured well.


All this is very complicated, but there might be a better approach:

On the server side, you can try to detect unnatural typing behavior (if one is typing too fast or at a constant interval).

Aloso
  • 5,123
  • 4
  • 24
  • 41