hide fetched user data from backend - security

I am looking for how to to get user data and expose it in the UI without show it elsewhere in devtools - so I would like that data doesn't appear in any request response.
I considered different possibilities, as cookies or session but none of them allow to hide the data before it is displayed in the UI.
So I wonder what the usual practice is and if using socket.io would be considered a hack?
The idea is:
User is logged and visits some page, regular API requests are made and serve UI display, and is required user data for UI purposes.
As an example:
Are displayed elements to which it is possible to subscribe, so depending of user and of its subscriptions, style is different between followed and unfollowed elements.
Thank you in advance for your help.

I don't get the "why" you would want to do that. The normal user doesn't open devtools. The "hacker" user will most certainly not be prevented from getting that data. In the end there're more tools than just the browser's devtools to sniff incoming and outgoing data and since that is something you cannot prevent, there's no reason to do it in the browser in the first place.
What you can do though is encrypting the response in your backend and then decrypt in your frontend. Since you need to send the decryption password as well this will still not prevent anyone from decrypting the response messages, but obfuscating the decryption part somewhere in your code can at least make it a little more difficult (emphasize "little").

Related

Is it possible to send form data to server from developer tools

I just learnt one can manipulate the frontend code of a website from the developer tools that comes with some browsers. Now, my question is that if someone can manipulate my js, HTML and CSS codes to suitable needs, and was able to send a request to my webserver, will the server receive and process the request as authenticated request. Let me site a suitable example:
Let's say I created a form that uses ajax to retrieve some information from my webserver, in the form I have a hidden input that contains numbers which determine the information that will be displayed (e.g. 1 should display information for level 1 users, 2 should display information for level 2 users). The default value of the hidden input is 1, now if the user (level 1) is able to tweak the frontend code and set the value to 2 before sending, will he receive the information meant for level 2.
If this is possible, how can I prevent such thing from happening, or what is the standard procedure for handling situations like this?
The typical rules in this case are:
Validate
Validate
Validate
Do not trust the client exclusively to tell you whether they have the permission or not. You should have the information to determine that on the server side, use it.
Validate client side requests, and make sure the user that is requesting an action has the actually has permissions to do so, and that the data they are sending is valid.
Sure, you can have client side validation for a good UX experience, but always backstop it with server side validation, authentication and authorization.
The best way to prevent your example scenario is: Don't send the client side data they aren't supposed to see and then rely on the client to hide it. If the user isn't supposed to see it, don't send it.

is authentication with client side rendered app and sessions possible?

No matter how I reason about it, it seems as if there is no secure way of implementing a client side rendered single-page-application that uses/accesses information on sessions for authentication, either via cookies, without severe compromise in security. I was mainly looking to building a React app, but it seems as if I will need to build it with SSR for a relatively secure version of authentication.
The use case that I'm especially thinking of is where the user logs in or registers and then gets a cookie with the session id. From there, in a server side implementation, I can simply set up conditional rendering depending on whether the server stored session has an associated user id or not and then pull the user information from there and display it.
However, I can't think of a client-side rendered solution where the user can use the session id alone on the cookie that isn't easily spoofable. Some of the insecure implementations would include using browser storage (local/session). Thanks.
I think the major issue here is that you are mixing the two parts of a web page (at least according to what HTML set out achieve) and treating them both as sensitive information.
You have two major parts in a web page - the first being the display format and the second being the data. The presumption in client side rendering / single page applications is that the format itself is not sensitive, and only the data needs to be protected.
If that's the case you should treat your client-side redirect to login behavior as a quality of life feature. The data endpoints on your server would still be protected - meaning that in theory an unauthenticated user could muck about the static HTML he is being served and extract page layouts and templates - but those would be meaningless without the data to fill them - which is the protected part.
In practice - your end product would be a single page application that makes requests to various API endpoints to fetch data and fill in the requested page templates. You wouldn't even need to go as far as storing complex session states - a simple flag notifying the client if it is authenticated or not would suffice (that is beyond what you would normally use for server-side authentication such as cookies or tokens)
Now let's say I'm a malicious user who is up to no good - I could "spoof" - or really just open the browser dev tools and set the isAuthenticated flag to true letting me skip past the login screen - now what would I do? I could theoretically navigate to my-service/super-secret without being redirected locally back to the login page on the client side - and then as soon as the relevant page tries to load the data from the server with the nonexistent credentials it would fail - best case displaying an error message, worst case with some internal exception and a view showing a broken template.
So just to emphasize in short:
A. If what you want to protect is your TEMPLATE then there is no way to achieve this clientside.
B. If what you want to protect is your DATA then you should treat gating/preventing users from navigating to protected pages as a quality of life feature and not a security feature, since that will be implemented on the server when serving the data for that specific page.

