On Fri, Apr 07, 2006 at 09:38:08PM +0100, Ulf Harnhammar wrote:
> Perhaps you could end it with a short, practical overview on how to find a
> few common
> mistakes in programs written in various languages? If you want me to, I could
> put
> something together and you could work it into the longer paper somehow.
Here it is, finally. You may have to edit it to make the text fit in, as our
writing
styles are quite different.
// Ulf
One very common problem in C/C++ programs with suid/sgid privileges
is to use sprintf and a format string containing "%s" to copy data
from an environment variable to a char array of a fixed size. The
environment variable can have any size, so unless the programmers
check the size earlier, it is probably a local buffer overflow that
can be exploited to execute arbitrary code with escalated privileges.
You can find such program constructs with this command:
egrep -r 'sprintf.*%s.*getenv' *
It both gives false positives ("%s" might not refer to the getenv
call) and false negatives (all three constructs may not be on the
same line in the code), but it is a good starting point.
You fix such bugs by changing "sprintf(buff, something)" to
"snprintf(buff, sizeof(buff), something)" if and only if buff is
a char array.
--
Another very common problem is syslog calls with no format
string. The syslog call, along with all calls in the printf family
as well as setproctitle, forms its output from a format string
that takes parameters. The format string must be a constant and
not user-defined data, otherwise you have a bug that could cause
crashes or even serious security problems in the form of arbitrary
code execution.
A common mistake is to write logging code that looks like this:
syslog(priority, buff);
You can find many such mistakes with this command:
egrep -r 'syslog[ TAB-CHARACTER-HERE]*\([^"]*$' *
(In bash, you insert the TAB character with Ctrl-V and then TAB.)
You fix the bugs by changing such lines to 'syslog(priority,
"%s", buff)'.
--
A final common problem in C/C++ code is using the fscanf call with
a format string containing "%s" or "%[something]". Such constructs
continue copying from the stream pointer as long as the right
type of characters are found (the ones in the "%[" definition,
or non-white-space characters in the case of "%s"). Unless the
file in question is a special file in /proc or /dev, there is no
way to know how many characters it will read. If you try to check
that beforehand and allocate the right amount of data, the file
could possibly change inbetween checking it and actually reading
it with fscanf.
You can find many problems of this type with this command:
egrep -r 'fscanf.*%[[s]' *
You fix the bugs by adding a maximum field width to the format string
parts - if "%s" will write to char buff[10], you should change it to
"%9s" instead, and likewise with "%[something]".
--
A common problem in Perl code is to use the open call with an EXPR
part that only consists of untrusted, perhaps remote, input. By
setting special characters at the beginning or end of the EXPR part,
you can make the open call start commands, read from, write to
or append to files. If you only want the open call to read files,
you must say so by starting the EXPR part with a "<" character.
Consequently, 'open(INPUT, $file)' should often be written as
'open(INPUT, "<$file")' to avoid any problems.
[I didn't have time for anything else, but feel free to comment or
add stuff to it]
|