So, let's sum up what
we've gotten out of this particular lesson.
The heart of the matter is
that when you have
an environment and you're running a sub-process,
that sub-process should never
assume the environment is pristine.
You can go ahead and change individual values,
but as the multiple insertions of paths showed,
you may not get the right ones.
So, it's much better just to completely clean
out the environment and we'll talk
about how to do that in a minute.
For whatever it's worth,
changing parts of your environment,
violate several fundamental design principles
including least privilege,
fail-safe defaults, and least common mechanism.
Least common mechanism system minimize sharing.
So, in that context,
the environment variable is
shared between the parent and the child.
We talked about least privilege already.
Fail-safe default says that if something goes wrong,
the program will either
still be able to continue or if it fails,
it will do so and restore the system to a secure state.
The right way as I said here is delete the environment.
Just get rid of it and then build your own,
one that you know is safe.
This satisfies all of
the design principles as that next slide shows.
Further, if you delete
the environment variables and that deletion fails,
you know worse off than you started.
So, it's a good idea to do this anyway.
For security-related programs,
do not dynamically load them, period.
There are manuals which tell you how to do this.
It's typically a compile-time option.
For FreeBSD you can give the static flag.
For Linux, the static flag also.
Solaris is very tricky and since it's being phased out,
it's probably it's not worth really going into but if
you're really desperate to know because you
happen to be working with the solar system,
this slide has a link to a web page that will help you.
Okay. Now, as another example,
FreeBSD is one of
the more secure systems around but
even there people make mistakes.
It turns out in FreeBSD the,
Run-time dynamic loader ignores
PRELOAD and LIBRARY PATH and so forth.
All right, but it also calls
unsetenv LD_PRELOAD that gets
rid of it from the environment.
Now, unsetenv walks down
the environment list looking for LD_PRELOAD.
What happens if there's an environment
variable before there?
That's just junk.
It turns out in this particular context
if the garbage environment variable came first,
unsetenv would fail because it expected
the values to be well
formed so you put a garbage one first.
When the unsetenv environment variable fails,
LD_PRELOAD is still up there and again,
the system will use that value. Moral of the story.
If unsetenv doesn't work,
it's going to return an error value.
This is why you always want to check the values,
return values of functions and system calls.
The only time you don't do it as if you don't care.
For example, if you're closing a file
and then immediately exiting the program,
it doesn't matter whether close works or not.
Exiting the program will close every file.
The other thing too is as you design a program,
figure out where your trust is,
what do you trusting exactly?
In many cases, you can simply minimize what you trust.
In cases where you can't you can often identify
where problems might arise and try
to program defensively against them.
Don't use dynamic loading as I
said earlier and if you have problems,
notify the system administrator at once.
So, the moral here is identify
design and implementation trust points
and see what you can do
about reducing the number so
that you don't have
to trust this man as you do currently.
To sum everything up,
the lesson to summary is
simply be very careful when you rely on the value
of environment variables because
those are under the control of
the user who is running the program
not of the programmer,
unless the programmer explicitly resets them.
When a privileged program spawns another,
always reset the environment to a safe state and
I don't mean just the users and the groups,
I also mean the environment variables.
Don't overwrite, delete.
If you want to change path,
delete path and then create a new path.
It's much safer that way.
That concludes lesson two of
the Secure Programming Modules. Thank you very much.