How can I send cookies from a bookmarklet XMLHttpRequest which belong to the site being accessed?

I'm trying to create a bookmarklet which needs to hit a server (using a POST) to obtain some data. Accessing that data requires that I am logged in, which is kept track of by using cookies. The problem is, my bookmarklet is running in the context of some random web site, and so it can't access the cookies belonging to the site I am trying to hit and in fact it doesn't even send the cookies that belong to that web site.
I have seen some hints that suggest that what I am trying to do is possible, but which are a bit unclear on exactly how this could be accomplished. For instance, in this question, the accepted answer includes this tidbit: "Very often these types of bookmarklets open a small popup for the user which contains a page from the app" but I do not understand how this would accomplish what I am trying to do. I assume it has something to do with the fact that the page itself is in the proper domain and thus can send the required cookies, but I'm not sure how to get data into the page to tell it what I want (I suppose I could do something where I encoded the request in the URL parameters, but then this would show up in the http logs which is not desirable), but more importantly I am not sure how I would get the data back from the window - whenever I try I get an exception "Permission denied to access property 'document'" (or whatever I try to access). I also get the same problem if I use an IFRAME and try to access the parent from the child (or the other way around).
You have asked several quetions.
1.) How can I send cookies from a bookmarklet XMLHttpRequest which belong to the site being accessed?
XMLHttpRequest will send cookies belonging to the domain you are calling. If you want to cross domains you have to enable CORS: http://enable-cors.org/
2.) "Very often these types of bookmarklets open a small popup for the user which contains a page from the app"
This is not about making an XMLHttpRequest. The data goes into the popup via GET. You can even do this via POST but it is slightly more complex. Just search "post to popup" or "post to iframe".
3.) I am not sure how I would get the data back from the window
If the other window/iframe is holding a page from a different domain, use postMessage: https://developer.mozilla.org/en-US/docs/Web/API/window.postMessage - this can actually go in both directions and can actually be used to enable complex cross domain communication without CORS.

sfGuard token login for wkhtmltopdf

wkhtmltopdf allows to make a screenshot of a browser view with a webkit browser.
I have a Symfony 1.4 application that requires login, which I would like to use wkhtmltopdf to create a "print this page" function.
How can I securely facilitate this. I'm thinking of creating a one-off token on each screen for the print button that allows wkhtmltopdf to login without using the password of the user.
Any suggestions for how to structure this?
We'vbe come to the conclusion to use the built in "keep me logged in" functionality for this problem.
Would you consider a different printing framework ?
What about jquery plugin (e.g. https://github.com/ianoxley/jqueryprintpage#readme) ?
That way you won't have to allow access to the restricted area from outside the session.
If you still want to use wkhtmltopdf, you can easily create an action that receives a url and a user_id and creates a unique token, I might save this token in your DB or in a Key-Value cache (depends what is your system architecture). I wouldn't create the unique token in advance, I think its better creating it on demand (When your user is asking a print).
You have couple of options in order to enable printing in secured actions,
1) Create a custom security filter. In the filter, in addition to authenticated request, you have to allow requests that contain "token" parameter with right combination of url and user
2) Change the action to unsecured. If you don't want the change the security filter, you would have to change each action to "unsecured" and create a function that verifies if either the request is authenticated or it has a proper token parameter.
It would be smart to remove each token after you used it once to make it even harder to guess a token.
In addition you might want to create a periodic worker that clears old tokens that were never in use.
Even though you already decided on an approach, I would still like to add one more alternate option that might help others viewing this issue.
Another alternate route might be to grab the current source of the page being viewed and post that into your printer backend using something like
$.post("/printer", document.documentElement.outerHTML);
This way you can also preprocess the HTML in an easy way. Your backed could first store the HTML and then parse it to for example convert images or perhaps remove some parts of the page that will not be used when printing.

