Reputation: 190
I'm trying to code a live console/terminal. For that I am using phpseclib library, at first I include all stuff & login:
use phpseclib\Net\SSH2;
include('vendor/autoload.php');
$ssh = new SSH2('127.0.0.1');
if(!$ssh->login('user', 'pass')) {
exit('Login Failed');
}
$ssh->setTimeout(1);
after that I check for an Ajax request (read for display, write for execute):
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
if($_POST['request'] == 'read') {
echo $ssh->read();
} elseif($_POST['request'] == 'write') {
$ssh->write($_POST['command']."\n");
echo $ssh->read();
}
exit();
}
HTML markup:
<textarea readonly>...</textarea>
<div>
<input type="text" placeholder="Command">
<button>
Do it
</button>
</div>
Some jQuery:
$('div button').click(function(e) {
$('div button').text('Loading...');
e.preventDefault();
$.ajax({
type: 'POST',
url: 'index.php',
data: {
request: 'write',
command: $('div input').val()
},
success: function(data) {
$('textarea').append(data);
$('textarea').scrollTop($('textarea')[0].scrollHeight - $('textarea').height());
$('div input').val('');
$('div button').text('Do it');
}
});
});
The Problem(s) every time I request cmd with write() it will show the Debian login message (and if I change the current directory using cd and after that I use ls it resets - because the new login I think), also im not sure how to create an interval so I get the current output continually - e.x. if I ping a website. Tried smth. like this:
setInterval(function() {
$.ajax({
type: 'POST',
url: 'index.php',
data: {
request: 'read'
},
success: function(data) {
$('textarea').append(data);
$('textarea').scrollTop($('textarea')[0].scrollHeight - $('textarea').height());
}
});
}, 300);
Im thankful for any help!
Upvotes: 2
Views: 1158
Reputation: 2187
I was able to do this but without SSH lib. You should be able to take this answer and work it into your existing code.
Yes, the reason why you keep seeing the login, and why the directory changes do not persist is because you are reconnecting and creating a new session each time. Additionally, since PHP removes all resources (your SSH connection) on exit, you cannot make it persist by serialization or anything.
Basically, what you need is a bash session that stays up that you can interact with, using PHP. You can do this with netcat
and a fifo
and some PHP system()
calls.
screen
(this is so the netcat
command keeps running even after you logout)Run the following (persistently listens to port 1234 on localhost, writes to fifo, and cat's the fifo contents into a shell).
rm /tmp/f
mkfifo /tmp/f
cat /tmp/f | /bin/sh -i 2>&1 | nc -k -l 127.0.0.1 1234 > /tmp/f
Use CTRL+A+D to detach from the screen
session (or make another SSH connection while leaving the above command running)
Create the following PHP script and make it executable (chmod +x
)
#!/usr/bin/php
<?php
$com = $argv[1];
$junk = system('(echo "'.$com.'") | nc localhost 1234');
$data = system('(echo "") | nc localhost 1234');
echo $data
?>
So, we echo
the command you want to run into netcat
(nc), which connects it to the other persistent netcat
running a shell, the output of the command is written to the fifo
but not before the current contents of the fifo
is read write to the $junk
variable. Next we echo ""
and pipe that to netcat
, which again is sent to the other netcat
which writes "" to our fifo, only this time when the fifo
is read it contains the result of the previous command we ran. Neat, huh?
root@zim:/tmp# ./run_command.php "mkdir /tmp/stackoverflow"
$ $ $ $root@zim:/tmp# ./run_command.php "cd /tmp/stackoverflow"
$ $ $root@zim:/tmp# ./run_command.php "ls -al"
total 8
drwxrwxr-x 2 ttucker ttucker 4096 May 22 07:38 .
drwxrwxrwt 11 root root 4096 May 22 07:39 ..
$ $ $ $root@zim:/tmp# ./run_command.php "touch a b c d"
$ $ $ $root@zim:/tmp# ./run_command.php "ls -l"
total 0
-rw-rw-r-- 1 ttucker ttucker 0 May 22 07:39 a
-rw-rw-r-- 1 ttucker ttucker 0 May 22 07:39 b
-rw-rw-r-- 1 ttucker ttucker 0 May 22 07:39 c
-rw-rw-r-- 1 ttucker ttucker 0 May 22 07:39 d
$ $ $ $root@zim:/tmp# ./run_command.php "mkdir subdir"
$ $ $ $root@zim:/tmp# ./run_command.php "cd subdir"
$ $ $root@zim:/tmp# ./run_command.php "ls -al"
total 8
drwxrwxr-x 2 ttucker ttucker 4096 May 22 07:40 .
drwxrwxr-x 3 ttucker ttucker 4096 May 22 07:40 ..
$ $ $ $root@zim:/tmp# ./run_command.php "touch q w e r t y"
$ $ $ $root@zim:/tmp# ./run_command.php "ls -al"
total 8
drwxrwxr-x 2 ttucker ttucker 4096 May 22 07:40 .
drwxrwxr-x 3 ttucker ttucker 4096 May 22 07:40 ..
-rw-rw-r-- 1 ttucker ttucker 0 May 22 07:40 e
-rw-rw-r-- 1 ttucker ttucker 0 May 22 07:40 q
-rw-rw-r-- 1 ttucker ttucker 0 May 22 07:40 r
-rw-rw-r-- 1 ttucker ttucker 0 May 22 07:40 t
-rw-rw-r-- 1 ttucker ttucker 0 May 22 07:40 w
-rw-rw-r-- 1 ttucker ttucker 0 May 22 07:40 y
$ $ $ $
It does seem to return $
a couple of times when running commands. This is because it still returns the $
for the shell after a command completes. I think you could easily scrub this out though...
Upvotes: 2