How to have access to a shell without ssh or telnet using jQuery terminal

If you have, like I do, a virtual server on hosting service, that support cgi but don’t have access to a shell and php have passthru disabled you still can have access to a shell, even if you can’t install anything on that machine – like anyterm.

There is this project, which I did, called jQuery terminal, that emulate a Unix terminal. All you need is interpreter that will execute shell commands.

Lots of hosting services disable php passthru but leave cgi script, so if you have them you can create simple shell like this one:

UPDATE: If you don’t want to code it yourself (or look at working solution), you can check my project LEASH – Browser Shell.

#!/bin/bash
echo -en "Content-Type: text/plain\r\n\r\n"
query=$(/usr/bin/python -c "import urllib; print urllib.unquote_plus('$QUERY_STRING')")
eval $query 2>&1

I use python subprocess to decode QUERY_STRING. Probably it can be done using some Unix tools.

On my server I use Python CGI script like this one:.

#!/usr/bin/python
import cgi
import subprocess as sub

try:
    from json import dumps as json_serialize
except ImportError:
    def json_serialize(obj):
        result = ''
        t = type(obj)
        if t == types.StringType:
            result += '"%s"' % obj.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n')
        elif t == types.NoneType:
            result += 'null'
        elif t == types.IntType or t == types.FloatType:
            result += str(obj)
        elif t == types.LongType:
            result += str(int(obj))
        elif t == types.TupleType:
            result += '[' + ','.join(map(json_serialize, list(obj))) + ']'
        elif t == types.ListType:
            result += '[' + ','.join(map(json_serialize, obj)) + ']'
        elif t == types.DictType:
            array = ['"%s":%s' % (k,json_serialize(v)) for k,v in obj.iteritems()]
            result += '{' + ','.join(array) + '}'
        else:
            result += '"unknown type - ' + type(obj).__name__ + '"'
        return result

class Singleton(object):
    __single = None
    def __init__(self):
        Singleton.__single = self

    def __new__(cls):
        if Singleton.__single:
            return Singleton.__single
        else:
            return super(Singleton, cls).__new__(cls)


class Form(Singleton):
    def __init__(self):
        super(Form)
        self.form = cgi.FieldStorage()

    def __getitem__(self, name):
        return self.form.getvalue(name)

def execv(command, path):
    command = 'cd %s && %s && pwd 1>&2' % (path, command)
    proc = sub.Popen(['/bin/bash', '-c', command],
                     stdout=sub.PIPE, stderr=sub.PIPE)
    stderr = proc.stderr.read()[:-1]
    stdout = proc.stdout.read()[:-1]
    if not os.path.exists(stderr):
        raise Exception(stdout, stderr)
    return {
        "cwd": stderr,
        "stdout": re.sub('.\x08', '', stdout)
    }

if __name__ == '__main__':
    print "Content-Type: text/plain"
    print
    form = Form()
    if token() == form['token']:
        response = {}
        try:
            response['result'] = execv(form['command'], form['path'])
        except Exception, e:
            response['error'] = e.args[1]
            response['result'] = {'stdout': e.args[0], 'cwd': form['path']}
        else:
            response['error'] = None
    else:
        response = {'error': 'You are not authorized', 'result': None}
    stdout.write(json_serialize(response))

You have enabled passthru in php you can write your shell in php.

Now when you have access to a shell you need to setup interface using jQuery terminal.

<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>Shell</title>
    <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
    <script src="terminal/js/jquery.mousewheel-min.js"></script>
    <script src="terminal/js/jquery.terminal.js"></script>
    <link href="terminal/css/jquery.terminal.css" rel="stylesheet"/>
    <style>
    .terminal a.ui-slider-handle:focus { outline: none; }
    body { margin: 0; padding: 0; }
    html { background-color: #000; }
    .clear { clear: both; }
    /* This works only in Safari and Google Chrome */
    @media screen and (-webkit-min-device-pixel-ratio:0) {
        .terminal, .terminal .terminal-output, .terminal .terminal-output div,
        .terminal .terminal-output div div, .cmd, .terminal .cmd span, .terminal .cmd div {
            font-weight: bold;
        }
    }
    </style>
<script>
$(function() {
    var pwd, last_dir, home_dir;
    var terminal = $('#shell').terminal(function(command, term) {
        if (command.replace(/^ *(.*) *$/, '$1') == '-') {
            pwd = last_dir;
            return;
        }
        term.pause();
        $.post("/cgi-bin/cmd.py", {
            token: term.token(),
            command: command.replace(/(\\)?~/, function($0,$1) {
                return $1 ? $0 : home_dir;
            }),
            path: pwd
        }, function(response) {
            term.echo(response.result.stdout);
            pwd = response.result.cwd;
            term.resume();
        });
    }, {
        login: function(user, password, authenticate) {
            $.post("/cgi-bin/cmd.py", {
                user: user,
                password: password
            }, function(token) {
                if (token) {
                    home_dir = pwd = last_dir = '/home/ + user;
                }
                authenticate(token);
            });
        },
        prompt: function(callback) {
            var username = terminal.login_name();
            var re = new RegExp("^" + '/home/' + username);
            var username = '[[;#44D544;]' + username + ']';
            var path = '[[;#5555FF;]' + pwd.replace(re, '~') + ']';
            callback(username + '[[;#989898;]:]' + path + '[[;#989898;]$] ');
        },
        name: 'shell'
    }).css({
        overflow: 'auto'
    });

    $(window).resize(function() {
       terminal.css('height', $(window).height()-20);
    }).resize();

});
</script>
</head>
<body>
  <div id="shell"></div>
</body>
</html>
About these ads

, ,

  1. How to have access to a shell without ssh or telnet using jQuery terminal | Jakub Jankiewicz – jcubic | SetZero

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: