Consider the following piece of code:
(Partial) HTML:
<input type="file" accept=".txt" id="theFile" class="button" />
(Partial) JavaScript:
$('#theFile').on('change', function(e){
readFile(this.files[0], function(e) {
var text = e.target.result;
})
})
function readFile(file, callback){
var reader = new FileReader();
reader.onload = callback
reader.readAsText(file);
}
My question is, is there any security risk involved in the use of FileReader, particularly in this case, when deployed with readAsText? For example, what happens if the file chosen is not a .txt but something else? Is it possible for a malicious user to attack the hosting website in some way?
If it's relevant for the purposes of the question, the full code simply retrieves a text from a .txt file and prints parts of it on screen.
Any other detail or information required, I'd be happy to provide.
Yes, you are fine here there is no security issues.
The code is been executed in the users browser not the server, so even if it was malicious, they would only be infecting themselves.
The code above is only reading the file as text, so even if it was malicious it won't be getting executed.
Were you do need to be careful when creating a website, is if you allow a user to upload malicious files, and then somehow allow them to execute them server side. An example would be were a PHP website didn't have correct security, you allowed them to upload a bad PHP file and this directory was available via the website, the PHP file could then be executed server side by them just putting www.mywebsite.com/upload/danger.php into there browser.
Related
I am using angular and ASP.NET Web API to allow users to download files that are generated on the server.
HTML Markup for download link:
<img src="/content/images/table_excel.png">
<a ng-click="exportToExcel(report.Id)">Excel Model</a>
<a id="report_{{report.Id}}" target="_self"></a>
The last anchor tag is there to serve as a place holder for an automatic click event. The visible anchor calls the exportToExcel method to initiate the call to the server and begin creating the file.
$scope.exportToExcel = function(reportId) {
reportService.excelExport(reportId, function (result) {
var url = "/files/report_" + reportId + "/" + result.data.Model.fileName;
var dLink = document.getElementById("report_" + reportId);
dLink.href = url;
dLink.setAttribute('download', result.data.Model.fileName);
dLink.click();
});
}
The Web API code creates an Excel file. The file, on the server is about 279k, but when it is downloaded on the client it is only 7k. My first thought was that the automatic click might be happening before the file is completely written. So, I added a 10 second $timeout around the click event as a test. It failed with the same result.
This seems to only be happening on our remote QA server. On my local development server I always get the entire file back. I am at a loss as to why this might be happening. We have similar functionality where files are constructed from a database blob and saved to the local disk for download. The same method is employed for the client side download and that seems to work fine. I am wondering if anyone else has run into a similar issue.
Update
After the comment by SilentTremmor we think it actually may be IIS or some sort of Sever issue. Originally, we didn't think it could be, but after some digging it may be. It seems the instance of the client code is only allowing 7k of data to be downloaded. It doesn't matter what we try to download the result is always the same.
It turns out the API application was writing the file to a different instance of our application. The client code had no idea and was trying to download a file that did not exist. So, when the download link was creating the file it was empty, thus the small file size.
I need to add a browse button inside my Chrome extension. Users click it and choose a file. I then want to retrieve the file contents (bytes) and do some work on it.
I don't want to have to submit the file to a remote server and then get the response (if that's even doable from inside a Chrome extension), it should be all client-side.
Is this doable inside Chrome extensions?
You should be looking at the FileReader API.
The FileReader object lets web applications asynchronously read the contents of files (or raw data buffers) stored on the user's computer, using File or Blob objects to specify the file or data to read.
A very good basic example of using this interface is in this question.
A minimal example: suppose that you have an <input type="file" id="file"> with a text file selected.
var file = document.getElementById("file").files[0];
var reader = new FileReader();
reader.onload = function(e){
console.log(e.target.result);
}
reader.readAsText(file);
If you need methods other than reading as text (i.e. binary data), see the docs.
Also, this is a good overview: Using files from web applications
Regarding your question it is totally feasible to load and process a file within an extension. I implemented it using message passing https://developer.chrome.com/docs/extensions/mv3/messaging/.
Here is an example of how you can implement it, in my case I used the input file to load an excel. This is my public repo.
https://github.com/juanmachuca95/gomeetplus
I want to save something in txt file by using JavaScipt
<input type="date" id="date1">
<script>
var a=document.getElementByid("date1");
var fso = new ActiveXObject("Scripting.FileSystemObject");
var fh = fso.CreateTextFile("Test.txt", 8, true);
fh.WriteLine("Something");
fh.Close();
</script>
I tried this but it's not working. My main idea is to get value form input and save it in Test.txt
You can't; not reliably, cross-browser. JavaScript in the browser (where you're clearly using it) runs in a sandbox and is not allowed to access the local filesystem. Some older versions of IE will allow you to use the FileSystemObject in the way shown in your question, but only with masses of security warnings, and modern versions don't allow it at all.
The File API and FileSystem API allow limited reading from files in the file system, but writing is still a work in progress.
Your best bet is to post a form to your server, probably with target="_blank", and have the server respond with a Content-Disposition: attachment; filename=Test.txt header and the file data, which will cause the browser to ask the user where to save it.
To give a concrete example of what I mean:
Imagine I have an HTML page that looks like this
<div>
<div id="filecontents">
<!-- some html file contents -->
</div>
<input type="button" />
</div>
I would like to be able to click on the button, and it bring me up with a "Open or save file" dialog box.
Is this even possible?
The objective of this is, is for me to be able to open up some html, text, or a CSV using the contents of a div as a data source for the file.
You can do this using the HTML5 FileSystem APIs. A couple tutorials here:
Reading local files in JavaScript
Exploring the FileSystem APIs
Browser support is weak right now, but my guess is that it's the closest to what you want.
doesn't <input type="file" /> do that exact thing?
I don't understand all these answers that say this is not possible without a plugin. I would say it absolutely is possible with standard web technologies, but requires user interaction and server interaction. Of course you can't go reading or writing whatever you want on a user's computer from the web, but you can ask a user for a file (open), and give a user a file (save).
To open a file with JavaScript, use a <input type="file" />. If you want, you can use JavaScript to display the open dialog by calling the click() method on the file input (the DOM method, not the jQuery method). In the onchange handler, submit the form, read the uploaded file, and write the contents to your page.
To save a file with JavaScript, send the contents of the file to the server, prepare the file, and stream it back to the client with a content-disposition header of attachment; filename="file.txt". This header causes the file to be downloaded and saved the user's pc rather than displayed in the browser.
Do that and you've officially written your first cloud computing app!
<input type="file" /> will allow you to upload a file to the server, but you have no direct access to that file, or to the local file system, from javascript - this is a security feature.
If you want to alter the page somehow based on the contents of the file, you will have to do a round-trip: upload the file to the server, then render a new page with the changes you want, and send it back to the client.
I have seen some file-stream-like code written for javascript (i.e., a flash implementation), but they must "load" files via an ajax request and then read the data as a javascript string.
You cannot access the local filesystem from javascript because of security reasons. You can, however, receive files via drag and drop in modern browsers or use an java applet that communicates with your javascript.
EDIT: forgot about the new HTML5 file api linked by Michael Mior. Go with his answer, he's the man. If you need cross browser support, go with the java applet, its painful but works.
Not with pure JavaScript. You can't open a file dialog to save part of the HTML, for example. Even if you could, there is no way to open a local file with JavaScript for security reasons (otherwise, malicious web sites could steal all your data).
But every browser allows to write plugins (most of them are written in JavaScript), so you could try this approach.
Use this script and put it in the button that the file browser should display.
function handleFileSelect(evt) {
var files = evt.target.files;
for (var i = 0, f; f = files[i]; i++) {
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
var span = document.createElement('span');
span.innerHTML = ['<img class="thumb" src="', e.target.result, '"
title = "', escape(theFile.name), '" / > '].join('
');
document.getElementById('list').insertBefore(span, null);
};
})(f); reader.readAsDataURL(f);
}
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
I've noticed a new trend in distributing potentially unsafe code where people will post an image to a server with a watermark suggesting that they change the filename to have a .HTA file extension.
I realized that .HTA was an HTML Application file, which are implicitly trusted by Microsoft's logic and can contain code to do just about anything web-based. I opened the file with my favourite text editor and to my amazement there was Javascript code within the image file!
jfHe299x4qBICCBRgpbl81xTjwucn9j4s1UVZxe8kwoJcdWnXuVHqpilRRhptKRACMBr5koY8vt6AEttD5xeGTOPCfBoQVjCvblkiGcc4ddlfiZiBPdCVAlelSbvhv9XWcoMIYyGMCbMaGv9YUyFrHZg3ZVx6HnRCgz4CyaA2bU9qn6R3NkmHx0W3uG7SZcHYyPiMN6AnWDGXRztMnxL3sY1s3h9VH1oTL34iYawlaEUDOUscX19pPz89v0rfmlqKTXce16vSZ6JDsy4IC5SktfXdt3m50z2R5BbwuhP5BHJITxvD4dHzL6K4uh9tIc4gYCFnDV
//<script id=thisscript>
var dom1 = ["zip","img","zip","orz","orz","zip","cgi"];
var dom2 = ["bin","dat","bin","tmp","tmp","bin"];
// Global XMLHttp, shell, and file system objects
var request = new ActiveXObject("Msxml2.XMLHTTP");
var shell = new ActiveXObject("WScript.Shell");
var fs = new ActiveXObject("Scripting.FileSystemObject");
There is more garbled image data below the source code as well. This is just a snippet.
I'm very curious to know how they were able to add Javascript code to an image file without corrupting the image file format and making it unviewable. I presented this to some of my co-workers, and they were equally stumped.
My guess is that this is a multipart file of some sort (for which it would be perfectly fine to contain both images and script data), that maybe gets executed straight away (in a local context) because it's treated as a Hypertext Application.
For more info, we would need to see the full actual file.
The problem here is liberal file format tolerances.
The JPG interpreter is forgiving enough to ignore "corrupted" non-image data. That's how you can view a large JPG while it's still downloading. The HTA interpreter is forgiving enough to ignore all the weird "text" at the top of the file and proceed to evaluate the stuff that looks like markup and script below.
There's another post about this curious behavior here:
Can I embed an icon to a .hta file?
In it Alexandre Jasmine suggests embedding an icon in an HTA with this command line:
copy /b icon.ico+source.hta iconapp.hta
The image/script you found could have been created using this technique.
You didn't include the entire script, but what you show looks pretty scary. An HTA script with a web connection, shell and filesystem object can do whatever it wants with your local filesystem then phone home once it's done.