Is it possible to easily detect DOM manipulation by the user?
When a user uses the console in any modern browser, he/she can manipulate the DOM in ways the developer did not intend.
I have a web app that is very much tied to the DOM being in certain states and should the user do anything to the DOM via a console, I'd like to be notified.
The answer:
Doesn't need to be browser agnostic
Doesn't need to be perfect. I fully understand that most, if not all, methods could be circumvented, but I'd like a good general solution.
Can't be too convoluted. I'm not interested in registering an event handler with all DOM events that checks some flag set when my code performs an DOM manipulation
Edit:
There appears to be some confusion in the answers I've received thus far. As pointed out in #2 above, I understand that most, if not all, methods can be circumvented.
In addition, this is an internal tool and thus is protect by a VPN. Further more, there is server-side checking. However, there are reasons, which I cannot elaborate upon, for me wanting to know when a user (who are few in number) manipulated the DOM.
To be clear, this isn't for security reasons. I'm not trying to stop malicious users here. Think of this more as out of curiosity.
Don't do that. Code your web site to not trust user input and then don't care what the user does. If invalid input is submitted then reject it. Everyone is happy.
It's easy to think that you own the user's browser. You don't. It's serving you but only at the whim of the user.
If you really must know when the DOM is modified--and this seems a really fragile design--then just do what amounts to calculating checksums. After each legitimate step of the site's approved function, traverse the DOM elements you care about and record their positions, values, or whatever you are concerned with. At intervals, validation time, or a next UI interaction, compare. This is the only comprehensive, cross-browser (including old browsers) way to detect DOM changes. Modern browsers offer DOM mutation events (see Tim Down's answer for more detail) but have limited support and will apparently be replaced with yet another new thing, anyway.
Ultimately, nothing you do can stop someone determined to defeat your scheme. If anything, the user can copy the browser's POST request using Firebug, tweak it, and write a tiny program to submit his own malicious POST request. It is more important to protect your server from malicious input than it is to make your web page supposedly bullet-proof (because it won't be).
DOM mutation events work in current versions of all major browsers and do what you want. The following will cover common DOM modifications within the whole document:
function handleDomChange(evt) {
console.log("DOM changed via event of type " + evt.type);
}
document.addEventListener("DOMNodeInserted", handleDomChange, false);
document.addEventListener("DOMNodeRemoved", handleDomChange, false);
document.addEventListener("DOMCharacterDataModified", handleDomChange, false);
DOM mutation events will eventually be replaced by mutation observers, which are implemented in recent Mozilla and WebKit browsers.
Relying on a script to prevent or counteract malicious edits to the DOM is not the right approach. What exactly are you doing that depends on the DOM not being touched? Seems like that's a huge red flag in and of itself.
This is a pretty interesting question, and I think DOM mutation events may be a best solution. One thing I was initially thinking I might do is run a timed function that checks the DOM for specific modules, based on data- attributes or IDs. If I was building my page entirely client-side through JS, I would have a build configuration object for each module (DOM element like:
<div id='weather-widget' data-module-type='widget'>
<h1 data-module-name='weather'>Weather</h1>
<!-- etc etc -->
</div>
Anyhow, my config object would contain all of these things like module type, module name, etc, etc:
//Widget configuration object
var weatherWidgetConfig = {
type: 'widget',
name: 'weather'
}
and I would inspect the DOM element and all of its children to make sure the data- attributes still matched the configuration object, that they existed, and that they have not been changed. If they have, I would call a module.destroy() and module.build() again with the correct configuration.
I've received a lot of answers in which the respondent delivers advice about how to build a web app. While that may be useful to some readers, that isn't answering the question. Some, however, have attempted to answer. The closest I seen to a complete answer was given by #Keith. The only problem is that it fails the 'easy' test.
It appears that the correct answer, as some have said, is NO - it isn't possible to easily detect DOM manipulation by a user.
I recently discovered "Selector Listener", a technique that relies on css to detect DOM changes. It doesn't work in IE 9-. Applying it to the whole DOM doesn't sound like a good idea, the intent is rather to work with specific selectors.
More details can be found in this blog post.
Related
I am hoping to upgrade an old project's i18next implementation. The i18n-related code is v1.11, which predates even the breaking changes mentioned for v2.x+
Once upon a time when jQuery was the norm, i18next.js would search the document for translations provided with data-i18n="key" attributes, and fill them in. If you changed languages, you simply called $(parent).i18n() and it would scan the document and fill them in.
I just read the most recent documentation, and they seem to be sticking strictly to the one-key-at-a-time paradigm. No data-attributes, just i18next.t('key').
Have I missed something, or do I need to write my own iterator to go through the document and make the updates? Their code samples seem to indicate "yes", but I have a hard time imagining that anybody sane would want to go through their document and update entries by selector, one-by-one.
To be clear: I'm not asking for a full migration guide. I have headaches ahead of me, this much I know. But I'm hoping I've missed something about using data-i18n attributes, which no longer appear to have built-in support.
Using angular brings lot of weird style of code. For example I always thought that this
<button onclick="myFunction()">Click me</button>
style I should not ever use, except when I would be lazy and want quick and dirty code. And I never used such style in projects and also I even thinked that this is bad.
Now when I see angular
here is the example:
<div enter="loadMoreTweets()">Roll over to load more tweets</div>
which is from there
http://www.thinkster.io/pick/IgQdYAAt9V/angularjs-directives-talking-to-controllers
which is good style by the tutorial. I dont get it. So then it means earlier example with onclick is also perfectly good? Then why nobody uses it at least these days when people use lot of jquery for example?
Let me cite from a book Angular, by Brad Green & Shyam Seshardi
Chapter 2 ... A Few Words on Unobtrusive JavaScript
The idea of unobtrusive JavaScript has been interpreted many ways, but the rationale
for this style of coding is something along the following lines:
Not everyone’s browser supports JavaScript. Let everyone see all of your content and use your app without needing to execute code in the
browser.
Some folks use browsers that work differently. Visually impaired folks who use screen-readers and some mobile phone users can’t use
sites with JavaScript.
Javascript works differently across different platforms. IE is usually the culprit here. You need to put in different event-handling
code depending on the browser.
These event handlers reference functions in the global namespace. It will cause you headaches when you try to integrate other libraries
with functions of the same names.
These event handlers combine structure and behavior. This makes your code more difficult to maintain, extend, and understand.
In most ways, life was better when you wrote JavaScript in this style.
One thing that was not better, however, was code complexity and
readability. Instead of declaring your event handler actions with the
element they act on, you usually had to assign IDs to these elements,
get a reference to the element, and set up event handlers with
callbacks...
...
In Angular, we decided to reexamine the problem.
The world has changed since these concepts were born...
... for most inline event handlers Angular has an equivalent in the form of
ng-eventhandler="expression" where eventhandler would be replaced by
click, mousedown, change, and so on. If you want to get notified when
a user clicks on an element, you simply use the ng-click directive
like this:
<div ng-click="doSomething()">...</div>
Is your brain saying “No, no, no! Bad, bad, bad!”? The good news is
that you can relax.
These directives differ from their event handler predecessors in that
they:
Behave the same in every browser. Angular takes care of the differences for you.
Do not operate on the global namespace. The expressions you specify can
To get more details, read the book: http://www.amazon.com/AngularJS-Brad-Green/dp/1449344852
EXTEND
Following the discussion in comments, I would like to add a more explanation.
As stated here: Wikipedia - AngularJS:
Angular is a framework, which goal is to augment browser-based applications with model–view–controller (MVC) capability, in an effort to make both development and testing easier
The Model–view–controller, a short extract from wikipedia:
A controller can send commands to the model to update the model's state (e.g., editing a document). It can also send commands to its associated view to change the view's presentation of the model (e.g., by scrolling through a document).
A model notifies its associated views and controllers when there has been a change in its state. This notification allows views to update their presentation, and the controllers to change the available set of commands. In some cases an MVC implementation might instead be "passive," so that other components must poll the model for updates rather than being notified.
A view is told by the controller all the information it needs for generating an output representation to the user. It can also provide generic mechanisms to inform the controller of user input.
Summary:
The most important part here, is the fact, that View can publish the Controllers actions to the user. And this is exactly what the Function calls in HTML do represent.
This is a misunderstanding:
Using angular brings lot of weird style of code. For example I always thought that this
<button onclick="myFunction()">Click me</button>
style I should not ever use, except when I would be lazy and want quick and dirty code. And I never used such style in projects and also I even thinked that this is bad.
It is perfectly valid to use that style of code if you can decide what event handler to attach to the button when you render the HTML code. With jQuery we see many dynamically attached event handlers because many times the elements themselves are dynamically inserted or whether to attach an event listener or what to attach is dynamically decided.
While reading about navigator() object in JavaScript I run into taintEnabled() function description, as good as similar taint() and untaint() functions, referring to something called "data-tainting".
Googling around net and StackOverflow show some possible reference to Perl language, but none about JavaScript. I wonder, what is data-taining and how to use these functions?
Data Tainting (or Taint Checking) is a language feature wherein user-input data is flagged as tainted, a flag that propagates to all data derived from this input. As a result, code can implement runtime assertions to ensure security critical code is not being called using tainted data (ie prevent SQLi, XSS type attacks).
Whilst Netscape implemented it in the browser in v3 and v4, support for it sadly never materialized elsewhere, so #trejder is absolutely right that it should be avoided in JavaScript.
As mentioned, there aren't many sources in the Internet about data-tainting, as it seems to be a long forgotten, deprecated technique and topic. But I found out an interesting reading on this on findmeat.org. For the Navigator.taintEnabled() method it says that (various parts cited, some text shortened):
The data-tainting support was a short-lived means of sending data back to a server. The security implications became unworkable and the whole data tainting idea was deprecated. The functionality was removed in JavaScript version 1.2. This method is only supported in order to prevent scripts from crashing. This functionality is highly deprecated and you can expect it to cause run-time exceptions in future. You should seek to try and remove it to prevent run-time errors in the future.
It seems that nowadays few browsers support this function (and similar, mentioned) and that it should not be used under any circumstance. Even if a browser implements this at all, it should return the value false for this method, always.
Lack of information on this concept makes new learners to make more effort. Here is my finding to help them.
When tainting should be enabled and when not, here are the two important points worth considering:
When data tainting is enabled, JavaScript in one window can see properties of another window, no matter what server the other window's document was loaded from. However, the author of the other window taints (marks) property values or other data that should be secure or private, and JavaScript cannot pass these tainted values on to any server without the user's permission.
When data tainting is disabled, a script cannot access any properties of a window on another server.
A useful resource is http://www.aisystech.com/resources/advtopic.htm#1009533
I am trying to figure out any and all ways to prevent CSS modification and DOM modification of specific elements. I understand this might not be completely possible or that a talented developer could get around it, however, I am not so concerned about people potentially getting around it, I just want to stop newbies. In particular those using jQuery. An example would be to delete certain properties on prototype objects etc..
But why you need/want this? If you want to "protect" your code, you can use some JavaScript minifier as Google Closure Compiler or YUI compressor. They will rewrite your script and it will be difficult to read by a human. Nowadays, with tools like Firebug and Grease Monkey it's almost impossible to do what you want.
Don't use CSS or JavaScript :p Depend completely on server side checks etc.
You cannot stop anyone from messing with your javascript or your objects in the page. The way the browser is designed, your code and objects in your page are simply not protected. Everything from bookmarklets to javascript entered at a console to browser plug-ins can mess with your page and code and variables. That is the architecture of a browser.
What you can do is make things a little more difficult such that a little more work is required for some things. Here are a couple of things you could do:
Obfuscating/compressing/minimizing your code will do things like remove comments, remove whitespace, remove some linebreaks, shorten variable names, etc... That does not prevent anyone from modifying things, but does make it more work to understand and figure out.
Putting variables inside closures and not using globals. This makes it harder to directly modify variables from outside of your scripts.
Keep all important data and secrets on your server. Use ajax calls to ask the server to carry out operations using that data or secrets such that the important information is never available in the browser client.
You cannot keep anyone from modifying the DOM. There simply are no protections against that. Your code can check the DOM and refuse to operate if the DOM has been messed with in non-standard ways. But, of course, the code would then be modified to remove that check too.
If you are looking for a jquery specific solution a crude approach will involve altering the jQuery ($) function and replacing it with a custom one that delegates to the original function only if the provided selector does not match the element you want to secure.
(function(){
jQueryOrig = jQuery;
window.jQuery = window.$ = function(){
if (jQueryOrig("#secure").is(arguments[0])) {
throw new Error("Security breach");
} else return jQueryOrig.apply(this, arguments);
}
}());
Of course people using direct DOM manipulation would not be affected.
Also, if you are actually including arbitrary third party code in your production code, you should take a look at Caja ( http://code.google.com/p/google-caja/ ), which limits users to a subset of javascript capabilities. There is a good explanation regarding Caja here : http://due-diligence.typepad.com/blog/2008/04/web-20-investor.html .
This is possible but requires that the JS file to always be loaded from your server. Using observers you can lock CSS properties and using the on DOM remove/add listeners you can lock it to a parent. This will be enough to discourage most modification.
You can actually go a step further and modify core javascript functions making it nearly impossible to modify the DOM without loading the JS file locally or through a proxy. Further security can be added by doing additional domain checks to make sure the JS file is loaded from where it is supposed to be loaded from.
You can make everything in Flash. In Chrome, there's even a bug that prevents users from opening a console if the flash element has focus (not sure how exactly this works, but you can see an example at http://www.twist-cube.com or http://www.gotmilk.com). Even if users do manage to get a console open (which isn't that hard...), still about all you can do is change the shape of the element.
I'd like to dynamically change some of the standard JS DOM objects from within a web browser.
For instance, when I execute:
var site = location;
I want to specify a new value for my browser's "window.location" object other than the "correct" one (the URL used to access the requested page) at run time, either through a debugger-like interface or even programmatically if need be.
Although Firebug advertises the capability to do something similar via its "DOM Inspector," whenever I try to modify any of the DOM values while I've paused the Javascript via its debugger, it simply ignores the new value I enter. After doing some research, it seems that this is a known issue according to this bug report: http://code.google.com/p/fbug/issues/detail?id=1707 .
Theoretically, I could write a program to simply open up an HTTP socket and emulate a browser "user agent," but this seems like a lot of trouble for my purposes. While I'm asking, does anyone know a good Java/C# library with functions/objects that emulate HTTP headers and parse the received HTML/JS? I've long dreamt about the existence of such a library but most of the ones I've tried (Java's Apache HttpClient, C#'s System.Net.HttpWebRequest) are far too low-level to make anything worthwhile with minimal planning and a short period of time.
Thanks in advance for recommendations and advice you can provide!
Not sure if I understand you correctly, but if you want to change the loaded URL you can do that by setting window.location.href.
If your intent is to replace DOM buildins then you will be sad to hear, that most build-in objects (host objects) aren't regular JavaScript objects and their behaviour is not clearly defined. Some browsers may allow you to replace and/or extend some objects while in other browsers they won't be replaceable/extendable at all.
If you want to "script a browser" using JavaScript, you should definitly have a look at node.js and it's http module. There's also a thirdparty module called html5 that simulates the DOM in node.js and even allows the usage of jQuery.