Jan 29

Limited Shell (lshell)

Tags:, , , , Ignace Mouzannar (-ghantoos-) @ 12:35 pm

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:
* use the install.sh script that will guide you through the install:
- copying files
- creating user to use lshell as main shell
- changing main shell of user
- listing current users using lshell as main shell

* Follow the instructions below:
Extract the files in the wanted directory (tar xvfz lshell.tar.gz)
Included files:
* lshell.py
* lshell.conf
* COPYING
* README
* CHANGES

lshell.py must be executable:

$> chmod +x lshell.py

2- Configuration:

lshell.conf presents a template configuration file. Fields to fill by user are:
* allowed: a list a the allowed commands
* forbidden: a list of forbidden character or commands
* warning_counter: number of warnings when user enters a forbidden value before getting exited from lshell.
* timer: a value in seconds for the session timer
* passwd: password of specific user
* path: list of path to restrict the user geographicaly
* home_path: set the home folder of your user. If not specified, the home directory is set to /home/username
* env_path: update the environment variable $PATH of the user (optional)
* scp: 1 or 0 to allow of forbid the use of scp on a user’s account

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:
1- Untar the lshell tar.gz in /usr/local/lshell/

$> cd /usr/local/
$> tar xvfz lshell-xxxxxxxx.tar.gz

2- Save the lshell configuration file in: /etc/lshell.conf
3- then, vi/etc/passwd and put as the following
(example with user ghantoos):

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

9 Responses to “Limited Shell (lshell)”

  1. zeridon says:

    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.

  2. linux454 says:

    Also recall that vi is not a safe command to allow, as it allows shell escapes.

  3. Ignace Mouzannar (-ghantoos-) says:

    linux454 says: Also recall that vi is not a safe command to allow, as it allows shell escapes.

    True. I had just put it as an example. It has been corrected. : )
    Cheers, Ghantoos

  4. Valery says:

    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.

  5. Ignace Mouzannar (-ghantoos-) says:


    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.

    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

  6. Jonathan Patschke says:

    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.

  7. Ignace Mouzannar (-ghantoos-) says:

    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). (…) 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.

    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

  8. youdah says:

    well, now read something about ssh and then rewrite your code so that it really works :)))

  9. Ignace Mouzannar (-ghantoos-) says:

    well, now read something about ssh and then rewrite your code so that it really works :)))

    Thank you youdah (or zdenda..) for this very useful comment. : )

    Cheers,
    Ghantoos

Leave a Reply