Solving code injection in JavaScript - javascript

I've been given a task to deal with security vulnerabilities. I've ran a test on all custom JavaScript files in our project using DefenseCode ThunderScan and found several high threat vulnerabilities, all of them associated with 'code injection'. Example of piece of code where the vulnerability was found:
setTimeout(function () {
window.location.href = Urls.getHuhnScaleIndexDataUrl.replace('ResidentId',
model.residentId()).replace('SessionVal', true);
}, 2000);
window.open(urlReport, '_blank');
What exactly poses a vulnerability in these code examples?

Using windows.open is considered bad practice because the new windows retains a reference to the parent one and can then try to inject / code into it.
The new window has an opener field which points to the former window with unrestricted access, which means you can delete the body of the parent or steal tokens embedded in forms...
Reference: https://dev.to/ben/the-targetblank-vulnerability-by-example

Related

Javascript redirect not working in Edge browser when opened with android ActionView intent, but working after manual reload

Situation
In our Android app (Xamarin), we open a web page using an ActionView intent. The code looks like this:
Intent intent = new Intent((string)Intent.ActionView, Android.Net.Uri.Parse(args.url));
intent.AddFlags(ActivityFlags.NewTask);
The opened page at some point does a JS redirect, with a line like this:
window.location = '...';
We tried many different variations of that line, including window.location.href = '...', window.location.assign('...'); and some more. All show the same behavior.
Problem
This has worked fine for years now, in all browsers - but now we ran into a problem, when the browser on the android device is the Edge browser:
When the browser tab is initially opened by the intent, the window.location = '...' line in Javascript is just ignored by the browser. No error message - just ignored.
However, if that same browser tab with exactly the same URL is opened manually (either by reloading or by copying and pasting the URL), the JS redirect is executed just fine.
Question
How do we fix this, how do we make the JS redirect reliably work?
My guess is that we are running into a security feature, which prevents JS redirects in browser tabs that the user has never interacted with.
Is there something (maybe an intent flag?) to circumvent this? We already tried the flag GrantWriteUriPermission, but it did not help.
Possible duplicates
Android Browser Facebook Redirect Does Not Always Trigger Intent for URL :
The proposed situation of setting the URL on a link and faking a click on it did not work.
Microsoft Edge security
Microsoft Edge recently fixed an issue regarding XSS Targeting Non-Script Elements (June 24, 2021).
The vulnerability was found by two researcher when they visited a website in another language via the Microsoft Edge browser and attempted to translate the page. The goal of the recent fix by Microsoft is to avoid vulnerability regarding accessing dynamically to a content from a third party application and specifically in the case of browser redirection. They need to act quickly because the vulnerability is quite huge.
In order to mitigate a large class of potential cross-site scripting issues, the Microsoft Edge Extension system has incorporated the general concept of Content Security Policy (CSP)
Ok, but ... is there any solution?
Maybe you can find a solution to solve your issue here, in particular the part concerning the <button onclick="...">.
Inline code is considered harmful in concept of CSP and microsoft recommend some good practices :
1 - The clickHandler definition must be moved into an external JavaScript
2 - The inline event handler definitions must be rewritten in terms of addEventListener and extracted into your external js file. If you are currently starting your program using code like <body onload="main();">, consider replacing it by hooking into the DOMContentLoaded event of the document, or the load event of the window, depending on your requirements. Use the former, since it generally triggers more quickly.
3 - Function inside onclick call must be rewritten to avoid converting the string of function into JavaScript for running.
The code exemple of the external .js file cited in the documentation look like this :
function awesome() {
// Do something awesome!
}
function totallyAwesome() {
// do something TOTALLY awesome!
}
function awesomeTask() {
awesome();
totallyAwesome();
}
function clickHandler(e) {
setTimeout(awesomeTask, 1000);
}
function main() {
// Initialization work goes here.
}
// Add event listeners once the DOM has fully loaded by listening for the
// `DOMContentLoaded` event on the document, and adding your listeners to
// specific elements when it triggers.
document.addEventListener('DOMContentLoaded', function () {
document.querySelector('button').addEventListener('click',
clickHandler);
main();
});
Hope it's helps