Programmatic Bot Detection

I need to write some code to analyze whether or not a given user on our site is a bot. If it's a bot, we'll take some specific action. Looking at the User Agent is not something that is successful for anything but friendly bots, as you can specify any user agent you want in a bot. I'm after behaviors of unfriendly bots. Various ideas I've had so far are:
If you don't have a browser ID
If you don't have a session ID
Unable to write a cookie
Obviously, there are some cases where a legitimate user will look like a bot, but that's ok. Are there other programmatic ways to detect a bot, or either detect something that looks like a bot?
User agents can be faked. Captchas have been cracked. Valid cookies can be sent back to your server with page requests. Legitimate programs, such as Adobe Acrobat Pro can go in and download your web site in one session. Users can disable JavaScript. Since there is no standard measure of "normal" user behaviour, it cannot be differentiated from a bot.
In other words: it can't be done short of pulling the user into some form of interactive chat and hope they pass the Turing Test, then again, they could be a really good bot too.
Clarify why you want to exclude bots, and how tolerant you are of mis-classification.
That is, do you have to exclude every single bot at the expense of treating real users like bots? Or is it okay if bots crawl your site as long as they don't have a performance impact?
The only way to exclude all bots is to shut down your web site. A malicious user can distribute their bot to enough machines that you would not be able to distinguish their traffic from real users. Tricks like JavaScript and CSS will not stop a determined attacker.
If a "happy medium" is satisfactory, one trick that might be helpful is to hide links with CSS so that they are not visible to users in a browser, but are still in the HTML. Any agent that follows one of these "poison" links is a bot.
A simple test is javascript:
<script type="text/javascript">
document.write('<img src="/not-a-bot.' + 'php" style="display: none;">');
</script>
The not-a-bot.php can add something into the session to flag that the user is not a bot, then return a single pixel gif.
The URL is broken up to disguise it from the bot.
Here's an idea:
Most bots don't download css, javascript and images. They just parse the html.
If you could keep track in a user's session whether or not they download all of the above, e.g. by routing all of the download requests through a script that logs the attempts, then you could quickly identify users that only download the raw html (very few normal users will do this).
You say that it is okay that some users appear as bots, therefore,
Most bots don't run javascript. Use javascript to do an Ajax like call to the server that identifies this IP address as NonBot. Store that for a set period of time to identify future connections from this IP as good clients and to prevent further wasteful javascript calls.
For each session on the server you can determine if the user was at any point clicking or typing too fast. After a given number of repeats, set the "isRobot" flag to true and conserve resources within that session. Normally you don't tell the user that he's been robot-detected, since he'd just start a new session in that case.
Well, this is really for a particular page of the site. We don't want a bot submitting the form b/c it messes up tracking. Honestly, the friendly bots, Google, Yahoo, etc aren't a problem as they don't typically fill out the form to begin with. If we suspected someone of being a bot, we might show them a captcha image or something like that... If they passed, they're not a bot and the form submits...
I've heard things like putting a form in flash, or making the submit javascript, but I'd prefer not to prevent real users from using the site until I suspected they were a bot...
I think your idea with checking the session id will already be quite useful.
Another idea: You could check whether embedded resources are downloaded as well.
A bot which does not load images (e.g. to save time and bandwidth) should be distinguishable from a browser which typically will load images embedded into a page.
Such a check however might not be suited as a real-time check because you would have to analyze some sort of server log which might be time consuming.
Hey, thanks for all the responses. I think that a combination of a few suggestions will work well. Mainly, the hidden form element that times how fast the form was filled out, and possibly the "poison link" idea. I think that it will cover most basis. When you're talking about bots, you're not going to find them all, so there's no point thinking that you will... Silly bots.

Resources