Format string vulnerability in sudo
Posted Jan 30, 2012 22:33 UTC (Mon)
by arjan (subscriber, #36785)
[Link] (4 responses)
if you compile with -D_FORTIFY_SOURCE=2, glibc's printf and co do some extra checks that will block most format string sploits.
Posted Jan 30, 2012 23:11 UTC (Mon)
by SEJeff (guest, #51588)
[Link] (1 responses)
Posted Jan 30, 2012 23:31 UTC (Mon)
by mathstuf (subscriber, #69389)
[Link]
[1]http://kojipkgs.fedoraproject.org/packages/sudo/1.8.3p1/2...
Posted Jan 30, 2012 23:37 UTC (Mon)
by mgedmin (subscriber, #34497)
[Link]
Posted Jan 31, 2012 7:44 UTC (Tue)
by Adrien (guest, #82659)
[Link]
Code:
Compilation:
-Wformat is enabled by -Wall but -Wformat-nonliteral is not (not by -Wextra either). Still, it's really something that should not be skipped (along with a number of other warnings; C developers: USE THE WARNINGS!).
For reference, from gcc's manpage:
Posted Jan 30, 2012 23:00 UTC (Mon)
by pr1268 (guest, #24648)
[Link]
$ sudo -V Thank goodness Slackware is a few versions behind bleeding edge! :-D Yes, I did read the part about "...that does not mean that such exploits do not exist."
Posted Jan 31, 2012 5:01 UTC (Tue)
by josh (subscriber, #17465)
[Link] (22 responses)
Posted Jan 31, 2012 7:10 UTC (Tue)
by rqosa (subscriber, #24136)
[Link] (21 responses)
> Honestly, programs need to stop looking at argv[0] at all. Using argv[0] doesn't necessarily cause a vulnerability â it's no more of a hazard than the other elements of argv. It just needs to be treated like any other untrusted data source (which in this case probably means it should have been used as one of the values to which the format string was bound, rather than part of the format string itself). > I don't know why any program looks at argv[0] at all One thing argv[0] is often used for is to allow a program to print its own name, such as in the "usage" message that's printed in response to the "-?" switch, or in "trace" messages used for debugging. I'm guessing that the latter usage is what sudo uses argv[0] for â the vulnerability report says that it's in a function called sudo_debug() which is intended for use "when developing policy or I/O logging plugins". So, probably sudo_debug() is a function that plugins call in order to print trace messages, and it uses argv[0] to prepend something like "sudo: " to the messages before printing them.
Posted Jan 31, 2012 8:59 UTC (Tue)
by zuki (subscriber, #41808)
[Link] (2 responses)
usage: ../../usr/bin/sudo [options]
(Besides the user probably knows how he or she called the program.)
Posted Feb 1, 2012 19:17 UTC (Wed)
by wahern (subscriber, #37304)
[Link] (1 responses)
It's usually far easier to just use warn(3) and warnx(3) from <err.h>, which prepend the program name. Or getprogname() (*BSD) or program_invocation_short_name (glibc) if you're rolling your own formatter. But sudo probably needs to be much more portable than than those allow.
Posted Feb 1, 2012 19:22 UTC (Wed)
by wahern (subscriber, #37304)
[Link]
Although, calling themselves something other than how they were invoked would be quite confusing, IMO.
Posted Jan 31, 2012 9:00 UTC (Tue)
by josh (subscriber, #17465)
[Link] (17 responses)
Posted Jan 31, 2012 9:59 UTC (Tue)
by alonz (subscriber, #815)
[Link] (10 responses)
argv[0] is more robust.
Posted Jan 31, 2012 13:44 UTC (Tue)
by josh (subscriber, #17465)
[Link] (9 responses)
Posted Feb 1, 2012 8:00 UTC (Wed)
by cmccabe (guest, #60281)
[Link] (8 responses)
And there isn't any other way to get the name of a running process without resorting to horrible platform-specific hacks.
Before you comment: yes, I'm aware of prctl, which allows you to get the initial 15 bytes of the name, and reading /proc/cmdline, and even running ps and grepping for the process name. They are all much worse than just using argv[0].
Posted Feb 1, 2012 8:10 UTC (Wed)
by josh (subscriber, #17465)
[Link] (7 responses)
I don't, however, see the point of trying to adapt to sysadmins blindly renaming executables. The program is called "sudo", and it should refer to itself as such. I see nothing wrong with this:
~$ strangename foo
Sysadmins should not blindly rename executables without informing those executables at compile time. Autoconf makes renaming executables fairly straightforward; just look at --program-transform-name and similar, which exists for crazy sites that install GNU programs with a 'g' prefix, such as gsed. And if you use a packaging system, you shouldn't bypass the packaging system by renaming any files it installed.
Posted Feb 1, 2012 8:39 UTC (Wed)
by ekj (guest, #1524)
[Link] (2 responses)
Similarily, the program is still the sudo-program, even if I rename the executable to carbonated_kryptonite
Posted Feb 1, 2012 20:01 UTC (Wed)
by rqosa (subscriber, #24136)
[Link] (1 responses)
Posted Feb 1, 2012 20:02 UTC (Wed)
by rqosa (subscriber, #24136)
[Link]
Posted Feb 3, 2012 6:36 UTC (Fri)
by cmccabe (guest, #60281)
[Link] (3 responses)
Even if we ignore the rename issue, there are plenty of reasons why a program might want to know its own name.
One of them is if you are writing an argument parsing library intended to be used by many different programs. You won't know the program name ahead of time, and you want to print it out in the usage message.
Another is if you want the same program to have different behaviors based on the name it was invoked with. Busybox has used this trick for more than a decade to avoid the space overhead of having a different binary for each command.
If you're searching for configuration files, one place you might want to look is in dirname(argv[0]).
Just because you don't have the imagination to think of good uses for argv[0], doesn't mean that they don't exist.
Posted Feb 3, 2012 6:44 UTC (Fri)
by cmccabe (guest, #60281)
[Link]
Posted Feb 3, 2012 8:54 UTC (Fri)
by josh (subscriber, #17465)
[Link] (1 responses)
Libraries ought to accept the program name as a parameter; the program could choose to pass them argv[0] if it wants to, but might want to pass something else (a subcommand name for instance), or just pass the compile-time name of the program.
You *definitely* don't want to look in dirname(argv[0]) for configuration files, for several reasons: argv[0] need not contain a path at all, it might contain a user-controlled path that you don't trust, and on most systems the path containing the binary will never contain configuration files. Most programs get their configuration path at compile-time; programs using autotools get it from the ./configure command line.
As for making behavior conditional on the program name, that makes sense for something like busybox that needs to save space at all costs, but most programs don't do that anymore due to various logistical complications, preferring instead to have the same behavior no matter how they get invoked. For example, these days gunzip refers to a shell script rather than a hardlink to gzip.
I don't necessarily consider argv[0] a universally bad thing to rely on, but I don't think it should get used and relied on as often as it does.
Posted Feb 3, 2012 19:07 UTC (Fri)
by cmccabe (guest, #60281)
[Link]
Well, I would definitely never suggest doing this for setuid binaries, like sudo. I did it once for with scripts that I wrote and it worked out fine.
Posted Jan 31, 2012 10:25 UTC (Tue)
by gowen (guest, #23914)
[Link] (5 responses)
foo(const char* user_string)
when what you mean is:
foo(const char* user_string)
Posted Jan 31, 2012 11:59 UTC (Tue)
by epa (subscriber, #39769)
[Link] (2 responses)
Posted Jan 31, 2012 13:45 UTC (Tue)
by josh (subscriber, #17465)
[Link]
Posted Jan 31, 2012 13:46 UTC (Tue)
by gowen (guest, #23914)
[Link]
Posted Jan 31, 2012 13:46 UTC (Tue)
by josh (subscriber, #17465)
[Link] (1 responses)
Posted Jan 31, 2012 13:50 UTC (Tue)
by gowen (guest, #23914)
[Link]
And I like that /bin/sh gets me a more POSIXy shell that /bin/bash, without needing two executables.
Posted Jan 31, 2012 16:43 UTC (Tue)
by jengelh (guest, #33263)
[Link]
Posted Jan 31, 2012 19:31 UTC (Tue)
by iabervon (subscriber, #722)
[Link]
The problem is that they've got a: function which wants to do a single write() and get the executable name at the beginning, following printf() rules for the fmt. They probably should have done it by using the preprocessor to paste "%s" into the beginning of the format string and the call to get the executable name into the beginning of the arguments (which limits callers to string literals for the format, but that shouldn't be a problem).
Format string vulnerability in sudo
Not sure if this one gets blocked (since it's only in printf and co)
Format string vulnerability in sudo
Format string vulnerability in sudo
The linked article says _FORTIFY_SOURCE helps here:
Format string vulnerability in sudo
"On systems that support FORTIFY_SOURCE (most Linux and NetBSD), adding -D_FORTIFY_SOURCE=2 to the OSDEFS line in src/Makfile and then rebuilding sudo will prevent the bug from being exploited."
Format string vulnerability in sudo
| % cat a.c
| #include <stdio.h>
|
| void f(char *fmt) {
| printf(fmt, 1);
| }
| % gcc -c -Wformat -Wformat-nonliteral a.c
| a.c: In function âfâ:
| a.c:4:3: warning: format not a string literal, argument types not checked
| -Wformat-nonliteral
| If -Wformat is specified, also warn if the format string is not a
| string literal and so cannot be checked, unless the format function
| takes its format arguments as a "va_list".
Format string vulnerability in sudo
Sudo version 1.7.4p6Format string vulnerability in sudo
Format string vulnerability in sudo
Format string vulnerability in sudo
> name, such as in the "usage" message that's printed in response to the
> "-?" switch, or in "trace" messages used for debugging.
This doesn't make much sense. What is the gain? Saving 5 bytes on the name string? Of course there are some exceptions, like programs which vary their behaviour based on argv[0], or which can legitimately be installed under different names, but 99% of programs are better of printing their real name, even if called differently. E.g. if the user specifies the full path ../../usr/bin/sudo, it's inelegant to say
Format string vulnerability in sudo
Format string vulnerability in sudo
Format string vulnerability in sudo
But then you run into trouble if somebody renames the program – e.g. because of a name clash with some other program, or in order to install two versions of the same tool concurrently.
Format string vulnerability in sudo
Format string vulnerability in sudo
Format string vulnerability in sudo
Format string vulnerability in sudo
sudo: foo: command not found
Format string vulnerability in sudo
Note, though, that it says that the sudo_debug() logging facility is intended for use by developers of sudo itself (and its plugins). I suppose they might want to name their development/debugging builds of sudo differently from the main systemwide installation of sudo.
Format string vulnerability in sudo
(And then have the log messages from that development build show up under the chosen name.)
Format string vulnerability in sudo
Format string vulnerability in sudo
Format string vulnerability in sudo
Format string vulnerability in sudo
Format string vulnerability in sudo
> for configuration files, for several reasons: argv[0]
> need not contain a path at all, it might contain a
> user-controlled path that you don't trust, and on most
> systems the path containing the binary will never contain
> configuration files.
Format string vulnerability in sudo
{
printf(user_string);
}
{
printf("%s",user_string);
}
Format string vulnerability in sudo
Format string vulnerability in sudo
Format string vulnerability in sudo
Format string vulnerability in sudo
Format string vulnerability in sudo
Format string vulnerability in sudo
Format string vulnerability in sudo
sudo_debug(level, fmt, ...)