Firefox add-on declaring functions and use in content script

i am trying to write my first firefox add-on. the main problem seem s to be that i am also new to javascript. at the moment i have:
require('sdk/page-mod').PageMod({
include: ["*"],
contentScript: 'window.addEventListener("click", function(e) { alert("blub"); }, false);',
attachTo: ["existing", "top"]
});
(thx to the answer here.)
now i want to use a declared function instead of an anonymous one, but i cant get it to work:
require('sdk/page-mod').PageMod({
include: ["*"],
contentScript: 'window.addEventListener("click", function(e) { alert("blub"); }, false);',
attachTo: ["existing", "top"]
});
getImgData function (e) {
alert("blubber3");
}
the first problem is i get syntax error by just adding the function "missing ; before statement". But cfx doesn't tell me the wrong line. (Is there any useful tool for js editing with good syntax check/ content assist?)
So how to declare a function and use ist somewhere else in the script. At the end the function needs to get the target of click and parse it.
(i read the tutorials but thy all use anonymous functions :-P)
thx in advance
It's important to realize the separation between chrome scripts and content scripts. Chrome scripts are those that run with the same security privileges as Firefox - they have full access to Firefox and your computer. Content scripts are those that run with the same privileges as web pages. They can mess around with that web page, but are severely restricted otherwise. To maintain security, the way these two types of scripts can communicate is limited. You wouldn't want a web page to be able to call any function it wants in your extension's internal code!
Your main JS file (the one that includes require('sdk/page-mod')) is a chrome script. What you're injecting (contentScript) is (obviously) a content script. They can't communicate through a direct function call as you're doing.
If your getImgData function is something that can be done with normal web page privileges, you can move your definition of it to within the content script. If it requires additional privileges, you must have your content script communicate with your chrome script via the emit and on functions as described in the link above.
If you are going to make your content script any longer, I would recommend you separate it into its own file to make your life easier.

Is there a phantomJS injection vulnerability in page.evaluate()?

Using PhantomJS you can execute code in the browser by doing page.evaluate(). Are we opening ourselves up to an attack vector if we allow users to specify code which could be executed in that browser context? Is there a way to escape from the browser context into the phantomJS environment thereby executing commands on our servers?
Here's an example:
page.open(options.url, function(status) {
var test = function() {
return page.evaluate(function() {
return eval({{USER JAVASCRIPT STRING}});
});
});
var interval = setInterval(function() {
if (test()) {
clearInterval(interval);
// take screenshot, do other stuff, close phantom
}
}, 250);
});
From my understanding, the eval() occuring inside the page.evaluate() prevents them from ever escaping the context of the page which was opened. The user javascript string is passed as a string (it is not "compiled" into a single javascript file). It appears to me that it is no different then a user browsing to a site with a browser and attempting to hack away through their favorite Javascript console. Thus, this usage does not represent a security vulnerability. Is this correct?
Update
To provide a little more clarity about the exact use case. The basic gist is that someone will go to a url, http://www.myapp.com/?url=http://anotherurl.com/&condition={{javascriptstring}}. When a worker is available, it will spin up a phantom instance, page.open the URL provided, and then when condition is met, it will take a screenshot of the webpage. The purpose for this is that some pages, especially those with massive amounts of async javascript, have bizarre "ready" conditions that aren't as simple as DOM ready or window ready. In this way the screenshot won't be taken until a javascript condition is true. Examples include $(".domNode").data("jQueryUIWidget").loaded == true or $(".someNode").length > 0.
I'm not very familiar with PhantomJS, but eval is inherently unsafe when it comes to running unknown code. It would be very easy to escape the intended context:
return page.evaluate(function() {
return eval({{javascriptstring}});
});
http://example.com/?url=http://anotherurl.com/&condition={{javascriptstring}}
How about where {{javascriptstring}} equals:
console.log('All your script are belong to us');
I'm not sure what kind of nasty things you could do with PhantomJS, but it's an example of a user being able to run any code they want, so this doesn't sound like a good idea. The user string could literally be an entire program.
To clarify, the injection vulnerability is not in page.evaluate(), it's in the eval in your code.
Yes, this is DOM based XSS. This is a vulnerability that can be used to hijack user's (or administrative) sessions and expose users to other attacks.
If the input comes from a GET/POST or Fragment or part of the URL then its very easy to exploit. If the input comes from the UI, then it can be exploited with clickjacking.

