I am creating a website which allows users to make their website alive for a certain amount of time. It works like this:
user uploads a .zip file containing javascript/html/css/image.
filtering the files using whitelist to remove unallowed extensions>
a new subdomain will be made with a random name containing the unzipped files.
and the user now can view his design.
so what security issues may result due uploading javascript/html/css files?
All of the files are potential security hole. JavaScript, HTML and CSS files could be dangerous because all of them may have JavaScript code in them. By allowing people to upload files that contain JavaScript code you're letting them upload code that will be executed by visitors' browsers.
On modern browsers, embedding JavaScript code in CSS files isn't a real problem. But if you expect to support older browsers, such as IE6 or 7, then the CSS files are a potential security hole as well.
A common technique used by attackers is Cross-site scripting, or XSS. Basically, attackers inject JavaScript code on a website, by using a form or some low-security API that allows visitors to send information to the website. That JavaScript code may then be executed by all other users, and could steal sensitive information. Here's some more information on it: https://en.wikipedia.org/wiki/Cross-site_scripting
Now, because all websites reside in different subdomains, they actually have different origins, and thus the browser will prevent one website's JavaScript from fiddling with another website's cookies. This is called the Same origin policy, and its described in more detail here: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
Do bear in mind that one of these malicious JavaScript files could change its origin by running the following code:
document.domain = "yourdomain.com";
And that could be a potential threat.
Also, the Same origin policy has different behaviour on some browsers, such as Internet Explorer. It's ideal that you read the documentation on it for the most common web browsers.
Related
I am building small offline web app using HTML and JavaScript. CSV file is used to store data.
To read CSV (using jquery-csv library) file I use following code.
<script>
$(document).ready(function(){
var filepath = 'data.csv';
var data_string = $.get(filepath);
});
</script>
But I can't read it because of following error.
XMLHttpRequest cannot load
file:///C:/Users/Nimal/Desktop/javascript-csv/data.csv. Cross origin
requests are only supported for protocol schemes: http, data, chrome,
chrome-extension, https
Then I could learned about same origin policy concept.
Then, I found many related articles from here.
"Cross origin requests are only supported for HTTP." error when loading a local file
XMLHttpRequest cannot load file. Cross origin requests are only supported for HTTP
Ways to circumvent the same-origin policy
From Wikipedia,
In computing, the same-origin policy is an important concept in the
web application security model. Under the policy, a web browser
permits scripts contained in a first web page to access data in a
second web page, but only if both web pages have the same origin.
But I have a problem.
If I use <img src="abc.jpg"> I can load the image.
Why is there an exception for images?
How all we can load images, but we can't load other file types?
I thought same origin policy should apply all file types including images.
Or have I understand same-orgin-policy wrongly?
To comprehend the problem, you have to understand the same origin policy (hereafter called as sop) and how it's being handled. It is an important concept when writing an application that allows users to browse the world wide web. Before that concept, many security violations has occurred.
In short, you can see sop as a tuple with three elements: (scheme,host,port).
scheme: the protocol. HTTP and HTTPS are different.
host: the url after the scheme. stackoverflow.com is different to google.com
port: https://stackoverflow.com is different to https://stackoverflow.com:9876/question (reason: default port is usually 80)
When you are visiting a page with a script that obtains information from multiple URLs. The tuple on this page is eg. tuple_main. If the script loads content from another URL, a tuple is generated from the URL: tuple_request. Two situations can occur here:
1) tuple_main == tuple_request
===> OK => get content
2) tuple_main != tuple_request
===> NOK => do not get content and show that sop is being violated.
Initially, the sop is invented to protect content in your DOM against malicious adversaries. Throughout the years, this got broadened to secure other parts of the information that the browser is handling. A most notable example is the global javascript variables. 10+ years ago, developers started to store sensible information in their javascript as var foo in global space. It was easy for malicious adversaries to get it and abuse it...
Other extensions were added to secure Adobe Flash, MS Silverlight plugins, javascript mechanisms (like XMLHttpRequest), ect ... throughout the years. The sop ensures that the content of the webpage you are visiting does not leak to malicious adversaries (mostly by XSS)
Now, your question was initially (which is a description of the problem):
To read CSV (using jquery-csv library) file I use following code.
<script>
$(document).ready(function(){
var filepath = 'data.csv';
var data_string = $.get(filepath);
});
</script>
But I can't read it because of following error.
XMLHttpRequest cannot load file:///C:/Users/Nimal/Desktop/javascript-csv/data.csv. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https
Since the tuple is different, you are violating the sop. So you will get this message of course.
But your main question is
If I use <img src="abc.jpg"> I can load the image.
Why is there an exception for images?
To answer that, another concept and (eh ...) some history (old IE ages) are used here. To give developers means to use resources from a different sop location, a cross-origin concept is added. From this concept, there are three mechanisms (source):
Cross-origin writes.
Here, we are talking about links to another sites, HTTP redirects and form submissions.
Cross-origin reads
"Reading from another source" which is discouraged. But you can work-around it by embedding it. This leads us to the last mechanism:
Cross-origin embedding
This is what you were doing when loading the csv file. This mechanism is added to allow web developers to use content from other sources such as stylesheets, scripts, images... You can see this as an "exception to the Same origin Policy principle".
If you are building a web page and you want to use jQuery (a script), then the browser will load that script. But embedded. You can run the script, but not read the content of the <script> tag.
That's what happens here at images. When loading the image by <img> tag, the browser is only reading the image. It cannot access the content (the byte information behind the file name that describes the whole image). Therefore, you can see the image on the page you're viewing.
If you want to load the image in a <canvas> element, then it will not be able to do so because it violates the rules. Your script is trying to access the byte information behind that file name. That is not allowed.
Why was I talking about IE history? Well, long time ago, IE was a mainstream browser. Since many companies started to "come online" they have build applications that uses IE for their business tasks. For example a financial employee was using IE to have a monthly summary of sales.
But the same origin policy was not extended in the way we have now. Loading sources from other domains were "not an issue". Companies started to setup websites with third party scripts (Ext js was used heavily back then), third party stylesheets and "third party" images. There are images on the world wide web that are free-to-use (and hosted by sites like tinypic, imageshack, ...). Lots of companies have used these images for their websites.
If those exceptions were not implemented, then lots of legacy websites would break. Images would not load. Scripts would not run. The economical cost of fixing it would be huge. So to anticipate that, this embedding mechanism got added.
A personal note: I am kinda happy that this exception exists otherwise maintaining a website would be a developer nightmare. If the sop is strict as intended, then you have to download the scripts and images and host it from your server. By this, your website can access these and use these. If a script got an update, you have to download it and overwrite your local script...
You are trying to read the content of the csv file which violates the security measurements behind the embedding mechanism.. Since it contains sensible information that should not be leaked to malicious adversaries, the browser informs you that you cannot load it. Just to prevent you for some security problems.
If you want to work locally, you have to use CORS. Or launch the browser without sop restrictions (albeit I don't recommend it).
When you have all these various javascript files included on a page for various services like website analytics, click tracking etc., doesn't this create a huge security risk because using javascript they can hijack the persons credit card that is entered on the form?
How is this even considered to be safe currently?
Meaning, your server is security, your payment provider is secure, you have SSL, but if someone was to hack into any of these services people use (I see over 10+ services many sites use to track clicks, ad related, etc) then they can comprise your payment form.
Yes this is a security risk, known as a third party script include.
By including a script on your page hosted by a 3rd party, you are trusting that the external domain is not malicious nor compromised. By using a <script src="//example.com"> tag, the third party domain has full control of the DOM on your site. They can inject whatever JavaScript they wish.
You are right to be concerned. PageFair was recently compromised bringing down every site that it offered its analytics service to with it. You should verify all third party domains that you are referencing for script, and ensure you trust them. For example you are probably OK with the big guys such as Google and Facebook, however any others you should consider either dropping them or reviewing the script code and then hosting locally on your domain instead.
You can mitigate this with subresource integrity:
<script src="https://example.com/example-framework.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"></script>
This will ask the browser to check that the loaded script has the specified cryptographic hash. Any changes to the script, even as much as a single character, would produce a completely different hash enabling any changes to be detected and the script would be rejected from loading and running. As of August 2018, all major browsers support it except for IE and iOS Safari.
EDIT: As has been pointed out to me in the comments, you cannot solve all of your JavaScript security problems by downloading all of the resources over HTTPS, as I asserted in a previous version of this answer. Instead, that simply reduces the problem to how much your end user can safely trust the provider of the JavaScript itself - and if the service gets compromised or is an actively malicious organization, they can't.
There are two primary ways that hosts can solve this problem and make their JavaScript downloads more reliable for their users:
Where it doesn't make sense, don't include the JavaScript component at all. One thing you will notice on Amazon.com, for instance, is that while the normal shopping pages have header bars and are full of extra information and advertising and all that, the actual checkout page, where you enter your payment information, is almost blank - most of the styling and scripting is not included, and there are certainly no ads on the page.
If you need the component, but can host the script yourself, do so. That way, unless you yourself are compromised, you can be confident that any script being downloaded by the user is not, because you are providing it. For offline scripts that don't actively communicate with other services, this is often needed anyway for compatibility reasons, and many online scripts can also be included here without too much loss in functionality.
I am creating a HTML page where I need to display the names of the files present in the specific local folder, example - C:\Users\User1\Documents\folder1 . I tried to write the code in java script but have not succeeded yet. Most of the question threads mention about "ActiveXObject" to be used but that itself does not work for me.
Reference: JavaScript: Read files in folder
Can anyone help me in achieving this?
In general, you can't do that. Web pages do not have access to the local filesystem.
Chrome can access the contents of a directory that is selected using a file input field. However, other browsers, such as Internet Explorer and Firefox, have not implemented this feature at this time, nor is there currently any way to access a directory that was not selected by the user.
In theory, it is possible to read arbitrary files using a signed Java (not Javascript) applet. However, this requires the user to approve a series of extremely scary warning dialogs — and requires Java! — so it's really not a viable solution.
I'm afraid I may be the bearer of bad news for your design: The action you are requesting expressly violates the security model as specified in the File API spec. The client implementation of FileReader() must make sure that "all files that are being read by FileReader objects have first been selected by the user." (W3C File API , 13. Security Considerations: http://www.w3.org/TR/FileAPI/#security-discussion).
It would be a huge security risk of browser scripts could just arbitrarily open and read any file from a path without any user interaction. No browser manufacturer would allow unfettered access to the entire file system like that.
Thinking about it however, if it is all being run locally, you could use ajax to query a server side script that could return the directory you request.
I am creating a HTML page where I need to display the names of the files present in the specific local folder, example - C:\Users\User1\Documents\folder1 . I tried to write the code in java script but have not succeeded yet. Most of the question threads mention about "ActiveXObject" to be used but that itself does not work for me.
Reference: JavaScript: Read files in folder
Can anyone help me in achieving this?
In general, you can't do that. Web pages do not have access to the local filesystem.
Chrome can access the contents of a directory that is selected using a file input field. However, other browsers, such as Internet Explorer and Firefox, have not implemented this feature at this time, nor is there currently any way to access a directory that was not selected by the user.
In theory, it is possible to read arbitrary files using a signed Java (not Javascript) applet. However, this requires the user to approve a series of extremely scary warning dialogs — and requires Java! — so it's really not a viable solution.
I'm afraid I may be the bearer of bad news for your design: The action you are requesting expressly violates the security model as specified in the File API spec. The client implementation of FileReader() must make sure that "all files that are being read by FileReader objects have first been selected by the user." (W3C File API , 13. Security Considerations: http://www.w3.org/TR/FileAPI/#security-discussion).
It would be a huge security risk of browser scripts could just arbitrarily open and read any file from a path without any user interaction. No browser manufacturer would allow unfettered access to the entire file system like that.
Thinking about it however, if it is all being run locally, you could use ajax to query a server side script that could return the directory you request.
I am posting this question on Super User as well. In my opinion this question overlaps the two...
I am creating a simple JavaScript wrapper for CouchDB's REST-ful interface, but I am stuck on same-origin policy issues.
So far I've been developing my code to work locally - and only as a proof of concept - on Mozilla FireFox. My server is running on localhost, port 5984.
To disable cross-origin policy in Mozilla FireFox you can use the PrivilegeManager, but it only gets me half-way in the sense that I can't do PUT requests against my server...
/*
* Including this in my JavaScript file only seems to disable cross-origin
* policy checks for POST and GET requests in Mozilla FireFox.
* PUT requests fail.
*/
netscape.security.PrivilegeManager.enablePrivilege(
"UniversalBrowserRead UniversalBrowserWrite"
);
Is there any way that I can configure my server to hide it's location so I won't have to implement browser-specific work-arounds to avoid same-origin policy issues? If not: what browser work-arounds exist to disable same-origin policy completely?
Unfortunately, any browser workarounds to disable same-origin policies are likely to be treated as serious security bugs and fixed as soon as possible.
See if you can come up with a way to work within the same-origin policy without trying to bypass it.
Can you serve your example scripts on the target server? Could you build a reflection script that would load the target script on your server after a local script on the users computer uploaded whatever they modified?
There should be a good solution that doesn't involve bypassing the same-origin policy. Trying to hack your way around it is a good way to ensure that your code doesn't work properly in future browsers.
I strugled with that issue too, trying to run automated tests on a local html file connecting to a virtualized CouchDB server, here's my solution:
I created a small implementation (and open sourced it) of the simplest solution when you can't enable CORS on the server,
you need to upload a .js and an .html file to the target server, (you can use any security mechanism to restrict access to this file if you want). Or you can change some simple parameters on the html file to restrict by domain.
On your page you use the same script to create an invisible iframe where the hosted .html is loaded, and proxy certain methods (sort-of RPC) thru that iframe using window.postMessage(), by default jQuery ajax methods can be proxied without extra configuration.
All this with one line of js code :)
FrameProxy at GitHub
(fell free to use it and fork it!)