Jan 29
Limited Shell (lshell)
Limited Shell (lshell): python to rescue my SSH needs
As I wondering how I could do to relieve my wrt54gl from the huge weight of libopenssl and nsupdate, I thought.. Wouldn’t it be cool if I could set a very restricted account on my server, and just ask my wrt54gl to ssh to it and execute locally nsupdate. So I started searching for a way to restrict user ssh accounts by listing a set a allowed commands. No luck there.
So.. python came to the rescue.
I developed this small python script so I could finally create ssh user accounts and restrict them to the commands and environment I wanted. Which is quite cool..: )
You can find an up-to-date version of lshell at this address: http://sourceforge.net/projects/lshell/
Here’s a little overview of it.
1- Installation:
You can download the current version of lshell from the following link: http://sourceforge.net/project/showfiles.php?group_id=215792
You have 2 options:
lshell.py must be executable:
$> chmod +x lshell.py
2- Configuration:
lshell.conf presents a template configuration file. Fields to fill by user are:
3- Usage:
To launch the Limited Shell, just execute lshell.py specifying the location of your configuration file:
$> cd /path/to/lshell $> ./lshell.py /path/to/configuration/file
By default lshell will try to launch using lshell.conf in the same directory unless specified otherwise.
4- Use case 1: OpenSSH & authorized_keys
The primary goal of lshell, was to be able to create shell accounts with ssh access and restrict their environment to a couple a needed commands.
For example User ‘bla’ who #_only_# needs to use ls, pwd, rvim (restricted vi) and dig websites from my server.
His ‘allowed’ variable in the configuration file will look like: ['ls', 'pwd', 'dig','rvim'].
In this case, my configuration file will look something like this:
# START [bla] passwd : blabla allowed : ['ls', 'pwd', 'dig','rvim'] forbidden : [';', '&', '|'] warning_counter : 2 timer : 0 path : ['/home/bla', '/usr/bla'] home_path : ‘/home/bla/’ env_path : ‘:/usr/bla:/usr/bli’ scp : 1 # or 0 # END
In order to launch lshell limited to the ’ssh’ command, I used ssh’s authorized_keys:
$> vi /home/bla/.ssh/authorized_keys
and add :
command="/path/to/lshell.py /path/to/lshell.conf",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
just before the “ssh-dss blablablabla” part.
This will have the effect of executing lshell upon user’s connection.
The great thing about it, is that when the user exist lshell, the ssh session is automatically ended! : )
Your authorized_keys should look something like this:
no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command= "/path/to/lshell.py /path/to/lshell.conf" ssh-dss AAAAHadWj4caz5T AA6Xgonf2FjpmpgpquvN+6cQsGTEOwm6R+oEaFBU1VyfuwlEklqn3TWnWzACBAKNJ cJFr6pJsECEz5LZFtGu7b4tYNu8/vne11SjZBrOqm7WuQiWpOguzyldk6IJSnIKrn WoT/fGgXeED2UingA65bKIvOh0B3NzaC1kc3McsrBEDjQ3NAAAAFQDP6OHwkLNSA1 PyKqIMzqiCpAmJE7gRgFu8Pxc7i1TZvmiXSCjdXRaXZNncxPj6eOUng4QFDAoZc6n N8iUYCwKJ2pl2ryMqC/hnBVL5SRne+FqcRKbzWXkh7NI6KtJ4XxI32NI/OIpZAo2e G/8rdCgShZflCbpFZL865fKmUH2pefSZwl/12VXWDqQmukNp6+XrA3LPXdElIeQAA ACAHoQ3GpC4/BcxuHj1TBNg7Hw3KxZMeL1vQNVF2+cfJ22U1hERNBcRuUjqe5Gv9Q GoCMcsNpG8/FtV5Pnoq8nPPWuUkrBeBxY6KSgzaZ/DTSd+WvPOwNonntRkEwxpSdk lSqXpmqNlw2fPodg6QAAAIEVdZiSZZ9EoH+4MJjKDSvE= bla@somewhere.somet hing
Now, when “sshing” to your machine, with the bla user, he will be forced to lshell! And when quitting lshell, the ssh session is automatically ended! : )
Here is what will happen when user ‘bla’ is going to SSH to your server:
ghantoos@machine1:~$ ssh bla@machine2 Enter passphrase for key '/home/bla/.ssh/id_dsa': <– enter your SSH passphrase here Enter bla’s password : <– enter your lshell password here —————— Welcome to lshell! —————— Type ‘?’ or ‘help’ to get the list of allowed commands bla:-$ ? or hit [tab][tab] EOF dig help ls pwd quit rvim bla:-$ ls test_file bla:-$ pwd /home/dns bla:-$ quit Exiting.. Connection to machine2 closed. ghantoos@machine1:~$
5- Use case 2: /etc/passwd
In order to configure a user account to use lshell by default, you
can force the its shell to be lshell by specifying it in /etc/passwd.
In this case, you must:
$> cd /usr/local/ $> tar xvfz lshell-xxxxxxxx.tar.gz
ghantoos:x:1001:1001:ghantoos,,,:/home/ghantoos:/usr/local/lshell/lshell.py
After this, whichever method is used by the user to log into his account,
he will end up using the limited shell you configured for him!
6- Contact & contribution
If you want to contribute to this project, please do not hesitate.
Limited Shell (lshell) is licensed under GNU General Public License (GPL)
Send me a patch, or just your new lshell.py so I can check it out.
You can use the interface on sourceforge.net:
http://sourceforge.net/projects/lshell/
Cheers,
Ghantoos