Take Screenshot of Browser via JavaScript (or something else)

For support reasons I want to be able for a user to take a screenshot of the current browser window as easy as possible and send it over to the server.
Any (crazy) ideas?
That would appear to be a pretty big security hole in JavaScript if you could do this. Imagine a malicious user installing that code on your site with a XSS attack and then screenshotting all of your daily work. Imagine that happening with your online banking...
However, it is possible to do this sort of thing outside of JavaScript. I developed a Swing application that used screen capture code like this which did a great job of sending an email to the helpdesk with an attached screenshot whenever the user encountered a RuntimeException.
I suppose you could experiment with a signed Java applet (shock! horror! noooooo!) that hung around in the corner. If executed with the appropriate security privileges given at installation it might be coerced into executing that kind of screenshot code.
For convenience, here is the code from the site I linked to:
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
...
public void captureScreen(String fileName) throws Exception {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Rectangle screenRectangle = new Rectangle(screenSize);
Robot robot = new Robot();
BufferedImage image = robot.createScreenCapture(screenRectangle);
ImageIO.write(image, "png", new File(fileName));
}
...
Please see the answer shared here for a relatively successful implementation of this:
https://stackoverflow.com/a/6678156/291640
Utilizing:
https://github.com/niklasvh/html2canvas
You could try to render the whole page in canvas and save this image back to server. have fun :)
A webpage can't do this (or at least, I would be very surprised if it could, in any browser) but a Firefox extension can. See https://developer.mozilla.org/en/Drawing_Graphics_with_Canvas#Rendering_Web_Content_Into_A_Canvas -- when that page says "Chrome privileges" that means an extension can do it, but a web page can't.
Seems to me that support needs (at least) the answers for two questions:
What does the screen look like? and
Why does it look that way?
A screenshot -- a visual -- is very necessary and answers the first question, but it can't answer the second.
As a first attempt, I'd try to send the entire page up to support. The support tech could display that page in his browser (answers the first question); and could also see the current state of the customer's html (helps to answer the second question).
I'd try to send as much of the page as is available to the client JS by way of AJAX or as the payload of a form. I'd also send info not on the page: anything that affects the state of the page, like cookies or session IDs or whatever.
The cust might have a submit-like button to start the process.
I think that would work. Let's see: it needs some CGI somewhere on the server that catches the incoming user page and makes it available to support, maybe by writing a disk file. Then the support person can load (or have loaded automatically) that same page. All the other info (cookies and so on) can be put into the page that support sees.
PLUS: the client JS that handles the submit-button onclick( ) could also include any useful JS variable values!
Hey, this can work! I'm getting psyched :-)
HTH
-- pete
I've seen people either do this with two approaches:
setup a separate server for screenshotting and run a bunch of firefox instances on there, check out these two gem if you're doing it in ruby: selenium-webdriver and headless
use a hosted solution like http://url2png.com (way easier)
You can also do this with the Fireshot plugin. I use the following code (that I extracted from the API code so I don't need to include the API JS) to make a direct call to the Fireshot object:
var element = document.createElement("FireShotDataElement");
element.setAttribute("Entire", true);
element.setAttribute("Action", 1);
element.setAttribute("Key", "");
element.setAttribute("BASE64Content", "");
element.setAttribute("Data", "C:/Users/jagilber/Downloads/whatev.jpg");
if (typeof(CapturedFrameId) != "undefined")
element.setAttribute("CapturedFrameId", CapturedFrameId);
document.documentElement.appendChild(element);
var evt = document.createEvent("Events");
evt.initEvent("capturePageEvt", true, false);
element.dispatchEvent(evt);
Note: I don't know if this functionality is only available for the paid version or not.
Perhaps http://html2canvas.hertzen.com/ could be used. Then you can capture the display and then process it.
You might try PhantomJs, a headlesss browsing toolkit.
http://phantomjs.org/
The following Javascript example demonstrates basic screenshot functionality:
var page = require('webpage').create();
page.settings.userAgent = 'UltimateBrowser/100';
page.viewportSize = { width: 1200, height: 1200 };
page.clipRect = { top: 0, left: 0, width: 1200, height: 1200 };
page.open('https://google.com/', function () {
page.render('output.png');
phantom.exit();
});
I understand this post is 5 years old, but for the sake of future visits I'll add my own solution here which I think solves the original post's question without any third-party libraries apart from jQuery.
pageClone = $('html').clone();
// Make sure that CSS and images load correctly when opening this clone
pageClone.find('head').append("<base href='" + location.href + "' />");
// OPTIONAL: Remove potentially interfering scripts so the page is totally static
pageClone.find('script').remove();
htmlString = pageClone.html();
You could remove other parts of the DOM you think are unnecessary, such as the support form if it is in a modal window. Or you could choose not to remove scripts if you prefer to maintain some interaction with dynamic controls.
Send that string to the server, either in a hidden field or by AJAX, and then on the server side just attach the whole lot as an HTML file to the support email.
The benefits of this are that you'll get not just a screenshot but the entire scrollable page in its current form, plus you can even inspect and debug the DOM.
Print Screen? Old school and a couple of keypresses, but it works!
This may not work for you, but on IE you can use the snapsie plugin. It doesn't seem to be in development anymore, but the last release is available from the linked site.
i thing you need a activeX controls. without it i can't imagine. you can force user to install them first after the installation on client side activex controls should work and you can capture.
We are temporarily collecting Ajax states, data in form fields and session information. Then we re-render it at the support desk. Since we test and integrate for all browsers, there are hardly any support cases for display reasons.
Have a look at the red button at the bottom on holidaycheck
Alternatively there is html2canvas of Google. But it is only applicable for never browsers and I've never tried it.
In JavaScript? No. I do work for a security company (sort of NetNanny type stuff) and the only effective way we've found to do screen captures of the user is with a hidden application.

How to bypass document.domain limitations when opening local files?

I have a set of HTML files using JavaScript to generate navigation tools, indexing, TOC, etc. These files are only meant to be opened locally (e.g., file://) and not served on a web server. Since Firefox 3.x, we run into the following error when clicking a nav button that would generate a new frame for the TOC:
Error: Permission denied for <file://> to get property Location.href from <file://>.
I understand that this is due to security measures within FF 3.x that were not in 2.x, in that the document.domain does not match, so it's assuming this is cross-site scripting and is denying access.
Is there a way to get around this issue? Perhaps just a switch to turn off/on within Firefox? A bit of JavaScript code to get around it?
In firefox:
In address bar, type about:config,
then type network.automatic-ntlm-auth.trusted-uris in search bar
Enter comma separated list of
servers (i.e.,
intranet,home,company)
Another way is editing the users.js.
In users.js, write:
user_pref("capability.policy.policynames", "localfilelinks");
user_pref("capability.policy.localfilelinks.sites", "http://site1.com http://site2.com");
user_pref("capability.policy.localfilelinks.checkloaduri.enabled", "allAccess");
But if you want to stop all verification, just Write the following line into users.js file:
user_pref("capability.policy.default.checkloaduri.enabled", "allAccess");
You may use this in firefox to read the file.
function readFile(arq) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var file = Components.classes["#mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(arq);
// open an input stream from file
var istream = Components.classes["#mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);
istream.init(file, 0x01, 0444, 0);
istream.QueryInterface(Components.interfaces.nsILineInputStream);
var line = {}, lines = [], hasmore;
do {
hasmore = istream.readLine(line);
lines.push(line.value);
} while(hasmore);
istream.close();
return lines;
}
Cleiton's method will work for yourself, or for any users who you expect will go through this manual process (not likely unless this is a tool for you and your coworkers or something).
I'd hope that this type of thing would not be possible, because if it is, that means that any site out there could start opening up documents on my machine and reading their contents.
You can have all files that you want to access in subfolders relative to the page that is doing the request.
You can also use JSONP to load files from anywhere.
Add "file://" to network.automatic-ntlm-auth.trusted-uris in about:config

Categories

Resources