So this was the project that I received and I'm stuck half way.

In most Linux distributions (Fedora and Ubuntu included), /bin/sh is actually a symbolic link to /bin/bash. To use zsh, we need to link /bin/sh to /bin/zsh. The following instructions describe how to change the default shell to zsh:

  • login as root
  • cd /bin
  • rm sh
  • ln –s zsh sh

The system(const char *cmd) library function can be used to execute a command within a program. The way system(cmd) works is to invoke the /bin/sh program, and then let the shell program to execute cmd. Because of the shell program invoked, calling system() within a Set-UID program is extremely dangerous. This is because the actual behavior of the shell program can be affected by environment variables, such as PATH; these environment variables are under user’s control. By changing these variables, malicious users can control the behavior of the Set-UID program.

The Set-UID program below is supposed to execute the /bin/ls command; however, the programmer only uses the relative path for the ls command, rather than the absolute path:

int main() 
    system("ls"); return 0;

Login as root, write this program into a file named bad_ls.c, compile it (using gcc –o bad_ls bad_ls.c) and copy the executable as a Set-UID program into /tmp with permissions 4755.

Is it a good idea to let regular users execute the /tmp/bad_ls program (owned by root) instead of /bin/ls? Describe an attack by which a regular user can manipulate the PATH environment variable in order to read the /etc/shadow file.

I have successfully changed the default shell to zsh, created the executable bad_ls, and copied it to /tmp with permission ID 4755.

Describe an attack by which a regular user can manipulate the PATH environment variable in order to read the /etc/shadow file.

This is where I'm stuck.

After running the bad_ls file, I change the PATH env Variable to point to the current directory by using the code

export PATH =.:$PATH 

If I run ls -a /etc/shadow, all I get is this: /etc/shadow

I would be really thankful if you could guide me in this problem.

  • You need to think about why having a setuid executable that runs ls via a system call is a bad idea. What is special about ls? – steeldriver Oct 16 '16 at 19:56
  • "This is because the actual behavior of the shell program can be affected by environment variables, such as PATH; these environment variables are under user’s control." Now I need to know how to read /etc/shadow file by attacking using PATH env variable. Please help – Data Shark Oct 16 '16 at 20:27
  • Well ... think about how PATH is used by the shell when you execute a command such as ls. Also have a read of the NOTES section of the system manual page (man 3 system). – steeldriver Oct 16 '16 at 21:33
  • BTW: The first paragraph of the project text should not be taken with a grain (or rather block) of salt. Ubuntu has not been using bash as default shell (via symlink to sh) for 10 years (!). The last version where thas was the case was 6.06. Instead Ubuntu, as well as Debian and most of their derivatives, use dash. Also, you should not - ever - change the default shell (i.e. /bin/sh, be it a symlink or even binary) unless you know exactly what that entails. Packages, daemons, etc. may depend on /bin/sh behaving in a certain way, where the replacement may do things differently. – Adaephon Oct 18 '16 at 13:08
  • As to the question, another hint may be in order: The name of a program does not necessarily reflect its function. – Adaephon Oct 18 '16 at 13:16

The problem is this case is that system("ls") would run whichever executable named ls it finds first in the user's set PATH.

This ls does not necessarily have to list the contents of a directory. Instead it could be a script like this:

cat /etc/shadow

Let's say you place this script somewhere in a directory below your home directory, for example /home/datashark/bin and add this to your PATH:


If you now run ls, you will not get a directory listing, instead you will receive an error message:

cat: /etc/shadow: Permission denied

But if you run bad_ls, the system("ls")-call therein will also look for a executable named ls in your PATH and find and /home/datashark/bin/ls instead of /bin/ls. As bad_ls runs with elevated root permissions, the script named ls will (on certain systems - see below) also run with elevated root permissions and so will the command cat /etc/shadow, which will print the contents of /etc/shadow.

So it is a bad idea for root to let normal users run bad_ls as long as it has SUID privileges, because it would run any program named ls that comes first in the user's PATH.


This does not work on every Linux system. For example, it will not, according to man 3 system, work on systems where /bin/sh is or links to an (unpatched) bash of version 2 or newer (2.0 was released in 1996). bash drops privileges on startup. This does not only effect the ls script but also the call system() before, as system() passes the command to /bin/sh.

It may work on other distributions that do not use bash as /bin/sh. Contrary to the the information stated in the project, Ubuntu (like Debian and probably most derivatives of either) uses dash and not bash as /bin/sh and has been doing so since version 6.10 (from 2006! See this page in the Ubuntu Wiki). It seems that with recent versions of Ubuntu (at least 16.04) dash and therefore /bin/sh are patched to automatically drop SUID permissions (Look for "priv" in man dash).

  • Thanks for the detailed explanation Adaephon! Unfortunately, the project was due a day before you posted the answer. – Data Shark Oct 20 '16 at 16:27
  • By the way, how do I create this script? #!/bin/sh cat /etc/shadow – Data Shark Oct 20 '16 at 16:30
  • @DataShark I am sorry to hear that. Unfortunately I did not see your comment about the urgency of the matter until a few hours after you posted it. Again, sorry about that. As for the script: just create a file with a text editor and put it in there. Save the file and make it executable with chmod. – Adaephon Oct 20 '16 at 16:47
  • Ignore the previous comment. I finally created the script, copied both the files ls and bad_ls to /tmp, set permission 4755 to bad_ls, changed the path to point it to /tmp but when I run the bad_ls file I get this message – Data Shark Oct 20 '16 at 16:50
  • I get the message seed@ubuntu:~$ /tmp/bad_ls cat: /etc/shadow: Permission denied It's actually better than before. Running bad_ls previously would only list all the directories. – Data Shark Oct 20 '16 at 16:52

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.