Let's assume I have a casual user who can log in to the system via SSH into a bash shell. I also have a PHP (though the language is irrelevant here) script that acts as a process accepting various commands and other user input and acts according to them (essentially a 'shell-like' script).

Now, what I want to do is to lock the user inside said PHP script, ie. run it as soon as the user logs in (this part is simple via .bashrc) but at the same time ensure that when the script execution ends, the user is also automatically 'kicked out' of bash and consequently the ssh session, so that he cannot do anything via bash itself and stays limited to what the PHP script offers.

Is that even possible? If yes, how would I go about doing it?

Update: Based on the answers so far - having bash inbetween my script and the user logging in via SSH is no requirement whatsoever. It just seemed like a necessity to me at first. Anything that forces the user into my script only directly after a SSH login is a welcome answer.

  • How much power are you giving users? I think you are going to have a very difficult time trying to secure this from every possible attack. – sparticvs Nov 6 '12 at 19:59
  • To put it into a less abstract light - let's assume the script is called "app", and has a set of subcommands like "status" (which shows stuff like memory usage etc.), "update" (performs a 'git pull' inside a predefined directory) and so on. Essentially the user is limited to what and how input will be parsed by the script and nothing more. The input is at no point eval()'d and always treated as strings, so it boils down to casual PHP security concerns as long as the user remains inside the script. – alkor Nov 6 '12 at 20:14

Following the updated information, you should have them do private/public key pairs and inside the .ssh/authorized_keys file set it to only run script.php file. You shouldn't rely on the .bashrc for protection, especially since that is needed to initialize the environment.

  • Using 'command' in there does indeed seem like a good solution (another one I haven't thought about...). I'll give it a try and see if I run into any issues. I haven't ever used it though - I'm assuming the difference would be that using this would completely circumvent bash and run my script (or whatever the command may be) directly after login? – alkor Nov 6 '12 at 20:55
  • 1
    Tested it and it works like a charm. And it's also flexible as it allows me to easily pass different parameters to the script depending on which key is used to log in. To expand on the answer, said line(s) in authorized_keys might begin like this command="/usr/bin/php /some/path/script.php --user someone" ssh-rsa AAAAB3NzaC... – alkor Nov 6 '12 at 22:54
  • A good answer. I might alter my script solution to something simmilar to yours to see this working instead of change the user's shell :) – user34720 May 10 '14 at 18:06

You can change shell for the user in question to whatever you like in the last field on the appropriate line in /etc/passwd, e.g.:


if you include appropriate hash-bang (e.g. #!/usr/bin/php on the first line of the script) it should work right away. For security reasons I would recommend not to put the script into a directory writeable by the user.

  • This was the first thing that came to my mind before I even considered asking this question. However, with this approach it does essentially hang on SSH login. Quite frankly I don't understand the internals, but I'm assuming it's understandable considering the script is not a full-fledged login shell so it has no way to deal with logins, especially since I'm using pub/priv keys. – alkor Nov 6 '12 at 21:55
  • 1
    Depending on how your pam and ssh are configured, the script you're specifying as a login shell probably has to be listed in /etc/shells (via its full path). What does ssh say if you try to login verbosely? (Also, I've done this in the past by specifying the script in .ssh/authorized_keys, as @sparticvs says in another answer, rather than in /etc/passwd. I expect you should be able to get the latter method to work too, though.) – dubiousjim Nov 6 '12 at 22:24
  • My apologies, the answer is indeed also functional, even without specifying the shell in /etc/shells in my case. I was getting a 'server refused our key' message, but a quick look into the auth log told me that the script is 'simply' not executable. Another stupid mistake, just because I'd normally run it through the interpreter directly, not using a shebang. However, I do prefer @sparticvs 's way for the reasons mentioned in the comments. In any case - thank you, this helped me better understand the login internals. – alkor Nov 6 '12 at 23:20

The simplest way would be to put sth like this into .bashrc

php script.php

After execution of script.php shell will exit session.

But it's hard to say what you exactly need to do and how security level you need.

  • 1
    This answer made me feel stupid but it does indeed solve the problem, so thank you! :) Security, other than generic system security, is of lesser (to avoid saying "none at all") concern as I stated in a comment above. Essentially the user cannot do anything apart from what the script itself allows and I wanted to leave the script as much flexibility as possible (thus no jailkits) and enforce any restrictions on PHP's level. – alkor Nov 6 '12 at 20:33
  • Better would be to put just exec php script.php in your .bashrc. Then the bash process will be replaced entirely, rather than sitting around taking up resources while the php script runs. – Jim Paris Nov 6 '12 at 20:55
  • 1
    Tested both now. One issue I found with the approach in the answer is that I had to explicitly trap sigint, ie. trap "exit" 2 php script.php exit ... otherwise ^C would put me back in bash (and obviously I can't handle the signal inside the script to exit something outside its scope). There is no such issue with @JimParis 's code so that would be a better choice, also considering the mentioned resource usage. – alkor Nov 6 '12 at 22:10
  • @alkor - As I said it was the simplest thing that comes to my mind :) About ^C - after exiting program in this way shell will run next command, so it will exit properly no matter how 'php script.php' finishes. Am I wrong about it? – Mateusz W Nov 7 '12 at 10:08
  • @MateuszW - Well, yeah, it would exit the session properly if the script finished on its own (regardless of the exit code) and it also works for ^D (EOF). Sigint interrupts the processing chain completely, however, so exit never gets called. – alkor Nov 7 '12 at 13:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.