37

Consider the following line from /etc/passwd:

sadeq:x:1000:1000:Mohammad Sadeq Dousti,,,:/home/sadeq:/bin/custom-script.sh

The last part, /bin/custom-script.sh, shows the command/script to be run when the user logs in to the system. Currently, it's a simple Bash script, which presents the user with menu, effectively limiting the possible commands he can execute.

Or, I hope so! Maybe there's a way the users can bypass custom-script.sh, and access Bash directly. Then, they can execute any command within their user context.

Is there a way to bypass the above Bash script, and execute other commands?

Edit: Consider the following simple case as custom-script.sh:

#!/bin/bash
echo What is your name?
read name
echo Hi $name
M.S. Dousti
  • 1,514
  • 17
  • 23
  • 1
    First I would try to check, maybe there is some way to overwrite `.bashrc` or `.bash_profile`. Either by escaping tricks, or by some environment variable trick. Second, I would check, maybe there is some way to inject environment variables. But probably none of them would work, your script is too simple for that. Btw, an `echo "Hi $name"` would look much better in the last line! – peterh Aug 21 '18 at 16:00
  • @peterh: Using double quotes as per your suggestion seems to prevent the problem mentioned by Dmitry Grigoryev in his answer below. Thanks! – M.S. Dousti Aug 22 '18 at 20:42

5 Answers5

46

Assume there is a (probably unintentional) backdoor.

The default /etc/passwd on Sun workstations of the early 1990s included an entry something like this:

games::0:0:games:/nopath:/bin/false

In other words, an account named 'games' with no password. Apparently the genius who came up with this idea had no imagination, and assigned it a uid and gid of zero (i.e. root and wheel). Generally, that was okay, as the home directory was meaningless and the shell was set to a program that always exited with failure. Furthermore, the default settings for any access by network -- telnet, rlogin, rcp, ftp -- were set to prevent access by any uid of zero. There was a separate passwd entry for root, with a properly-set set password, home directory, and shell.

This meant if you tried to log in as games, the following would happen:

  • Logging in as games at the console would at first succeed, but then spawn the /bin/false shell, which would immediately exit.
  • Using telnet or rlogin would outright deny the login. Even if it had succeeded, the /bin/false shell would immediately quit.
  • FTP and scp don't use shells, but they were configured to deny access to uid zero, so you couldn't log in this way.
  • A GUI login would start up the default GUI services, including a window manager, clock client, and a terminal. The latter would immediately exit because its child shell would immediately exit. So you would get an empty screen except for a clock. (More on this below...)
  • If you really had to log in as root, you would either have to do that from the console, or first rlogin/telnet as another user on that machine and then su root. Either way uses the root passwd entry rather than the games passwd entry, and thus works they way root should work.

So the games account appeared to always fail, unless you did a GUI login. In that case, the only thing that appeared was the clock. However, you could right-click on the background to get a root menu, with a factory-provided list of programs that users would normally customize for themselves. (Customizing the menu didn't work for the games account; I don't remember exactly why.) You could try to bring up more terminal windows, which would all fail. There was a puzzle game (which may have been the impetus for the account in the first place). Another choice was to log out. And then there was the graphical debugging tool, dbxtool.

dbxtool was a graphical frontend to the dbx symbolic debugger, similar to today's gdb. Being uid zero, you could attach to and control any process on the system, although this was not useful because programs provided by Sun were compiled without symbols. You could launch a shell, but this would use your SHELL environment variable, which was /bin/false. However, you could also change environmental variables! This meant you could get a root shell by the following:

  1. Log in via the GUI as games, without password.
  2. Right-click to bring up the root menu.
  3. Start a dbxtool.
  4. setenv SHELL /bin/sh
  5. (Optional) setenv HOME /
  6. Start a shell with !
  7. Because the terminal is not set, do stty sane

Voila, root shell without password!

So, do not assume that a user can't escape out of an invalid shell.

DrSheldon
  • 561
  • 1
  • 6
  • 11
  • 3
    Very interesting writeup! But what about a _valid login shell_? – ThoriumBR Aug 21 '18 at 15:32
  • 3
    @ThoriumBR: Any program capable of an `execve` call with user-supplied parameters should be considered suspect. This includes shells, scripting languages, the user-customisable root menu mentioned in the answer, and anything with a "shell escape" (such as `more` or `vi`). – DrSheldon Aug 21 '18 at 15:54
  • *Any program capable of an `execve` call with user-supplied parameters* Which includes login scripts that source user-controlled files such as but not limited to `.bashrc`. – Andrew Henle Aug 22 '18 at 13:55
  • Something's very odd. This is in the current books as how to disable a login (change shell to /bin/false) because of things like ssh keys. Anyway, on trying something similar on a more modern GUI, I discovered that it runs your shell at X login time and if your shell isn't a real shell you get logged out really quickly. I think what happens is the login spawns the GUI environment by `shell -lc guienvprogram`. – Joshua Aug 22 '18 at 21:33
  • @Joshua: Sun was using their own proprietary display server (NeWS), rather than generic X11. It launched processes directly through the `execve` system call, rather than launching a shell. – DrSheldon Aug 23 '18 at 03:54
