Skip to content

Instantly share code, notes, and snippets.

@boggle
Created February 10, 2011 12:02
Show Gist options
  • Save boggle/820416 to your computer and use it in GitHub Desktop.
Save boggle/820416 to your computer and use it in GitHub Desktop.
Forays into chowning with sys.exec from node.js; no authentication
var express = require('express');
var app = express.createServer();
var process = require('child_process');
// Simple server configuration variables
var execDir = "/tmp";
var bufCap = 32768;
// Supported commandos
var commandos = {
chown: function chown(req, res) {
var opts = {
cwd: execDir,
env: process.env,
setsid: false,
customFds: [-1,-1,-1]
};
var proc = process.spawn("/tmp/chown", req.body, opts);
execProc(proc, bufCap, res);
}
};
// Set-up application server
app.configure(function() {
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
app.use(express.bodyDecoder());
app.use(express.cookieDecoder());
app.use(express.methodOverride());
app.use(express.session({ secret: 'roger_wilco' }));
app.use(app.router);
app.use(express.logger({ format: ':method :uri'}));
});
// Set-up request routing
app.post('/commandos/:cmd', verifyReq(function(req, res) {
commandos[req.params.cmd](req, res);
}));
// Run server
app.listen(3000, 'localhost');
// Utility functions
// Wrap request handling function cont such that it fails
// unless the req header contains 'Content-Type: application/json'
function verifyReq(cont) {
return function(req, res) {
if (! req.is('application/json')) {
res.header('Content-Type', 'text/plain');
res.send("application/json required", 400);
}
else {
cont(req, res);
}
};
}
// Execute process proc with closed stdin, stderr redirected to stdout
// and stdout drained to a buffer of capacity bytes. After proc
// finishes, writes result to http res using 200 if exit code of proc = 0,
// 500 otherwise.
function execProc(proc, capacity, res) {
var buffer = new Buffer(capacity);
var offset = 0;
var overflow = false;
proc.stdin.end();
proc.stderr.pipe(proc.stdout);
proc.stdout.on('data', function(data) {
data.copy(buffer, offset);
offset = offset + data.length;
if (offset >= capacity) {
offset = 0;
overflow = true;
}
});
proc.on('exit', function(code) {
var retCode = 200;
if (code != 0) retCode = 500;
if (overflow) {
res.send("buffer overflow", 500);
}
else {
res.send(buffer.slice(0, offset), retCode);
}
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment