Is this considered DOM-XSS or self-XSS or both? - javascript

SCENARIO:
A web page shows an error login page using these javascript lines
<script>
let queryParams = new URLSearchParams(window.location.search);
document.getElementById("message").innerText = queryParams.get("message");
let link = document.getElementById("link");
link.innerText = queryParams.get("linkText");
link.href = queryParams.get("linkUrl");
</script>
The last javascript line allows me to hide javascript inside a link in the web page crafting an url like the following.
https://vulnerablewebsite.com/folder/custom.html?message=not+correct?&linkUrl=javascript:alert(1)&linkText=click+here+to+shine
1) the user click the shortened version of this link
2) the user click "click here to shine"
3) the alert opens
I was inspired by this article on portswigger
https://portswigger.net/web-security/cross-site-scripting/dom-based
in particular from this example
If a JavaScript library such as jQuery is being used, look out for
sinks that can alter DOM elements on the page. For instance, the
attr() function in jQuery can change attributes on DOM elements. If
data is read from a user-controlled source like the URL and then
passed to the attr() function, then it may be possible to manipulate
the value sent to cause XSS. For example, here we have some JavaScript
that changes an anchor element's href attribute using data from the
URL:
$(function(){ $('#backLink').attr("href",(new
URLSearchParams(window.location.search)).get('returnUrl')); });
You can exploit this by modifying the URL so that the location.search
source contains a malicious JavaScript URL. After the page's
JavaScript applies this malicious URL to the back link's href,
clicking on the back link will execute it:
?returnUrl=javascript:alert(document.domain)
QUESTION:
to me they look the same kind of attack but someone told me it is a self-XSS. Anyway I read that self-XSS expects the user to self-paste javascript code in his console. So I'm confused and I'd like to know which type it is. Also, can be considered a vulnerability of medium/high severity or not?

Naming doesn't matter much, but
It is definitely a vulnerability, according to CVSSv3 it would likely be a medium, but you can calculate yourself for this specific case.
It is not self xss, you yourself showed a way via a link that if sent to a victim by an attacker would make the page vulnerable.
It is definitely dom xss as it is entirely in javascript, no server roundtrip is necessary.

Related

Replace HTML code with code from another page