January 29th, 2008 at 3:14 pm
i’ve accomplished similar feat for the sake of archiving my site using authprogs.pl from hackinglinuxexposed
you can check it at: http://www.getoto.net/2007/11/backup-with-rsnapshot-and-ssh/lang/en/
Frankly said python is a bit heavier than perl so … i prefer perl.
January 29th, 2008 at 3:42 pm
Also recall that vi is not a safe command to allow, as it allows shell escapes.
January 29th, 2008 at 4:01 pm
True. I had just put it as an example. It has been corrected. : )
Cheers, Ghantoos
January 31st, 2008 at 12:44 pm
telnet allows shell escape too. Some (long) time ago I wrote noexec project (http://noexec.sf.net) to prevent shell escape (or actually any program execution) in cases like lshells. (noexec use LD_PRELOAD to turn any exec* to NOP).
By the way, noexec idea was integrated in sudo. So fill free to use it to :)
Valery.
January 31st, 2008 at 12:55 pm
Great stuff! Thank you Valery for your suggestion! : )
It took a look at http://noexec.sf.net. I will definitely try to use it with lshell!
Cheers!
Ghantoos
February 1st, 2008 at 10:28 am
Almost all Bourne-family shells (modern sh, ksh, jsh, bash) support a “restricted mode” that has functionality like this built-in (read the man page). Execution of programs via absolute paths is prohibited, and the user is unable to redefine the PATH variable. Set PATH appropriately (and activate restricted mode) in the user’s profile, deny editing of the profile, and symlink the programs you want available to something in the user’s PATH, and you’re done: no perl or python necessary. If you set ENV (or use .bashrc for bash) to a script that reactivates the restrictions, even shell escapes (via system(3), not exec(2)) from vi and telnet are handled.
February 1st, 2008 at 10:38 am
Sorry Jonathan, but I have read the man pages you talked about.
And sincerely, I prefer having one and *only* configuration file for all my ssh users, rather than creating folders with symlinks for each different user.
I feel it’s clearer and cleaner. : )
Python had my solution.
Nevertheless, thanks for the tip using .bashrc to activate restrictions on shell escapes.
Cheers,
Ghantoos
February 8th, 2008 at 7:05 pm
well, now read something about ssh and then rewrite your code so that it really works :)))
February 11th, 2008 at 8:56 pm
Thank you youdah (or zdenda..) for this very useful comment. : )
Cheers,
Ghantoos