Why setuid scripts are fundamentally a bad idea

December 19, 2007

The real problem with setuid scripts on Unix is not that writing secure shell scripts is challenging and obscure, it is that they are fundamentally insecure because of how the kernel runs them. While the kernel runs programs by directly loading them into memory, it runs scripts by running the script's interpreter with the filename of the script, leaving it up to the interpreter to read and execute the script itself. As is normal on Unix, there is nothing that keeps what file the filename points to the same between these two steps.

In other words, there is no way to guarantee that what the interpreter reads is the same script that the kernel gave setuid permissions to; it might be some other script that an attacker put in place in the time between the kernel starting the (setuid) interpreter and the interpreter opening and reading the file.

Since this is a direct consequence of sensible and long-standing decisions about how to run scripts, Unix can't work around the problem in general without creating incompatibilities. Nor can the problem be fixed in the interpreters alone by having them fstat() the opened script's file descriptor and refusing to work unless it has appropriate privileges, because this breaks exec()'ing scripts from a setuid program.

The best solution would be for the kernel to directly pass the file descriptor of the script that it already has to the interpreter. The command line filename would remain, but in fd-aware interpreters would only be used for $0 or the equivalent. However, this would require new fd-aware interpreters, which would be specific to the Unix variant that did this, and the demand for general setuid script support is low (to put it one way).


Comments on this page:

From 66.42.187.181 at 2007-12-20 07:57:01:

Solaris has supported suid scripts for quite some time IIRC; it passes the filename /dev/fd/3 or similar to the interpreter in place of the script's normal location in the filesystem. I thought Linux did the same thing (with /proc/self/fd/3) but I can't seem to reproduce the behavior I thought I remembered.

-- Kragen Javier Sitaker

From 83.145.204.27 at 2007-12-20 11:54:30:

On sidetracks, but I want to make this comment nevertheless: in this world where it is a mantra to say that compiled languages such as C and C++ are always and everywhere insecure, it is refreshing to discuss the potential dangers of interpreted or scripted languages.

With the danger of making myself laughable, I too would answer "yes" to the following quote:

"Q3: Are compiled languages such as C safer than interpreted languages like Perl and shell scripts?

The answer is "yes", but with many qualifications and explanations."

http://www.w3.org/Security/Faq/wwwsf4.html

... if I really, really mastered C in Unix enviromments.

- drear.

By cks at 2007-12-20 23:33:45:

The downside to the Solaris approach is that it breaks anything that wants the script filename to be meaningful (of which there are a few things).

(I thought the same as you about Linux, but on a quick skim of what kernel source I have lying around, back to 2.0.38, there's no code to do anything special with the script name if things are setuid.)

Written on 19 December 2007.
« How x86 Linux executes ELF programs
Virtualization does not eliminate security concerns »

Page tools: View Source, View Normal, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Wed Dec 19 23:16:27 2007
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.