I have got two html files, say page1.html and page2.html. In both files I have an article element. Now, on page1.html I would like to replace the content of the article element with that of page2.html using JavaScript (I don't want to use jQuery).
Currently, my solution is the following: When page1.html is loaded, I use the fetch method to get the content of page2.html's article element. Then, when the user clicks a button, I call
article.innerHTML = newContent;
This does work fine so far, but recently I've read that innerHTML shouldn't be used to prevent XSS attacks. Obviously, I cannot set the property article.textContent since I've got "real" html code in my articles that I want to be interpreted as such. Another solution I could think of is to include the html code in the script file as a string. The downside of this method would be that I would have to change both page2.html and the script file, whenever I want to change the article.
Is there a recommended way to achieve what I want to do? Also, all the examples of XSS attacks I've read about seem to indicate that my specific use of innerHTML doesn't allow XSS attacks (since I fetch the code from a site which I control myself), but I don't just want to be like "I can't think of an XSS attack, so there'll never be one". Any insights about the danger of XSS attacks in this context?
In case you have control over the content of this page2.html i.e. either you have a static or dynamic data which is not generated by the visitors visiting your webpages, then there is won't be any issue of XSS attack. In such cases you can confidently use innerHtml method.
But, in case the content of the page2.html contains the data from visitors (such as comments, posts, etc.) then only there is a chance of XSS attack. XSS attack is nothing but when your user put some JavaScript code for their advantage.
E.g. In case your page2.html contains comments, I can post comment like Hello world! <script> alert("You have been hacked, transfer money to this bank to save your computer") </script>. Or I can attach link to another vulnerable script which steal your user's data like cookie data.
For such use cases, please do not use innerHtml directly. The safe solution is either use textContent or sanitize your visitor's data (like the comment mentioned above) (Ref: https://remarkablemark.org/blog/2019/11/29/javascript-sanitize-html/)
try the following code here you have to call the .text() method in fetch response to get the actual HTML and insert it using Element.innerHTML
fetch('DataPage.html') .then((res) => res.text()) //here you have to change the response into html text .then(res => {document.querySelector("#target").innerHTML = res;})
You can do this with PHP.
<?php echo file_get_contents('./to/file'); ?>
This downloads the files with the thing. You could also do it with include.
<?php include "./to/file"; ?>

Where should I put urls in an AJAX based web project?

I am on my way to some web development at the moment. There I have a set of views (different versions of the site the user will be able to see). Many of those allow some interaction that is JS/Ajax based. This is just the context of this question:
Where can I put the request URLs of the various ajax requests?
I know this seems a little stupid this question thus let me explain a bit. I assume jQuery but this question is basically not strictly related to it. I will try to give very minimalistic snippets to see the idea, these are of course not 1:1 correct/finished/good.
Typically such a site has not only one single type of request but a whole bunch of these. Think of a site where the user sees his personal data like name, mail, address, phone etc. On clicking on one such entry, a minimal form should be displayed to allow modification of the entry. Of course you need minor changes in the replacements (e.g. distinguish between change name and change phone).
First approach was to write ajax code for each and every possible entry separately in a JS file. I mean that each entry gets its own html id and I just replace the content of the element with the named id with the new content. I write code for each id explicitly in JS causing quite some redundancy in code (although a well designed set of functions will help here):
$("#name").click(function(){ /* replace #name, hardcode url */});
$("#phone").click(function(){ /* replace #phone, hardcode url */});
One other way was to put some <a> tag with the href set to the url of the AJAX request. Then the developer can define some classes that need to follow a defined and fixed scheme. The JS code gets smaller in size as only a single event must be registered and I need to follow the convention throughout the site.
<div class='foo'>... <a href="ajax.php?first" class="ajax"></div>
<div class='foo'>... <a href="ajax.php?second" class="ajax"></div>
and the simplified JS:
$(".foo a.ajax").click(function(ev){ /* do something and use source of ev to fetch the url */ });
This second method could be done even worse if you did put the url in any html tag and hide it from the user (scary).
Ideally one should write the page such, that all interaction that is AJAX-enabled should be doable with JS disabled as well. Thus I think the way of putting the urls in <a> tags is not good. However I think hardcoding them is also not ideal.
So did I miss a useful/typical part of how one can do this? is there even some consesus where such data can be located best?
If your website is big enough, you should seperate your urls based on modules such as banking, finance, user etc. But if you do not have that much urls, you can store all of them in a single javascript file.
You should store BASE url in a single javascript file with all of should import it(in case of your domain changes or development to production mode).
//base_url.js
var BASE_URL_PROD = "www......com"; // production server url
var BASE_URL_DEV = "localhost:3000"; // local server url
var BASE_URL = BASE_URL_DEV; // change this if you are on dev or prod mode.
// urls.js
var FETCH_USER = BASE_URL + "/user/fetch";
var SAVE_USER = BASE_URL + "/user/save";
// in some javascript class
$("#clickMe").ajax({url: FETCH_USER} ...);
The question here is: do you want to offer a way to access the information, if javascript is turned off or not loaded yet?
You already answered yourself: If javascript is disabled or not loaded yet, the user will directly go to the given url.
If you want to offer a none-javascript way, change your controller and check for ajax request or just use the javascript way, like Abdullah described already.

can firefox extension modify DOM of HTML document then save as HTML?

I am creating a firefox extension that lets the operator perform various actions that modify the content of the HTML document. The operator does not edit HTML, they take other actions and my extension modifies the document by inserting elements, adding attributes, and so forth.
When the operator is finished, they need to be able to save the HTML document as a file (or have my extension send it to an internet destination, but this is not required since they can email the saved file).
I thought maybe the changes made by the javascript code in my extension would be reflected in the HTML document, but when I ask the firefox browser to "view source" after making modifications, it displays the original HTML text.
My questions are:
#1: What is the easiest way for the operator to save the HTML document with all the changes my extension has made?
#2: What is the easiest way for the javascript code in my extension to process the HTML document contents and write to an HTML file on the local disk?
#3: Is any valid HTML content incapable of accurate representation in the saved file?
#4: Is the TreeWalker part of the solution (see below)?
A couple observations from my research so far:
I've read about the TreeWalker object, which seems to provide a fairly painless way for an extension to walk through everything (?or almost everything?) in the HTML document. But does it expose everything so everything in the original (and my modifications) can be saved without losing anything of importance?
Does the TreeWalker walk through the HTML document in the "correct order" --- the order necessary for my extension to generate the original and/or modified HTML document?
Anything obscure or tricky about these problems?
Ok so I am assuming here you have access to page DOM. What you need to do it basically make changes to the dom and then get all the dom code and save it as a file. Here is how you can download the page's html code. This will create an a tag which the user needs to click for the file to download.
var a = document.createElement('a'), code = document.querySelectorAll('html')[0].innerHTML;
a.setAttribute('download', 'filename.html');
a.setAttribute('href', 'data:text/html,' + code);
Now you can insert this a tag anywhere in the DOM and the file will download when the user clicks it.
Note: This is sort of a hack, this injects entire html of the file in the a tag, it should in theory work in any up to date browser (except, surprise, IE). There are more stable and less hacky ways of doing it like storing it in a file system API file and then downloading that file instead.
Edit: The document.querySelectorAll line accesses the page DOM. For it to work the document must be accessible. You say you are modifying DOM so that should already be there. Make sure you are adding the code on the page and not your extension code. This code will be at the same place as your DOM modification code, not your extension pages that can't access the DOM.
And as for the a tag, it will be inserted in the page. I skipped the steps since I assumed you already know how to manipulate DOM and also because I don't know where you would like to add the link. And you can skip the user action of clicking the link too, but it's a hack and only works in modern browsers. You can insert the a tag somewhere in the original page where user won't see it and then call the a.click() function to simulate a click event on the link. But this is not a legit way and I personally only use it on my practice projects to call click event listeners.
I can only test this on chrome not on FF but try this code, this will not require you to even add the a link to DOM. You need to add this next to the DOM manipulation code. This will work if luck is on your side :)
var a = document.createElement('a'), code = document.querySelectorAll('html')[0].innerHTML;
a.setAttribute('download', 'filename.html');
a.setAttribute('href', 'data:text/html,' + code);
a.click();
There is no easy way to do this with the web API only, at least when you want a result that does not omit stuff like the doctype or comments. You could still write a serializer yourself that goes through document.childNodes and serialized according to the node type (Element.outerHTML, Comment.data and so on).
Luckily, you're writing a Firefox add-on, so you have access to a lot more (powerful) stuff.
While still not 100% perfect, the nsIDocumentEncoder implementations will produce pretty decent results, that should only differ in some whitespace and explicit charset declaration at most (everything else is a bug).
Here is an example on how one might use this component:
function serializeDocument(document) {
const {
classes: Cc,
interfaces: Ci,
utils: Cu
} = Components;
let encoder = Cc['#mozilla.org/layout/documentEncoder;1?type=text/html'].createInstance(Ci.nsIDocumentEncoder);
encoder.init(document, 'text/html', Ci.nsIDocumentEncoder.OutputLFLineBreak | Ci.nsIDocumentEncoder.OutputRaw);
encoder.setCharset("utf-8");
return encoder.encodeToString();
}
If you're writing an SDK add-on, stuff gets more complicated as the SDK abstracts some important stuff away. You'll need to go through the chrome module, and also figure out the active window and tab yourself. Something like Services.wm.getMostRecentWindow("navigator:browser").content.document (Services.jsm) should do the trick.
In XUL overlay add-ons, content.document should suffice to get the document of the currently active tab, and you have Components access already.
Still, you need to let the user choose a file destination, usually through nsIFilePicker and then actually write the file, by using something like a file stream or the fully async OS.File API.
Looks like I get to answer my own question, thanks to someone in mozilla #extdev IRC.
I got totally faked out by "view source". When I didn't see my modifications in the window displayed by "view source", I assumed the browser would not provide the information.
However, guess what? When I "file" ===>> "save page as...", then examine the page contents with a plain text editor... sure enough, that contained the modifications made by my firefox extension! Surprise!
A browser has no direct write access to the local filesystem. The only read access it has is when explicitly provide a file:// URL (see note 1 below)
In your case, we are explicitly talking about javascript - which can read and write cookies and local storage. It can also send stuff back to the server and retrieve it, e.g. using AJAX.
Stuff you put in local storage/cookies is effectively not accessible to other programs (such as email clients).
It is possible to create very long mailto: URLs (see note 2) but only handles inline content in the email and you're going to run into all sorts of encoding issues that you're not ready to deal with.
Hence I'd recommend pursuing storage serverside via AJAX - and look at local storage once you've got this sorted/working.
Note 1: this is not strictly true. a trusted, signed javascript has access to additional functions which may include direct file access.
Note 2: (the limit depends on the browser and the email client - Lotus Notes truncaets the content rather a lot)

