trojan-horse

0.2.0 • Public • Published

trojan-horse

Execute nodejs through the browser (what could possibly go wrong)

WARNING

If used improperly this module can give access to every sort of malicious code. It is possible to reboot, shutdown, format an entire disk or who knows what else. Use at your own risk and read about nounces to improve security.

WUT?

Using trojanHorse as express middle layer or any generic node req, res handler gives the browser the ability to execute JavaScript code remotely on the server.

// nodejs exammple
var trojanHorse = require('./trojan-horse');
require("http")
  .createServer(function (request,  response) {
    // in case this is a trojan-horse request GTFO
    if (trojanHorse(request,  response)) return;
    // in every other case we can simply do
    // whatever we usually do with requests
  })
  .listen(1337)
;
 
// express
var trojanHorse = require('./trojan-horse');
app.use('/.trojan-horse.js', trojanHorse);
app.use('/.trojan-horse', trojanHorse);

On the client side, the minimum amount of required code would look like the following:

<!doctype html>
<script src="/.trojan-horse.js">/* grab the constructor */</script> 
<script>
var th = new TrojanHorse();
th.exec(function () {
  console.log('Hello from the client');
  resolve();
});
</script> 

Localhost Security

If you make your service reachable through localhost only, using 127.0.0.1 as IP address, your computer should be the only one capable of reaching such page. In this case there's no need to play too much with nounces.

Allowing execution via nonces

If the server is not reachable through localhost only or it cannot trust the environment, it is really not recommended to accept any sort of function execution in the wild.

In order to allow only well known functions, it is possible to define one or more nonces which are a sha256 representation of cleaned up functions.

var trojanHorse = require('./trojan-horse');
 
// to create a named nonce ... 
trojanHorse.createNonce('cpus', function () {
  // will return cpus info
  resolve(require('os').cpus());
});
 
// 'cpus:c501c5c77cb24c0d9d7a05e94e9dc9254650afee8c249f7aa283e1061c62846b'
 

Since security is a major concern here, nonces can be defined only once per application lifetime, meaning that all privileged functions must be known upfront or trojan-horse will throw an error.

// main appication  file
var trojanHorse = require('./trojan-horse');
// define one or more nonces here once per appllication
trojanHorse.nonces = [
  'cpus:c501c5c77cb24c0d9d7a05e94e9dc9254650afee8c249f7aa283e1061c62846b',
  // eventually other nonces too ...
];
 
// rest of the app
require('http').createServer ...

HOW

The entire logic is based on Promise, AJAX, and normalized function decompilation. There is no way an executed function can access the client-side outer scope: it will be sent as string and evaluated through the nodejs vm module in a stateless way, or in a specific context.

// client side JS, executed from the browser
// trojan with persistent global context
 
(new TrojanHorse).createEnv().then(function (th) {
  // each exec will run in the same sandbox
  th.exec(function () {
    if (!global.i) i = 0;
    resolve(++i);
  }).then(function (i) {
    alert('now it is ' + i);
    th.exec(function () {
      resolve(++i);
    }).then(function (i) {
      alert('and now it is ' + i);
    });
  });
});

Every time a function is executed on the server it will have access to a resolve and a reject callback. Once executed, these will terminate the request and eventually send the result (or the error).

Every returned variable must be JSON compatible, and it is also possible to send to the server arbitrary arguments that must be compatible with JSON too.

// execute sending arguments
th.exec([1, 2, 3], function (one,  two, three) {
  resolve(one + two + three);
});

Examples and Demos

The base.js files contain the most basic playground while test.js and test.html contain a nonces based example. Change one of those two functions to see them failing.

MIT License

Copyright (C) 2015 by Andrea Giammarchi - @WebReflection

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

Package Sidebar

Install

npm i trojan-horse

Weekly Downloads

12

Version

0.2.0

License

MIT

Last publish

Collaborators

  • webreflection