The Context:
You have a web server which has to provide an exclusive content only if your client has your specific Chrome extension installed.
You have two possibilities to provide the Chrome extension package:
From the Chrome Web Store
From your own server
The problem:
There is a plethora of solutions allowing to know that a Chrome extension is installed:
Inserting an element when a web page is loaded by using Content Scripts.
Sending specific headers to the server by using Web Requests.
Etc.
But there seems to be no solution to check if the Chrome extension which is interacting with your web page is genuine.
Indeed, as the source code of the Chrome extension can be viewed and copied by anyone who want to, there seems to be no way to know if the current Chrome extension interacting with your web page is the one you have published or a cloned version (and maybe somewhat altered) by another person.
It seems that you are only able to know that some Chrome extension is interacting with your web page in an "expected way" but you cannot verify its authenticity.
The solution?
One solution may consist in using information contained in the Chrome extension package and which cannot be altered or copied by anyone else:
Sending the Chrome extension's ID to the server? But how?
The ID has to be sent by you and your JavaScript code and there seems to be no way to do it with an "internal" Chrome function.
So if someone else just send the same ID to your server (some kind of Chrome extension's ID spoofing) then your server will consider his Chrome extension as a genuine one!
Using the private key which served when you packaged the application? But how?
There seems to be no way to access or use in any way this key programmatically!
One other solution my consist in using NPAPI Plugins and embed authentication methods like GPG, etc. But this solution is not desirable mostly because of the big "Warning" section of its API's doc.
Is there any other solution?
Notes
This question attempts to raise a real security problem in the Chrome extension's API: How to check the authenticity of your Chrome extension when it comes to interact with your services.
If there are any missing possibilities, or any misunderstandings please feel free to ask me in comments.
I'm sorry to say but this problem as posed by you is in essence unsolvable because of one simple problem: You can't trust the client. And since the client can see the code then you can't solve the problem.
Any information coming from the client side can be replicated by other means. It is essentially the same problem as trying to prove that when a user logs into their account it is actually the user not somebody else who found out or was given their username and password.
The internet security models are built around 2 parties trying to communicate without a third party being able to imitate one, modify or listen the conversation. Without hiding the source code of the extension the client becomes indistinguishable from the third party (A file among copies - no way to determine which is which).
If the source code is hidden it becomes a whole other story. Now the user or malicious party doesn't have access to the secrets the real client knows and all the regular security models apply. However it is doubtful that Chrome will allow hidden source code in extensions, because it would produce other security issues.
Some source code can be hidden using NPAPI Plugins as you stated, but it comes with a price as you already know.
Coming back to the current state of things:
Now it becomes a question of what is meant by interaction.
If interaction means that while the user is on the page you want to know if it is your extension or some other then the closest you can get is to list your page in the extensions manifest under app section as documented here
This will allow you to ask on the page if the app is installed by using
chrome.app.isInstalled
This will return boolean showing wether your app is installed or not. The command is documented here
However this does not really solve the problem, since the extension may be installed, but not enabled and there is another extension mocking the communication with your site.
Furthermore the validation is on the client side so any function that uses that validation can be overwritten to ignore the result of this variable.
If however the interaction means making XMLHttpRequests then you are out of luck. Can't be done using current methods because of the visibility of source code as discussed above.
However if it is limiting your sites usability to authorized entities I suggest using regular means of authentication: having the user log in will allow you to create a session. This session will be propagated to all requests made by the extension so you are down to regular client log in trust issues like account sharing etc. These can of course be managed by making the user log in say via their Google account, which most are reluctant to share and further mitigated by blocking accounts that seem to be misused.
I would suggest to do something similar to what Git utilises(have a look at http://git-scm.com/book/en/Git-Internals-Git-Objects to understand how git implements it), i.e.
Creating SHA1 values of the content of every file in your
chrome-extension and then re-create another SHA1 value of the
concatenated SHA1 values obtained earlier.
In this way, you can share the SHA1 value with your server and authenticate your extension, as the SHA1 value will change just in case any person, changes any of your file.
Explaining it in more detail with some pseudo code:
function get_authentication_key(){
var files = get_all_files_in_extension,
concatenated_sha_values = '',
authentication_key;
for(file in files){
concatenated_sha_values += Digest::SHA1.hexdigest(get_file_content(file));
}
$.ajax({
url: 'http://example.com/getauthkey',
type: 'post'
async: false,
success:function(data){
authentication_key = data;
}
})
//You may return either SHA value of concatenated values or return the concatenated SHA values
return authentication_key;
}
// Server side code
get('/getauthkey') do
// One can apply several type of encryption algos on the string passed, to make it unbreakable
authentication_key = Digest::<encryption>.hexdigest($_GET['string']);
return authentication_key;
end
This method allows you to check if any kind of file has been changed maybe an image file or a video file or any other file. Would be glad to know if this thing can be broken as well.
Related
Overview
I am trying to make a Chrome Extension that takes the currently open html page and all its dependencies (CSS, JS) and uploads it to a custom domain via FTP. I would then be able to open it on my phone to make sure the website looks good on a phone.
Basically, I am trying to replicate the VSCode extension Live Server's functionality, but with it uploading the file to a custom domain. I know you'd normally be able to access live server's locally hosted server from a phone, but my university's internet setup doesn't seem to allow for this, hence my desire for an extension like this.
All I know about my hosting service is that it uses cPanel and supports FTP, which I assume is all I need. I can set up new FTP connections and logins. All the FTP details in the code will be hardcoded, but drawn from a separate file and .gitignored so they aren't in my commit history, which I hope is enough.
What I've Tried & What I'm Stuck On
I have most of the chrome extension stuff figured out; The FTP transfer process is what's giving me issues.
I first tried using chrome-app-ftp, but quickly realized that was old and was running into issues, so I switched to jsftp.
I used browserify to fix the "require" issue, and that cleared up some stuff.
I'm currently stuck on the following bug:
Error: TypeError: createConnection is not a function
I've done my research, and I do not think the error is because of an issue in my code; I believe that it is just a limitation of the tools I am using. This seems to be an issue with front-end JS not supporting the "net" module, which brings me to my question.
My Question
How do I circumvent my lack of support for the "net" module in the front-end? Do I need to set up some sort of local back-end for this with node or something like that? I have basically zero experience with anything back-end, so I might need pointed towards what sort of back-end is best for this. I more just need to know which tech stack is best for doing this.
If additional information is necessary I'll be checking back frequently and happy to help. Thanks in advance.
I created a small JavaScript application for which I reused some (quite large) JavaScript resources that I downloaded from the internet.
My application runs in the browser like other interactive web applications but works entirely offline.
However, I intend to enter some private information in the application which it shall visualize. Since I cannot ultimately trust the JavaScript pieces that I downloaded, I wonder if there is a JavaScript option to make sure that no data is downloaded and, in particular, uploaded to the web.
Note that I am aware that I can cutoff the local internet connection or perhaps change browser settings or use an application firewall, but this would not be a solution that suits my needs. You may assume that the isolation of a browser instance is save, that is no other, possibly malicious, web sites can access my offline JavaScript application or the user data I enter. If there is a secure way to (automatically) review the code of the downloaded resources (e.g. because communication is possible only via a few dedicated JavaScript commands that I can search for) that would be an acceptable solution too.
You should take a look at the Content Security Policy (CSP) (see here and here). This basically blocks every connection from your browser to any other hosts, unless explicitely allowed. Be aware that not all browsers support CSP, which leads to potential security problems.
Reviewing the library code might be difficult because there are many ways to mask such code pieces.
Find it yourself by watching your browser's network activity while your application is in action.
There are more than enough tools to do this. Also, if you know how to use netstat command line tool, it is readily shipped with windows.
Here is one cool chrome extension which watches the traffic of the current tab.
https://chrome.google.com/webstore/detail/http-trace/idladlllljmbcnfninpljlkaoklggknp
And, here is another extension which can modify the selected traffic.
https://chrome.google.com/webstore/detail/tamper-chrome-extension/hifhgpdkfodlpnlmlnmhchnkepplebkb?hl=en
You can set the filters and modify all requests/responses happening in your page.
If you want to write an extension to block requests yourself, check this answer out.
The set-up in question:
I have a stand alone, offline, kiosk mode instance of Chrome running on a Windows machine. I have full access to the system and any admin rights. I can start Chrome with any flags set or unset.
The task:
I have been asked to create a log file which tracks user activity within the offline app I am coding. It's a simple form of analytics which will append each event to the end of the file separated with a comma. The file will then be sent to a server once a day via a scheduled task. (None of this is my idea so please don't troll me)
Ruled out:
Any server side code - I have lobbied for Node, PHP etc but as this will be distributed to many different installations so we cannot guarantee this will be installed.
Flash/ActiveX/Java - ideally would like to avoid this (even though these will be installed by default)
Possible solutions:
File API - I have looked at this but AFAIK if opens dialogue boxes to save the data to each file and this needs to happen in the background.
Security - I have read in other SO Questions that this can be achieved if the security settings are reduced but no-one goes on to explain which ones. Is there a simple flag which allows it?
How to enable local file system read write access from Google chrome? - similar question!
Ideal result: (something akin to PHP)
$file = 'log.txt';
$current = file_get_contents($file);
$current .= ",clicked:link";
file_put_contents($file, $current);
Possible ideal side result: proving this isn't possible and forcing PHP/Node/Java to be used ;)
In reply to those suggesting local storage : I'm not storing unique key/value pairs and that is very much like setting a cookie. Similarily there are file size limits.
To those suggesting web SQL such as SQLite in chrome - there are file size limits if it's not a chrome extension. The only way I see that working is if I were to find the location of the file in the windows directory (C:\Users\%USERNAME%\AppData\Local\Google\Chrome\User Data\Default\databases) and upload that from the schedules task. Perfectly feasible but it is not a desirable answer.
You could use HTML5?
http://diveintohtml5.info/storage.html
var foo = localStorage.getItem("bar");
// ...
localStorage.setItem("bar", foo);
You can use the Chrome Apps File API, you will need to grant access to the file via a user action once, but after that you can get access the file again by using restoreEntry
You can use localStorage to save offline data. It's impossible to access other files using Javascript since it's a violation of the sandbox.
From http://en.wikipedia.org/wiki/JavaScript#Security:
JavaScript and the DOM provide the potential for malicious authors to deliver scripts to run on a client computer via the web. Browser authors contain this risk using two restrictions. First, scripts run in a sandbox in which they can only perform web-related actions, not general-purpose programming tasks like creating files.
You may want to look into Local Storage which is part of the HTML5 spec.
This will only be supported in modern browsers though.
If you need to use older browsers then may still be able to achieve what you're after using dojox.storage
Use HTML5 features like Web Storage or Web SQL database to store your logs.
Whenever needed read logs from the client side storage and send it back to the server & delete the client storage.
Refer http://www.html5rocks.com/en/features/storage.
I was just looking at this stackoverflow question: Display web browser settings
And that helps.
But, I'm curious if I can detect certain IE specific settings. I'm thinking some of the stuff in the Advanced Tab (e.g. Is 'Enable Integrated Windows Authentication' on)?
Or that our site was added as a Trusted Site? And within the Trusted Site settings, "Atomatic logon with current user name and password" is set?
I don't want to change them (I get that would be a huge issue that could be exploited). I just want to be able to present to the User:
"Hey, you need these couple of settings checked or unchecked for the site to work properly. Do this: a, b, c ... or Contact your Administrator".
Is this possible?
I don't think you can query these settings from within a web site. Being able to do so might introduce security holes.
I'm sure some settings can be determined by using circumstantial evidence (like if a JavaScript doesn't execute, scripting is probably disabled). But I don't think there is a proper API to poll every setting; I guess the best you can do is serve the user some advice on what to look for. (like, "The xyz symbol in the bottom right bar should show a green checkmark like so.... the abc checkbox in the options dialog should be unchecked... etc")
You can't check the settings directly, but you could test the functionality instead. If you attempt to authenticate with the server and find out you don't have their credentials passed in properly, you know it's not configured right. At this point you could show them your information about how to connect to the site. This would be a better solution anyways, as you're better off testing for features rather than specific settings.
To distill your question down, it looks like you're trying to find out whether IE is configured to automatically send NTLM credentials to your server.
Unfortunately, there's no way to cleanly feature-detect this. My initial thought was to put a JavaScript file in a protected directory that simply set a global variable, and link to that script in the <head>. (<script src="protected-dir/test.js"></script> – protected-dir would be configured only for integrated auth with anonymous auth off.) If the script loads, the variable is set; and if it fails, the variable obviously isn't. Another script on the page could check the variable and show a message if it's not set.
This works flawlessly when everything is configured correctly on a client, but when auto login is off, this causes an ugly 401 dialog to pop up, which is clearly no good. Additionally, a XHR request isn't the answer since the spec specifically says the browser should ask for credentials if it gets a 401.
Sadly, I don't think there's a way to automatically determine if auto login is enabled without causing the 401 dialog to pop up.
This has been asked a lot of times already: I need to get the full file path via a web-page. The use case is an application running on the same machine as the browser (i.e. the application starts a local HTTP server and fires up the browser.) File-paths are of course valid and the same for both client/server now. The use case it that the user selects a file and then the server process does some computation on it, and the input files are typically large (read: several GiB in size.)
The easiest thing would be to directly access the path using , but for security reasons, this is disabled. I'm looking now for the least intrusive workaround to this problem. The target browser in question is Chrome. I'm fine if the user has to click "accept" once on some security warning, as long as I can ensure that it won't appear again.
Do I have to write an extension, NSPlugin, can I use some special header magic to mark my page as "local", is there some security setting I can set? The less the client has to do the better, and I would prefer some "click here to allow access ..." solution above everything else. Can I directly install an extension from the server process that would do this (after the user clicks accept?)
Is it possible to do this with a Java applet/Flash? That would be the easiest solution, and clients are guaranteed to have Flash installed (as it is bundled in Chrome...)
You can create Java applet for tasks like this and self-sign it. User will have to allow it to run, but then you will be able to access applet's function that will return file path string via Javascript.
Clearly file io on the client's system is forbidden from JavaScript. If this wasn't the case it would be absolutely trivial to hack every web browser that visits your website.
Battlefiled 3 is controlled though the browser. To do this EA wrote a browser extension for the top three browsers. But that's resource intensive. If you just care about chrome you can use an addon, and for that i suggest using the NPAPI.
And as MOleYArd said, Java is a good solution and probably more common than an extension or addon.