I recently created a small website where users can sign-in (session is stored as a cookie with the flag HttpOnly).
Users can create and upload their own files and share some of them with their friends/colleagues or even make them completely public.
The issue I have is that these files can be HTML files that run their own custom JavaScript (and I would like to keep supporting this feature, i.e. allow them to have custom JavaScript).
But of course, since all of this is happening from the same domain there is no CORS to protect the user. This means it's possible to have a malicious user create a page with custom JavaScript that will fetch all the other files for the user that views this page (including private ones). And send these files to the malicious user. Additionally the custom JavaScript could also fetch other private information for that user from other endpoints.
Does anyone have any ideas of a good way to deal with this security risk (while still keeping the feature of allowing users to have their own HTML pages with custom JavaScript)?
Related
first of all before this gets marked as duplicate with CORS and X-header comments, let me prefice this by saying.. This question is strictly intended for LOCAL environments only.
I have written a website with .NET as backend that uses cookies and session-strings to maintain the authentication between the client and the website. However, a customer of ours want to disable authentication all together for all their users. Here is where the problem arises, our system rely on the fact that usernames and auth-data is sent along in most of our data-requests. So, the customer has agreed to use a static page with the username and password statically programmed (so that they wont have to login every time, but mearly open a chrome/firefox-shortcut on their desktop). This static page will redirect and pass along this static information to the "real" loginpage and sign in the user.
Illustration:
What are my options here?
Here's a screenshot of the req-headers in a successful login-post.
Thanks.
You want to serve your site from the backend and distribute a link to your site. Your client then bookmarks the link (or pins it to their home screen).
Serving static HTML files has fundamental limitations and you will hit a brick wall sooner or later (e.g. AJAX calls require the site to be served from some domain).
From here, there are a couple of options to do what you want.
The orthodox route is to delegate credential storage to the underlying OS. That is, just program the input forms as usual, issue Cookies as usual, and make sure the form HTML is such that the browser offers to save the credentials.
An alternative solution more in the vein of your initial proposal is to create what are known as signed URLs. You may create cryptographically signed URLs (e.g., http://localhost/your/site?hmac=<your_signature>) and hand that your client. Once you handle that URL in your server and verify the signature is valid, you may respond with a 301 redirect to your site, issuing the authentication cookie in the redirect response.
For background material, you may want to read about Post/Redirect/Get and Message authentication codes.
I developed a client side JavaScript functions and added them to the Dynamics 365 customer service solution as web resource using the recommended steps.
The functions were tested and operate as required when I am logged into the instance with Roles as a System Customizer and System Admin. But if login is as a user without these two Roles like a CSR Manager the JavaScript functions were not responding. On further investigation with client side developer tools in IE11, Chrome and Firefox I have verified that the JavaScript is in fact not downloading to the client browser for these users.
If I grant the System Administrator Role to the user the functions work fine and I can use client side debugger in the browser. As soon as I take away the Role and reload the browser the debug points I set do not pause and the JavaScript web resources are not downloaded.
I am not sure what's going on as no community forum or Microsoft docs article mentions any other requirements that secure the web resources or allow non admin users to view versus admin users.
CRM web resource (JS) cannot be rendered/controlled only for some security roles. It’s open for all.
But when you have different forms for different security roles, then there is a possibility of registered js libraries & functions missing in that particular form.
You cannot find anything like this any documentation/forum as this could be some admin/developer error.
If you enable multiple forms for Sys.Admin or CSR role, then form switcher will appear in record & you can test both behavior.
I see a couple of answers here talking about security roles and forms. If you have the jScript only on ONE form, it will not work for the others. So, you need to link that JS (whether a web resource or code you enter into the text editor) to every form you want the JSCRIPT to run on (in the Form Properties). It sounds like you have it running, and it works, for you and other users in the SysAdmin role. Have you tried this across all of your forms?
The second thing to check is what exactly your JScript code is doing. Is it only focused on one entity (the entity of the form you are injecting the JS to)? Is it updating, deleting, or appending something to the record?
As stated above, JScript and Web resources cannot be locked down by security (as far as I know), but if the user doesn't have the proper permissions to WRITE to an entity, you may see this behavior.
Update: Sorry, I lied. Web Resource is controllable through Security Role. It is in the Customization Tab, all the way at the bottom of the list (but above the Misc. Privs). You have the ability to set CREATE, READ, WRITE, DELETE permissions on this entity.
You might want to check the security roles that the non-SysAdmins have has at least READ on the Web Resource entity.
Thanks for all your responses. The issue was form "Enable Security Roles" related after all.
I am not sure whether by DEFAULT on custom form the security is only enabled for System Administrator and System Customizer Roles only OR one of my team members restricted access to these two roles.
But on reviewing these the and enabling the form for other Roles the JS script started to download for non admin users.
lesson learned do not assume, always check and double check especially in a team environment.
I'm building a website that is functionally similar to Google Analytics. I'm not doing analytics, but I am trying to provide either a single line of javascript or a single line iframe that will add functionality to other websites.
Specifically, the embedded content will be a button that will popup a new window and allow the user to perform some actions. Eventually the user will finish and the window will close, at which point the button will update to a new element reflecting that the user completed the flow.
The popup window will load content from my site, but my question pertains to the embedded line of javascript (or the iframe). What's the best practice way of doing this? Google analytics and optimizely use javascript to modify the host page. Obviously an iFrame would work too.
The security concern I have is that someone will copy the embed code from one site and put it on another. Each page/site combination that implements my script/iframe is going to have a unique ID that the site's developers will generate from an authenticated account on my site. I then supply them with the appropriate embed code.
My first thought was to just use an iframe that loads a page off my site with url parameters specific to the page/site combo. If I go that route, is there a way to determine that the page is only loaded from an iframe embedded on a particular domain or url prefix? Could something similar be accomplished with javascript?
I read this post which was very helpful, but my use case is a bit different since I'm actually going to pop up content for users to interact with. The concern is that an enemy of the site hosting my embed will deceptively lure their own users to use the widget. These users will believe they are interacting with my site on behalf of the enemy site but actually be interacting on behalf of the friendly site.
If you want to keep it as a simple, client-side only widget, the simple answer is you can't do it exactly like you describe.
The two solutions that come to mind for this are as follows, the first being a compromise but simple and the second being a bit more involved (for both you and users of your widget).
Referer Check
You could validate the referer HTTP header to check that the domain matches the one expected for the particular Site ID, but keep in mind that not all browsers will send this (and most will not if the referring page is HTTPS) and that some browser privacy plugins can be configured to withhold it, in which case your widget would not work or you would need an extra, clunky, step in the user experience.
Website www.foo.com embeds your widget using say an embedded script <script src="//example.com/widget.js?siteId=1234&pageId=456"></script>
Your widget uses server side code to generate the .js file dynamically (e.g. the request for the .js file could follow a rewrite rule on your server to map to a PHP / ASPX).
The server side code checks the referer HTTP header to see if it matches the expected value in your database.
On match the widget runs as normal.
On mismatch, or if the referer is blank/missing, the widget will still run, but there will be an extra step that asks the user to confirm that they have accessed the widget from www.foo.com
In order for the confirmation to be safe from clickjacking, you must open the confirmation step in a popup window.
Server Check
Could be a bit over engineered for your purposes and runs the risk of becoming too complicated for clients who wish to embed your widget - you decide.
Website www.foo.com wants to embed your widget for the current page request it is receiving from a user.
The www.foo.com server makes an API request (passing a secret key) to an API you host, requesting a one time key for Page ID 456.
Your API validates the secret key, generates a secure one time key and passes back a value whilst recording the request in the database.
www.foo.com embeds the script as follows <script src="//example.com/widget.js?siteId=1234&oneTimeKey=231231232132197"></script>
Your widget uses server side code to generate the js file dynamically (e.g. the .js could follow a rewrite rule on your server to map to a PHP / ASPX).
The server side code checks the oneTimeKey and siteId combination to check it is valid, and if so generates the widget code and deletes the database record.
If the user reloads the page the above steps would be repeated and a new one time key would be generated. This would guard against evil.com from page scraping the embed code and parameters.
The response here is very thorough and provides lots of great information and ideas. I solved this problem by validating X-Frame-Options headers on the server-side , though the support for those is incomplete in browsers and possibly spoofable.
The Webapplication we're currently building is using a .manifest file to make it available offline. In the top right of the application we display the username. All other context is requested through ajax.
Now the problem is that when the user log's out and a different one logs in the username field stays the same because the browser cached that page already.
So my question is: Is it possible to invalidate the manifest file upon logout with javascript?
I am aware that we could fill the username field through ajax too.
Thanks for your help
As much as I don't know a programmatically way to do it, a great common pattern for web apps is to use app cache for the resources that are common to all users and use other storage mechanisms (localStorage, indexedDB, etc) for specific user data.
I have an HTML5 app which is capable of running offline. However, I need to password protect the directory this app resides in to only allow access to authorized users. Initially I was using a PHP login page which set a cookie (outside of the app directory) then redirected to the app directory. The app (JavaScript) checks for the cookie and if it's there it lets the user run the app. If not, it redirects them back out of the app directory.
The problem with this method is that all of the files in the directory are still accessible if referenced directly (which I don't want). I do not want users to have to authenticate every time they hit the directory (it's a one-time authentication process; the cookie is there so that they never have to type their username/password again), and I also want to have a stylized login form (i.e. not using the default browser login box for http authentication).
Finally, because this is an offline HTML5 app, I can't include any PHP code in the app itself.
Any suggestions?
That doesn't sound like something you could do from Javascript. The script would need access to the file system to be able to restrict access to the folder, wouldn't it?
Unless this feature is exposed by the browser via a javascript API, I don't think it will be possible. It sounds like it would be a useful feature though.
Perhaps you could encrypt vital data, but apart from slowing down the application, I'm not sure what good it would do, since all the necessary keys would have to be stored locally as well...
Since the general rule of security on the web is that you can never ever rely on anything that happens client-side (e.g. in Javascript) without a double check on the server-side, this will of course pose a problem when the app is running offline and the server-side is not available :(
Looking at the "make Javascript redirect if the cookie exists" problem, unless I'm mistaken, it would be trivial for a malicious user to edit the Javascript, using for example Firebug, to redirect in any case.
EDIT: By the way, what level of security are you looking for? The "mom won't be able to accidentally access my account"-level (which it sounds like you already achieved), or the "no one, except maybe the NSA, should be able to hack it"-level?