28

You cannot bypass the script execution. This is your login shell, and will be started every time you login. And as a login shell, will log you off every time it ends. But you can use quirks, bugs and inconsistencies on the login shell to escape.

One thing you could do is to escape to a shell using any option on the menu. If the menu lets you start vim, less, more or some other commands, you can theoretically break free. If the sysadmin is experienced, those commands will use their restricted versions and will not work.

ThoriumBR
  • 50,648
  • 13
  • 127
  • 142
  • 25
    _"You cannot bypass the script execution."_ So certain are you. That got me [googling](https://www.google.com/search?q=linux+bypass+login+shell): plenty of anecdotes, CTF challenges, etc, where sshd is misconfigured in some way that lets you bypass the login shell ([sometimes the distro's default ssh config even!](http://commandline.ninja/2012/05/06/binfalse-sbinnologin-and-ssh/)). So is this one of those _"theoretically fine if you do it properly, but dangerous in practice"_ kind of things? – Mike Ounsworth Aug 20 '18 at 18:39
  • 1
    The last link is about creating a tunnel, not logging in. Most of the solutions involve using `sudo` when you have another user on the system. And I could not find anything interesting on that Google query. Care to share a way to bypass the login shell? It will be a nice addition to my library! – ThoriumBR Aug 20 '18 at 19:17
  • 2
    Yeah, if we're defining "Bypass the login shell" as _"gain shell access to this system over ssh"_, I agree with you: I'm not aware of anything. But for a slightly broader definition _"get the system to do something other than what the login shell allowes"_, then there may be more hardening required beyond just setting users' login shell. Your answer is good, I just wanted to point out that there's a jr. sysadmin trap lurking here! – Mike Ounsworth Aug 20 '18 at 19:38
16

I remember a wargame challenge where there was a similar case - the shell pointed to something that simply printed some output using the more command, then terminated the session. However, since more features a built-in text editor (in this particular case it was vi), it was enough to resize the terminal window from which you were connecting so that more is activated, then use it to escape the shell.

So, the answer depends on what your script does. Check the man pages for each of the commands you are running to avoid a vulnerability.

Elhitch
  • 403
  • 3
  • 11
8

With the sample script you have posted, the restricted user can for example learn a whole lot about the system, like names of other users and installed programs. E.g.

What is your name?
> /home/* 
Hi /home/foo /home/bar /home/sadeq

The actual script you have may be exploitable in similar ways, perhaps to the point where the user can get a real shell access.

You could probably improve the situation by starting the login menu in a sandboxed environment: it won't necessarily be 100% bulletproof, but at least sandboxing will plug a whole bunch of security holes the author of the script may have left.

Dmitry Grigoryev
  • 10,072
  • 1
  • 26
  • 56
5

TLDR: Script you're mentioned is secure!

But understanding that in production you may use different version, you should be aware of following concepts:

1. Whether the 'read' is vulnerable to command injection. If it is vulnerable, then 'name' value like 'Bob; cat /etc/passwd' could return contents of passwd file and 'Bob && /bin/bash -i' could give interactive bash session.

Such questions were already asked, f.e. here:

https://stackoverflow.com/questions/34640504/is-it-possible-to-perform-shell-injection-through-a-read-and-or-to-break-out-of

Answer says "No, not vulnerable", because of:

"(..) modern shells parse the statement prior to any variable substitution, and are thus unaffected by this attack."

So in your example user input by 'read' cannot be bypassed from within standard shell.

2. Where input is parsed?

Your scrip is secure, because 'echo' do not provide any escape tecnique (at least not known). But be mindful of using "dangerous" binaries like mentioned in f.e. here:

https://fireshellsecurity.team/restricted-linux-shell-escaping-techniques/

If user input is parsed by: man|less|more, awk, find, nmap, python|php|perl, bash|sh itself, then escape is possible, granting fully interactive shell (I'd just tested with less, python and find).

If you put input only to echo, like in your example, then you're Ok.

3. Whether your input is used within shell command with asterisks (*), like: tar * or ls *

I cannot imagine when it may be useful in your scenario, but it's always better to mention. If this is a case, please became familiar with following writing:

https://www.defensecode.com/public/DefenseCode_Unix_WildCards_Gone_Wild.txt

Such a behavior also may lead to escaping your script.

dtrizna
  • 67
  • 3
  • 3
    Wildcards Gone Wild was an interesting read; thanks for that. I'm surprised it doesn't discuss the defence against that attack, though, which is to ensure that the `--` argument is given explicitly before any wildcard. – Miral Aug 21 '18 at 07:22