-
Notifications
You must be signed in to change notification settings - Fork 831
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cordova-js: Event Listener Hijacking #276
Conversation
Updated Code with Both Document and Window Event Handlers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The lint failures is blocking the actual unit tests from running, so once the lint issues are resolved there might be additional changes required.
Co-authored-by: Norman Breau <[email protected]>
Co-authored-by: Norman Breau <[email protected]>
Co-authored-by: Norman Breau <[email protected]>
Co-authored-by: Norman Breau <[email protected]>
Co-authored-by: Norman Breau <[email protected]>
Co-authored-by: Norman Breau <[email protected]>
Co-authored-by: Norman Breau <[email protected]>
Co-authored-by: Norman Breau <[email protected]>
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #276 +/- ##
==========================================
- Coverage 83.62% 79.81% -3.81%
==========================================
Files 14 14
Lines 519 555 +36
==========================================
+ Hits 434 443 +9
- Misses 85 112 +27 ☔ View full report in Codecov by Sentry. |
Fixed global event handlers & removed the redundant func: document.addEventListener = function (evt, handler, capture) window.addEventListener = function (evt, handler, capture)
Removed allowedElements as advised
} | ||
}; | ||
var documentEventHandlers; | ||
var windowEventHandlers; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per the original report, you claimed these must not be globally accessible so they should be declared in the IIFE function, so that they will be out of scope of any external code.
Honestly I'm still not sure if this will be breaking or if there is existing cordova code that is external that depends on these global variables. I'll need to consult with other members who are more familiar with this part of the codebase.
After discussing this with a colleague we determined that the changes in this PR is high risk of breaking plugins and/or applications with low reward/value. As a result we will be declining this PR. There's a couple of reasons why we consider this low reward/value and I'll list them. 1. The PR doesn't actually prevents "hijacking" of events.The PR aims to isolate an object containing global event listeners because if an hypothetical malicious actor could replace the stored function with another. By removing this object from the global namespace, you remove the ability to replace the handler function. The reality is, hypothetical malicious actors do not need this object. They could simply attach an click event (or any other event) on the document. They can go as far as use the document.addEventListener('click', function(e) { ... }, true); Is all that is needed to listen for click events on any target and inspect what is actually being clicked. This is true even with standard browser APIs that isn't being overwritten. 2. standard window/document properties can simply be replacedA hypothetical malicious actor who wants to hijack events can do so by replacing the cordova's implementation with their own. This is true even if Cordova doesn't overwrite the addEventListener itself. The reality of webviews cannot load untrusted code. Any the attempts at hardening doesn't really do anything to deter or prevent a malicious actor in this case, hijack events. Once untrusted code is loaded, the app is at risk and at that point there is very little the application can do to "harden" itself. This is because the nature of the javascript engine is very dynamic and the runtime can be customized in the runtime on the fly. Webview environments aren't like other environments where you can minimize impact by implementing permission models or limiting access to resources, etc. The JS runtime can simply change anything it wants. As noted in the security email thread, there are best practices to follow to prevent unauthorized code from executing and if users follow them they are expected to be safe. For reference these guidelines can be found here Edit: I was also recently informed that the code in question is also its "prebuilt" stage. The source code in this repo gets wrapped in a function already in the final For example this code will be placed as follows: // file: src/cordova.js
define("cordova", function(require, exports, module) {
// Workaround for Windows 10 in hosted environment case
// http://www.w3.org/html/wg/drafts/html/master/browsers.html#named-access-on-the-window-object
if (window.cordova && !(window.cordova instanceof HTMLElement)) {
throw new Error('cordova already defined');
}
var channel = require('cordova/channel');
var platform = require('cordova/platform');
/**
* Intercept calls to addEventListener + removeEventListener and handle deviceready,
* resume, and pause events.
*/
var m_document_addEventListener = document.addEventListener;
var m_document_removeEventListener = document.removeEventListener;
var m_window_addEventListener = window.addEventListener;
var m_window_removeEventListener = window.removeEventListener;
/**
* Houses custom event handlers to intercept on document + window event listeners.
*/
var documentEventHandlers = {};
var windowEventHandlers = {};
document.addEventListener = function (evt, handler, capture) {
var e = evt.toLowerCase();
... These variables are within a function block and thus aren't scoped in a global accessible area. The hardening steps to isolate these functions in an IIFE is actually already being done. |
Motivation and Context
This issue was originially reported to [email protected].
About the Issue
The current code modifies the default behavior of addEventListener and removeEventListener for both document and window objects to handle custom events. This modification can potentially be exploited if not properly secured.
Relevant Code
The manipulation of the document.addEventListener and window.addEventListener methods is crucial to the DOM event system. Overriding these methods allows directing certain events to custom documentEventHandlers and windowEventHandlers objects while allowing the default behavior for others. Malicious code (XSS) might modify these handler objects to include or replace handlers for specific events.
Description of the Fix
To mitigate such risks, we can encapsulate the modified addEventListener methods within an IIFE (Immediately Invoked Function Expression) to limit the scope and potential impact of the modifications. Additionally, checks are added to ensure that the subscribe function exists before calling it.
By implementing these practices, we can significantly reduce the risk of event listener hijacking. Having said that, if you beleive this should be left to the application to follow security best practices for input validation, CSP & loading of secure libraries of thrid party scripts and as a framework we shouldn't restrict such events. I am happy for you to close this PR with no action! This is more of defense in depth strategy to bake in security.
Testing
Limited testing performed, could use some help here.