Embeddable js interpreter for user's code? - javascript

Imagine website, where user can generate content via js.
For example.
User clicks button
It requests our api (not user's api)
Api returns object with specific fields.
We show select with user's defined options generated by user's code or some calculated result based on data we sent.
The idea is to give user an ability to edit visible content (using our structures, we know beforehand which fields in returned object do what things).
First solution "developed" in 5 minutes.
Users clicks button
It send all required data as context to our api.
We fetch from database user's defined code
// here is the code which we write (not user) and we know this code is safe
const APP_CONTEXT = parseInput(); // this can be parameters from command line
const ourLibrary = require('ourLibrary');
// APP_CONTEXT is variable which contains data from frontend. We control data inside APP_CONTEXT, user can not write to it
// here is user defined code
const someVar = APP_CONTEXT['fieldDescribedInOurDocumentation'];
const anotherVar = APP_CONTEXT['anotherFieldFromDocumentation'];
ourLibrary.sendToFrontend(someVar + anotherVar);
In this very simple example once user clicked on button, we sent api request to our api, user's code has been executed, we show result of execution. ourLibrary abstract the way the handling is completed.
The main problem as I think is the security. I think about using restricted nodejs process. No network access, no file system access.
Is it possible to deny any import/require in nodejs process? I want to let user only call all builtin js function (Math.min, Math.max, new Date(), +, -), declare functions and so on. So it will work like a sophisticated calculator. And also we should have an ability to send it back to frontend. For example, via rabbitmq + nodejs + websockets. We can use simple console.log if former is the problem.
Some possible solution (not secure, of course) using nodejs interpreter. We execute interpreter every time when action is required.
const APP_CONTEXT = parseInput();
const ourLibrary = require('ourLibrary');
const usersCode = getUsersCode();
eval(usersCode);
Inside usersCode they use ourLibrary.sendToFrontend to produce the result. But this solution allows user to use any builtin nodejs functions, like const fs = require('fs'). Of course access will be restricted using linux system (selinux or similar) but can I configure/setup nodejs to run as simple js interpreter? May be there is some other js interpreter exists which is safe to use? Safe means: only arithmetic, Date function, Math functions and so on. No filesystem access, no network access.

Related

Hide/Disable firebase functions for client

I am new to firebase and wondering how to disable specific functions for the client to manually put in the browsers console.
Example:
function createRoomDB(roomID, name, mode, start, length, aname, opcount, secrettoken) {
firebase.database().ref('rooms/' + roomID).set({
name: name,
mode: mode,
start: start,
length: length,
aname: aname,
opcount: opcount,
secrettoken: secrettoken
});
}
(The names have nothing to do with my question.)
Long story short: I don't want users to simply use this command to create new data. I know that you can't hide code on front-end, but what are the easiest and most efficient ways to disable this hell of a backdoor?
I am planning to host this application on GitHub pages.
Since your code can access the database, there is no way to prevent other code that runs on the same environment to also access the database.
This means you have two options:
Make sure all code (no matter who wrote it) only can perform authorized operations on the database.
Run the code in a different environment.
For the first option, you'll want to look into Firebase security rules, which automatically run server-side and can enforce most requirements.
For the second option, you could for example run the code in Cloud Functions for Firebase, and call that from your API. This allows you to hide any secret values and code in a trusted environment, but does mean that you'll need to ensure only authorized users can call that Cloud Function.

XXE Vulnerabilities in incoming XML strings in Javascript code prased in Java

I have an application that manages APIs.
As a part of creation of an API we allow users to enter some JavaScript that will be executed every time the API is hit.
This JavaScript is executed on the server side so the flow is -
End user hits API link generated by me
I run the JavaScript entered at API creation time
I forward the request to wherever
I return the result to the front end
The intended use case is to set some request headers and the like.
Now, we recently had a security audit and this of course opens the door to an XXE vulnerability -
var x='<?xml version="1.0"?><!DOCTYPE foo [ <!ELEMENT foo ANY ><!ENTITY lol SYSTEM "file:///etc/xxxx" >]><foo>&lol;</foo>';
var xee = new javascript.ScriptableDocument(x);
context.setVariable("request.queryparam.foo",xee.toString())
I will have this entire content body in Java but how do I block against XEE vulnerabilities? I can imagine I'd have to run through the incoming JavaScript look for any XML and use one of Java's well known XEE stripping methods (described here excellently).
But the persistent hacker can simply just befuddle any attempts to identify JavaScript XML identification on my part.
Example -
var a='<', b="?" c="x";
new javascript.ScriptableDocument(a+b+c+...);
Is this an unwinnable fight? Or is there something super obvious I can do to mitigate this?
Thanks!
Zulfi

Passing URL Arguments and HTML Output Order of Execution

This is directly related to the answer in Google Apps Script - possible charts types.
I am trying to extend the top answer by deploying it as a webapp instead of an add-on, and also to pass URL arguments to the app script.
Everything is exactly the same as the linked example above, except that I stripped out the addon code and put in the most basic webapp code by adding a doGet(e) function.
/*
//if I manually specify the values in the script, it works fine
var sheetRange = "A1:D20"; // standard range to gather data
var sheetTabName = "Sheet1"; //name of the tab in the spreadsheet to look for. must be unique
var spreadsheetId = '1CKQTQYXgt3YgnUXu0YHFeMcG5sMh99sj293oKRFVp4M'; //spreadsheet ID
*/
var sheetRange;
var sheetTabName;
var spreadsheetId;
function doGet(e) {
//but if I try to load the arguments from the URL, it doesn't work
//these values never get set here
sheetRange = e.parameter.sheetRange;
sheetTabName = e.parameter.sheetTabName;
spreadsheetId = e.parameter.spreadsheetId;
Logger.log("This never gets run %s %s %s",sheetRange,sheetTabName,spreadsheetId );
//but this template gets made
var template = HtmlService.createTemplateFromFile('BubbleEx')
.evaluate()
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setWidth(800)
.setHeight(600);
Logger.log("Why doesn't this get printed at least?");
//and returned
return template;
}
function getSpreadsheetData() {
Logger.log("This does get run!\nSpreadsheetId is: %s\nSheetRange is: %s\nSheetTabName is: %s",spreadsheetId,sheetRange,sheetTabName);
var sheet = SpreadsheetApp.openById(spreadsheetId);
var data = sheet.getSheetByName(sheetTabName).getRange(sheetRange).getValues();
return (data.length > 1) ? data : null;
}
Clearly I'm missing something fundamental about the order of execution here. Something about the way the HTML is interacting with the script is causing it to be completed before certain parts of the code.gs complete. I'm really new to using GAS as a deployed webapp, so any/all help is greatly appreciated. Thanks!
Here's the preformatted link (with the included arguments) I'm trying to use. The sheet is publicly viewable with a link:
https://script.google.com/a/macros/edmonton.ca/s/AKfycbxMbCG3p-zdoJReIS6jRHnLK3J-XsI1Zm_BFvfz_UQ/dev?spreadsheetId=1CKQTQYXgt3YgnUXu0YHFeMcG5sMh99sj293oKRFVp4M&sheetTabName=Sheet1&sheetRange=A1%3AD20
Visualization in a Web App
I expanded on the linked question in a blog post a while back, with a dashboard example as a web app. (The code for the dashboard is in the blog, I won't bother repeating it here.)
Logger usage
Comments you've left in your code imply that the conclusions you're making about what-has-run-when is based on whether or not logs have shown up. If only it was that easy!
Unfortunately, the Logger is an unreliable tool when used for debugging a web app or other asynchronous operations. Surprise! It's the subject of another blog post of mine.
The Logger can be extended by using the BetterLog library and a few simple utility functions, so that you can generate logs from the client side as well as from asynchronous server-side calls.
Why aren't those globals working?
Order of execution isn't the issue - rather it's about how global variables behave between execution instances.
When you've set spreadsheetId in your doGet() function, its content is available to the whole script, but only for the duration of that instance's execution. In the following diagram, I've illustrated the communication between a few of the pieces of your solution. Each asynchronous call to a Google Apps Script function creates a new, independent execution instance of your script. Each instance has its own copy of the script's global variables.
The upshot of this is that the spreadsheetId value you set in doGet() isn't available to getSpreadsheetData() when it is invoked by the google.script.run call in the client-side JavaScript. The variable exists as a symbol only - it isn't always the same piece of computer memory. (It might not even be on the same physical computer.)
If you want to "set" some "global" variables to survive between instances, you can use a persistent storage method such as the Properties Service. In your example, though, you would want to be careful with this; if two users were accessing the Web App at the same time, the last one in would over-write values previously set by the earlier user.
A more appropriate way to handle this would be to explicitly pass the "globals" via the html template. (If you create a new Google Apps Script using the demo "Web App" template, you'll see an example of this.)

How to make per user base logging with hapi js

I am using winston logging framework and logging on basis of log level, but now i am facing difficulties in tracking down bugs. So we decided to make logging on per user basis, and this is where i ran into problem.
What i want to acheive?
log file for every user will be generated on every hour. (We can skip every hour constraint in this thread) and every user has unique identifier 'uid'.
What i have?
I have followed architecture as used here 'https://github.com/agendor/sample-hapi-rest-api'. Some additional lib modules exist too.
Currently i am using winston library (but i can afford to replace this if needed).
Brief introduction of flow
Currently, i have access to request object in handler function only, but i want to log events in DAO, library functions too ( on per user basis). 'Uid' is available to me in handler function in request object as i put uid in request in authentication middleware.
My solution (which is not elegant)
pass request object ( or only uid) to every function and log (using winston) event. Custom transport will determine where (in which file, on basis of uid) to put the log.
Certainly, this is not elegant way as every function must have uid parameter in order to log event, which seems bad.
What i want from you?
A better, elegant approach which is scalable too.
Related post: https://github.com/hapijs/discuss/issues/51
Try taking a look at Continuation-Local Storage:
https://github.com/othiym23/node-continuation-local-storage
Heres a good article on implementing it within express:
https://datahero.com/blog/2014/05/22/node-js-preserving-data-across-async-callbacks/

Use HTML5 localstorage to exchange information

I have a program written in c++ that reads values from this board. Anyways that part is not important. What I have is data that is constantly changing and I will like to graph that data. I was hoping to use a web browser to display the data since there are so many open source graphs and charts out there written in JavaScript. So my problem is to send data to the browser from my c++ program
I already investigated and UDP is not available in browsers yet so I will have to use TCP. TCP websockets are not that fast and I was thinking about using html5 localstorage instead. By that I mean have my c++ program write to the database on localStorage then javascript will wait for the value of that variable to exist and invent some sort of protocol that will make that work. Local storage is really fast for example :
<script type="text/javascript">
var counter = 0;
window.onload = function () {
function Test() {
counter++;
localStorage.p = counter + ""; // perform write
var read = localStorage.p; // perform read
if (read == "5000")
alert((new Date() - now)); // shows 45
else
Test(); // loop again
}
var now = new Date();
Test();
}
</script>
that script takes 54 milliseconds and it reads AND writes 5000 times! That means that instead of creating a plug-in for the browser next time I will just implement some sort of protocol that will enable me to exchange information using the localStorage. For example I could have the browser waiting for the variable x to exist. Once it exist I then creates a variable y by the browser notifying the c++ program that it is ready to receive data and so on. localStorage is just a sqlite database located on C:\Users[USER]\AppData\Local\Google\Chrome\User Data\Default\Local Storage
I haven't seen anyone online that uses this approach. Maybe it is too dangerous and Sqlite cannot handle multiple threads that good and I will be wasting time creating this program.
So should I start implementing this protocol? Should I use websockets? Or should I give it a try to https://stackoverflow.com/a/10219977/637142 ?
I would go with node.js as middleware from your C++ to the browser, instead of using directly websocket (been there done that) go with http://socket.io/ that will make your life much easier :)

Categories

Resources