Security in embedded iframe/javascript widget - javascript

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.

Related

Share state between between AMP cache page and authentication page across domains

We have to implement a mechanism to protect content on our main www.oursite.com. We also have AMP pages being served from amp.oursite.com. Finally, the AMP pages are also getting served from the Google cache via https://www.google.com/amp/s/amp.oursite.com/
The mechanism that we want to implement is similar to a freewall which requires users to register and once they do, they will have access to most of the content on the website.
Registration and login happens on a subdomain such register.oursite.com.
We envisage a typical flow would be as follows:
User finds a page while performing a search on their mobile device via a Google search results.
They click on search result and are taken to the page on the google.com domain.
A pop-up or modal window (served over register.oursite.com) appears over the page with protected content asking them to login.
They login and on successful login, the pop-up or modal window disappears. (assumes user has registered at a previous point)
The protected content which was hidden or blurred in the main/parent window, appears so the user can proceed to read it.
We can assume that, upon successful login, a cookie (let's say named login-status) is dropped on the user's browser, scoped to .oursite.com which could serve as a flag.
The problem we are facing is that the page in the original window was served over the .google.com domain and therefore we do not expect that it would be possible for the main window to apply display logic on the content based on the cookie named as login-status.
It would appear from this page that the way to solve this challenge is via identifier reconciliation on the server by maintaining a matching table between the reader id that AMP generates and the cookie. We have looked at the AMP access feature and AMP page implementation for New York Times but we cannot tell for sure whether they have achieved this via server side or client side solution.
Can anyone
validate the assumption that it is not possible somehow via AMP to share the login state of a user between 2 windows with content served over different domains?
suggest a way to solve this on the client side rather than the server side?
Thanks in advance

how to limit access to my iframe widget using CSP cookies and http referer

I am developing a web application (like a widget) that my potential clients will use on their websites for the benefit of their users. I was thinking about the best way to deliver the application to them and at the same time be able to control who is using my widget so that I can bill them correctly.
I checked a few previous posts like iframe for a widget and iframe best practices limitations and JS to load iframe but they are 7-10yr old and not exactly what I'm trying to do.
That being said, so far ... the best way to deliver seems to be a combination of:
iframe
Content-Security-Policy frame-ancestors HTTP header
cookies + $http_referer checks on the server side to avoid sneaky users
On the load I'm going to send a secret key with URL to deliver a customized/branded version and I'm planing to rely on cookies for subsequent calls
I have a few questions here:
Should I use an iframe tag with specific URL directly, like
<iframe src="https://superwidget.com/SecretKey=12345678"></iframe>
or should I use a JavaScript to load/create iframe element using the same URL? Is there any benefit from using one or another except being able to defer a load of an iframe in the JS version?
So I'm planing to use iframe / CSP / http referer / cookie combo ... Is there any other (better) way to deliver a widget and make sure only allowed audience using it?
Anything else I'm missing here
Any help appreciated!
My recommendation would be to use javascript.
That way, in your javascript, you can validate if the DOMAIN NAME for the page that the javascript is called from is authorized for that client's token.
If it is, load the IFrame with the custom content.
This will also allow you to have greater control over user experience.
If I were you I would use a simple iframe. The page should be retrived with a key (eg. ?key=some-special-key-in-base-16-58-or-64).
You backend should later on verify that the Refer: not-your-site.com header is whitelisted for that specific API key.
If, instead, you need to use a js widget, you could use the key as a param when requesting the js file and let the verification backend use the classic Host: not-your-site.com header.
You could send a custom widget that asks them to pay/renew the system if the key or the refer is not valid. Some people visitng the site might not like this idea so think carefully about implementing it. If you are not on top of the pyramid of the team let someone with more responsabilty choose.
The advantage of using an iframe widget over a js one is that it has a sandbox and therfor cannot be accesed by the parent site. Please note that it might be a disvantage if you want to let your consumers to modify the widget with their own js.
Please note that SCP has to always be set correctly if you want all of this to work.
Last tip: Using the hosts file to fake two sites on the same machine won't work, on Windows 10 at least, so you'll have to use two different machines.

Posting form-data through another page

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.

How do end users (hackers) change Jquery and HTML values?

I've been looking for better ways to secure my site. Many forums and Q/A sites say jquery variables and HTML attributes may be changed by the end user. How do they do this? If they can alter data and elements on a site, can they insert scripts as well?
For instance I have 2 jquery scripts for a home page. The fist is a "member only" script and the second is a "visitor only" script. Can the end user log into my site, copy the "member only" script, log off, and inject the script so it'll run as a visitor?
Yes, it is safe to assume that nothing on the client side is safe. Using tools like Firebug for Firefox or Developer Tools for Chrome, end users are able to manipulate (add, alter, delete):
Your HTML
Your CSS
Your JS
Your HTTP headers (data packets sent to your server)
Cookies
To answer your question directly: if you are solely relying on JavaScript (and most likely cookies) to track user session state and deliver different content to members and guests, then I can say with absolute certainty that other people will circumvent your security, and it would be trivial to do so.
Designing secure applications is not easy, a constant battle, and takes years to fully master. Hacking applications is very easy, fun for the whole family, and can be learned on YouTube in 20 minutes.
Having said all that, hopefully the content you are containing in the JS is not "mission-critical" or "sensitive-data". If it is, I would seriously weigh the costs of hiring a third party developer who is well versed in security to come in and help you out. Because, like I said earlier, creating a truly secure site is not something easily done.
Short Answer: Yes.
Anything on the users computer can be viewed and changed by the user, and any user can write their own scripts to execute on the page.
For example, you will up vote this post automatically if you paste this in your address bar and hit enter from this page:
javascript: $('#answer-7061924 a.vote-up-off').click();
It's not really hacking because you are the end user running the script yourself, only doing actions the end user can normally do. If you allow the end user on your site to perform actions that affect your server in a way they shouldn't be able to, then you have a problem. For example, if I had a way to make that Javascript execute automatically instead of you having to run it yourself from your address bar. Everyone who came to this page would automatically upvote this answer which would be (obviously) undesired behavior.
Firebug and Greasemonkey can be used to replace any javascript: the nature of the Browser as a client is such that the user can basically have it do anything they want. Your specific scenario is definitely possible.
well, if your scripts are public and not protected by a server side than the Hacker can run it in a browser like mozilla.
you should always keep your protected content in a server side scripting and allow access by the session (or some other server side method)
Yes a user can edit scripts however all scripts are compiled on the user's machine meaning that anything they alter will only affect their machine and not any of your other visitors.
However, if you have paid content which you feed using a "members-only" script then it's safest if you use technology on the server to distribute your members-only content rather than rely on the client scripts to secure your content.
Most security problems occur when the client is allowed to interact with the server and modify data on the server.
Here's a good bit on information you can read about XSS: http://en.wikipedia.org/wiki/Cross-site_scripting
To put it very simply:
The web page is just an interface for clients to use your server. It can be altered in all possible ways and anyone can send any kind of data to your server.
For first, you have to check that the user sending that data to your server has privileges to do so. Usually done by checking against server session.
Then you have to check at your server end that you are only taking the data you want, and nothing more or less and that the data is valid by validating it on your server.
For example if there is a mandatory field in some form that user has to fill out, you have to check that the data is actually sent to server because user may just delete the field from the form and send it without.
Other example is that if you are trying to dynamically add data from the form to database, user may just add new field, like "admin", and set it to 1 and send the form. If you then have admin field in database, the user is set as an admin.
The one of the most important things is to remember avoid SQL injection.
There are many tools to use. They are made for web developers to test if their site is safe. Hackbar is one for example.

How can I automatically answer a password prompt from an embedded item in an (X)HTML page?

I wrote a web page that displays images from several servers on my network via simple img tags with appropriate href values. The servers require authentication before they will send the images.
It works alright, except on first load the page presents the user with a series of password prompts (one for each server). The user can select the "Remember my password" checkbox, and then subsequent refreshes of the page work without prompting, with correctly updated images. That is, until someone closes out the browser, after which a new set of prompts awaits anyone who opens the page again.
All of the credentials needed are known beforehand, and I don't care if someone could read them in the page source, since this page is in a protected part of an internal intranet site. Everyone with access to this page knows the passwords anyway.
The only browser we're allowed to use is IE 7, so I don't care about compatibility with other browsers at the moment.
Is there any way I can use JavaScript (or some other client-side code) to automatically answer those prompts so the user never sees them?
Thanks very much, in advance.
You can include the authentication in the URL:
<img src="http://paulfisher:tastybacon#internalwebs/path/to/image.png">
Where, of course, paulfisher is my username and my password is tastybacon.
No, javascript can't do this. Here are a couple of options that I've used before to solve this problem:
Change the authentication on the other servers to be either anonymous or integrated.
Proxy in the images: On the server serving the page, add another page that takes in the URL of the remote server. This new page makes a webrequest to the other server and streams the image back. The webrequest can plug in the correct credentials.
Depending on the servers' DNS names, it might be possible to share an authentication cookie across all of the servers. Then you could set up some kind of module on all of the servers to allow the shared authentication.

Categories

Resources