I'm playing with inject JavaScript code into an existing DOM.
I've seen that if I put the script by hand in the browser's DOM elements inspector
<script>alert("XSS test");</script>
the script node is added to the DOM, but it has no effect. I mean, no alert box is shown.
On the other hand, if I put the script as plain text through the JavaScript console using document.write(), in this case the code got parsed and executed immediately, and the alert box is shown as expected.
document.write('<script>alert("XSS test");</script>');
I'm used to see that hand made changes to the DOM elements in the inspector reflects immediately in the page, while it seems that JavaScript nodes are an exception.
Why web browsers do not execute JavaScript nodes put by hand in the inspector?
Is there another way to send the script node to the DOM and make it run immediately?
script tags added via innerHTML and related methods (insertAdjacentHTML, etc.) are not executed. (The exact rules are somewhere in the script portion of the HTML specification but it's heavy going.) This may be because early on it was identified that poorly-written pages might use innerHTML and such to append user content, and so not executing it was a quick and simple way to avoid very, very basic XSS attacks. But only very, very basic ones.
You can add a script tag to the DOM and have it executed by creating and appending a script tag:
const script = document.createElement("script");
script.textContent = `console.log("Hi there");`;
document.body.appendChild(script);
You can do that from the console tab in devtools, for instance, rather than the DOM inspector tab.
try going to the web page you want and then in the URL bar at the top add
javascript:[your script]
for example
javascript:alert("Hello World!");
Related
This:
function myFunction()
{
document.write("sup");
}
called in html like:
<div id="myDiv">
<script>myFunction();</script>
</div>t
adds a string sup to the myDiv div element. Which is what I want, exactly. However, this:
function loadFile(uri)
{
var r = new XMLHttpRequest();
document.write("trying to open: " + uri);
r.open('GET', uri, true);
r.send(null);
r.onreadystatechange = function()
{
if (r.readyState == 4)
{
myFunction();
}
}
}
function myFunction()
{
document.write("sup");
}
called like this:
<div id="myDiv">
<script>loadFile("filename.txt");</script>
</div>
seems to be overwriting my whole html file. I.e. when I run it in Firefox it shows me only the string sup (that's the whole content of the page) but the page seems to be still loading (the loading icon of FF is still there animating, apparently infinitely).
First of all, this is going to be used only locally, offline, as a fast and handy way of presenting data (using html+js and web browser instead of plain text file). What I want is to load a local text file and then put some of its content as a part of the html page. The same as in my first example but with loading the text file first.
The issue is that when you run document.write after the document has loaded, it overwrites the entire document. If it is run before that, it does not overwrite it.
What you want to do is set the innerHtml of a specific element, something like:
document.getElementById("myDiv").innerHTML="Sup";
Lets go over what a browser does when it receives an html file.
The window document is opened for writing. Imagine opening a text file.
Browser writes the contents to the document. A lot of magic happens in this step - objects get created and html rendered as boxes.
The window document closes the document. Kind of like saving the text file.
Now, modern browsers also expose a document API that allow you to do exactly those tasks using javascript.
You can open a document for writing using document.open(). You can also start writing content to the document using document.write(). Finally, you can close the document for writing using document.close(). Since the document always needs to be opened for writing before you write, calling document.write() always results in an implicit document.open().
Interspersing document.write() calls throughout an html body is a commonly used technique used to insert string contents dynamically into an html page.
For example, if you execute document.write("<p>holla</p>") in the body of an html file, the browser will do the following upon receiving the html file.
Open the document for writing.
Start writing the html contents to the document.
JavaScript engine will execute document.write() when it encounters it and then write "<p>holla</p>" into that specific line in the document, just as if the string was already part of the html file! Since document.write() is called during the parsing of an html file, it just gets parsed as part of the page.
Close the document for writing. Parsing complete.
If that's how you use document.write(), there would have been no surprise. Instead, you call document.write() after the html is parsed.
So what do you think should happen?
As I mentioned before, a document needs to be opened for writing before it is written to. In theory, we could either append to the existing content or just overwrite it. Well, if we append to the content, we'll end up with an invalid html page because the new values will appear after the closing tags. So the more sensible behavior is to overwrite the content and that's exactly what happens.
I am trying to build a content editor. This contenteditor will load a HTML document (with JavaScript) into for example a #result element. The problem with this, is that if inside this HTML element there is for example $("input").hide();, then all of my inputs are gone throughout the whole page, so not just inside the loaded HTML (my goal).
What I want to do with the editor is when a client clicks on an element that represents something in the database, the info of this element will popup and the user will be able to edit this. (So, if a user hovers over a form with the class "contact-form" (which is in the database, connected to the loaded page) a new window will popup with information about this specific form element.
Also, I cannot completely disable Javascript, since the loaded HTML might contain Javascript for styling etc.
My goal: Remove Javascript, that can be annoying when a user loads in an HTML file. Like an alert(); Also, remove the ability for the Javascript to edit somehthing outside it's own DOM.
P.S. I am open to better workarounds like using an iframe for this, BUT I want to be able to hover over elements in interact with them.
Edit: It seems that this question might be a bit too broad, looking at the comments. Summary of my question: How can I disable alert() for a specific div and how can I create a sandbox so that code inside a div, can only change elements from inside that div.
What you're looking for is HTML sanitization. This is the process by which you remove any dangerous content from a snippet of HTML on the server, before it's loaded in the browser. There are plenty of sanitization libraries out there that can strip script tags, object tags, etc. Just remember, you can't sanitize using javascript because by the time you've injected your script, another malicious script may have already loaded and run.
The only way to effectively sandbox a javascript environment is with iframes. You'll notice that websites like CodePen, JSBin and JSFiddle use them extensively. There's something called the ShadowDOM, which is the basis of Web Components, but it isn't very well supported yet.
To make it possible to run your own frontend scripts that allow for hovering, you can inject your script after your sanitization process. This way, if it's loaded inside an iframe your script will also be loaded.
Finally, alert() doesn't belong to any elements on the DOM. You can trigger an alert as soon as the page loads, for example. However, if you're trying to prevent alerts from popping up on user interactions, you could try removing all event listeners from a particular element. This won't be necessary if you sanitize the HTML of script tags, however, since the script wouldn't have had a chance to load so there won't be any event listeners.
You can use ShadowDOM to load an html document into a host node. See also WHY SHADOW DOM?
As the title says, if I remove a script tag from the DOM using:
$('#scriptid').remove();
Does the javascript itself remain in memory or is it cleaned?
Or... am I completely misunderstanding the way in which browsers treat javascript? Which is quite possible.
For those interested in my reason for asking see below:
I am moving some common javascript interactions from static script files into dynamically generated ones in PHP. Which are loaded on demand when a user requires them.
The reason for doing this is in order to move the logic serverside and and run a small script, returned from the server, clientside. Rather than have a large script which contains a huge amount of logic, clientside.
This is a similar approach to what facebook does...
Facebook talks frontend javascript
If we take a simple dialog for instance. Rather than generating the html in javascript, appending it to the dom, then using jqueryUI's dialog widget to load it, I am now doing the following.
Ajax request is made to dialog.php
Server generates html and javascript that is specific to this dialog then encodes them as JSON
JSON is returned to client.
HTML is appended to the <body> then once this is rendered, the javascript is also appended into the DOM.
The javascript is executed automatically upon insertion and the dynamic dialog opens up.
Doing this has reduced the amount of javasript on my page dramatically however I am concerned about clean up of the inserted javascript.
Obviously once the dialog has been closed it is removed from the DOM using jQuery:
$('#dialog').remove();
The javascript is appended with an ID and I also remove this from the DOM via the same method.
However, as stated above, does using jQuery's .remove() actually clean out the javascript from memory or does it simple remove the <script> element from the DOM?
If so, is there any way to clean this up?
No. Once a script is loaded, the objects and functions it defines are kept in memory. Removing a script element does not remove the objects it defines. This is in contrast to CSS files, where removing the element does remove the styles it defines. That's because the new styles can easily be reflowed. Can you imagine how hard it would be to work out what a script tag created and how to remove it?
EDIT: However, if you have a file that defines myFunction, then you add another script that redefines myFunction to something else, the new value will be kept. You can remove the old script tag if you want to keep the DOM clean, but that's all removing it does.
EDIT2: The only real way to "clean up" functions that I can think of is to have a JS file that basically calls delete window.myFunction for every possible object and function your other script files may define. For obvious reasons, this is a really bad idea.
If your scripts have already executed removing the DOM elements are not going to get rid of them. Go to any page with JavaScript, open up your preferred javascript console and type $("script").remove(). Everything keeps running.
And this demonstrates #Kolink answer:
http://jsfiddle.net/X2mk8/2/
HTML:
<div id="output"></div>
<script id="yourDynamicGeneratedScript">
function test(n) {
$output = $("#output")
$output.append("test " + n + "<br/>")
}
test(1);
</script>
Javascript:
$("script").remove();
// or $("#yourDynamicGeneratedScript").remove();
test(2);
test(3);
test(4);
function test(n) {
$output = $("#output")
$output.append("REDEFINED! " + n + "<br/>")
}
test(5);
test(6);
test(7);
I've seen in several plugin instructions , paste the javascript/jQuery source just before the end of body tag. I made search why they are saying like that, didn't make me any sense.
If I put the src file where ever in the script, I never faced a problem at all. Could anyone give me a good answer about this?
If javascript code does not reference the DOM or any objects in the DOM, then it can be put anywhere in your page.
If you put it AFTER the HTML in the body tag right before the </body> tag, then the page will be parsed and displayed before your scripts load which will get your page displayed faster. So, the recommendation you've seen is to maximize the initial display performance of your pages.
If javascript DOES reference the DOM or any objects in the DOM, then it must either have special code to wait for the DOM to be loaded before executing using something like $(document).ready(fn) in jQuery or the code must physically be loaded after the DOM so that it won't execute until the DOM is loaded.
And, of course, code must be loaded after any code that it's initial execution immediately depends upon. So, a jQuery plugin would need to be loaded after the jQuery library itself.
Here's a general set of guidelines:
Put code as late as possible in the page to maximize the display performance of your page.
Put code after any other libraries that its initial execution depends on.
Put code in the <head> section only if that code needs to execute or be used before the document loads. As an example, if you had code that was examining the URL and cookie and deciding whether to do a client-side redirect, you want that code to execute immediately so you might put that code in the <head> section so it can execute before the DOM loads or displays. As another example, if you have some inline javascript that needs certain functions to be available during the page load (e.g. some inline javascript that does document.write() and calls some utility functions), then put those utility functions in the <head> section so they are available as the page loads.
If there is no reason to execute the code before the page loads or if the code needs to access the DOM itself, then put the code right before the </body> tag to optimize page display time and position the code where the DOM is ready for manipulation when the code runs.
Put code in external JS files whenever possible to take maximum advantage of browsing caching.
I could insert online javascript to the current DOM as below,
s = document.createElement('script');
s.src = 'http://url/script.js';
document.appendChild(s);
But Can I preload the script here and customize it a little before it is evaluatied? Is there any javascript could be used to do so?
EDIT: the last line in the above code shoudl be document.getElementsByTagName('head')[0].appendChild(s)
You could use XHR to load it as text, modify it, then isert it as the content of a script element. It will not be executed until it is in the DOM.
You append script tags this way to the head object, not to the document object like this:
document.getElementsByTagName('head')[0].appendChild(s).
And, when you load them this way, they will load asychronously and then execute as soon as they are loaded. You will not be able to mess with them before they execute. You can register to be notified when they are loaded and have successfully been executed, but can't control when they execute.