How can I customise all assignments to window.location.href?

In my JavaScript application, we have multiple places where we have used window.location.href="any string";. Now I want to write JS code in only one place (probably using window.location.prototype) to override assignments to href, so that I can append a parameter to all instances.
I want to append a parameter (e.g. "?abc=1234") to all urls which are assigned to window.location.href.
I want to write code that means when e.g.
window.location.href = "abc.html";
is written, it should actually result in the href being set to abc.html?abc=1234.
window.location.href = window.location.href + "?abc=1234"
I just test this in WebKit DevTools/
You can't actually do this.
It's more of the JavaScript engine which runs the page. All records in most browsers which are stored of your browsing is the history. Hardly anything else. So basically to the browser, there is no difference between a meta redirect, a header redirect and a javascript redirect.
Unless I'm wrong.

Get objects from javascript using URL without loading the document

I have an URL which links to a HTML docment, and i want to get objects of the document without load the URL in my browser. for instance, i have an URL named:
http://www.example.com/,
how can i get one object (i.e., by getElementsbyTagName) of this document?
You can't. You can omit, at best, extraneous files being linked to from within the document like javascript or css, but you can't just grab one part of the document.
Once you have the document, you can grab out of it a section, but you can't just grab a section without getting the whole thing first.
It's the equivalent of saying that you want the 2nd paragraph of an essay. Without the essay, you don't know what the 2nd paragraph is, where it starts or ends.
Is this document in the same domain, or a different domain as the security domain your javascript is running in.
If it's in the same domain, you have a couple options to explore.
You could load the page using an XMLHttpRequest, or JQuery.get, and parse the data you're looking for out of the HTML with an ugly regular expression.
Or, if you're feeling really clever, you can load the target document into a jsdom object, jQuerify it, and then use the resulting jquery object to access the date you're looking for with a simple selector.
If the url is on the same domain you can use .load() for example:
$("some_element").load("url element_to_get")
See my example - http://jsfiddle.net/ajthomascouk/4BtLv/
On this example it gets the H1 from this page - http://jsfiddle.net/ajthomascouk/xJdFe
Its hard to show using jsfiddle, but I hope you get the gist of it?
Read more about .load() here - http://api.jquery.com/load/
Using Ajax calls, I guess.
This is long to explain if you have never used XHR, so here's a link: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest
Another option is to construct an iframe using
var iframe = document.create('iframe');
iframe.src = 'http://...';

Categories

Resources