Trusted programs
MOTTO:
- Paranoia be with you, Anakin
- Paranoia be with you, Master
Said Anakin when he got first assignment on his own as security consultant.
Let's assume your account have administrative rights. So you are able to add/delete/change users.
One day, you got an e-mail from sexy_lady@example.com with the subject "I love you".
Into the body of message a program claiming will print out her address. You run it....
Well, you've got no address but a virus happily started on your computer. Is your system screwed?
On most operating systems yes. But let's try to change that.
On the Client/Server model, the only one having the power to change the system it is the
server. The client just request some actions to be performed. Into a world without viruses,
any program running under a user account will be trusted with the rights assigned to that
particular user. But our world is far away to be perfect, and a virus may be the one running
under a user account. The server must be sure that the request is made by a legitimate program.
The legitimate program is a program trusted do not perform any action without being asked to
do so by the user it run it. If a request is made by a secure program, now the only job left
for the server is to be sure that the user is legitimate to ask the requested action.
If a user start a virus received by e-mail, the server should not provide it with any
protected resource or perform action based on that request.
The responsabilities of a trusted program are:
- Assure that it is a legitimate request
That is. A command line trusted program have to check if the data it receive are from
a user terminal, where a legitimate user is logged in. In the case when a trusted program
is started to work into a pipeline, it must insure that the program providing input data
it is a trusted program too, and that the command was typed from a terminal where a legitimate
user is logged in. In case that a trusted program is started by another program it must insure
that either that program is trusted, either it was declared to be allowed to start trusted programs.
That is, if you want to use a trusted program from within a script, that script must be
registered into a database of trusted scripts. It will not be started by /bin/bash but by a
/bin/secured.bash, who will check the existence of the script into the database, and check if his MD5
sum match the one from the database.
- Provide a pre-filer from data sent to server
The server modules, who will perform the protected work in behalf of the client are
not intended for direct user interaction but only for communication with trusted programs.
So, the format of input/output (the protocol) for communicating with modules will be designed
for easy and safe parsing on the server side. This will impose for the trusted program writers
to parse and validate any user input, then generate the output that will be sent to the server.
This is an extra checking for the data, and chances are that a malformed input will be rejected
by the trusted program. Eventually it may crash the trusted program but not reach the server.
Even a smart exploit who succeed to pass the validation in the trusted program and reach the server,
will be already converted into a format that it is very easy to be validated on the server side.
That is, when design the communication protocol betwen trusted program and server, the only one
focus have to be how easy and safe is to validate it on server and nothing else.
- Requirement rights checking
The trusted program, may have many options. Some of them may not to be available for any user.
In this case, the trusted program it is to check which options are legal for a user and refuse
illegal requests.
The responsibility of declaring a program trusted will be assigned to the system
administrator, or to the system installation program(for home users).
In the latest case, the program will take the decision at install time based on
the level of trust assigned to a particular vendor's public key.
When the system is installed, a special user will be assigned for trusted programs: sys.
In order to declare a program as trusted, it will be made setuid sys. The sys user won't
have any rights on the file system (maybe only some log files).
The system server will require that always the incoming uid to be sys in order for a
connection to be declared trusted. Along with sys credentials, the client will send a unique
program name. This program name is trusted since it come from a sys connection.
The server will allocate a ClientProcess structure where it keep: pid, socket handle,
program unique name (sent into first message) and access rights of this program. The access rights are
read from a database where for each program unique name are listed the server task this program may require.
The server acknowledge with a OK message, when the structure is created, and the server is ready to receive
requests from this socket.
The trusted program will drop his sys privileges after opening a socket with the server,
sent the credentials and unique name and receive the OK from server. This will happen as soon the program start,
before processing any user input or command line parameters (so no buffer overflow may be exploited yet).
A special note for Linux: In Linux the rights for the socket can be also made 0600,
to increase security, but this feature is not available on all Unix systems.
The socket that was connected with the server is marked as close on exec using fcntl(F_SETFD)
system call. Just in this moment, the trusted program may start to process user input, or command line parameters.
Using setuid programs, not only provide to the server a method of authenticate a
trusted program, but also prevent the Shared library attack.
We are now pretty safe in case of an exec triggered by an buffer overflow attack:
= The connected socket will close on exec. So, the intruder program started by attacker won't be able to request protected task from the server
= The trusted program run with current user privileges, so the attacker don't get any more privilege over what he already have.
= Since the socket close, the server remove authorization the program have, so even if the new program connect again it won't be
recognized as a trusted program.
The only one remaining vulnerability I can see, is an injection of code into the program
who will succeed to take control over trusted program code, and send protected requests to the server.
Well, nobody's perfect :-) and this action may be however much more difficult to
achieve than starting a shell. But, at least in theory it can be done. This is the reason
for which I recommend replacing C with C++(or safer languages), wherever is required parsing
or validating the user input. The things may be done a little bit more safe in C++ than in C !!!
(Additional security checking that may be enabled on high security systems)
There are additional checking that can be done. A thread may periodically check the existence of a pid.
When look out for the existence of a pid, the thread may also check if the
program running with with that particular pid is the original one. For example, when first
connect has been made, the server also find out which program is running with that particular
pid. In Linux this can be done by readlink the file /proc/[pid]/exe. If found that the exe was changed, a "investigate" program may be started to
check what is going on. This is an post-attack response (like an
intrusion detection system) but may be helpful to prevent hostile actions.
If you are afraid of cheaters we can even catch the programs running as root who lie
about their credentials(at least in Unixes having proc filesystem). Having the pid,
we can see a programs opened descriptors, with getpeername() and the help of the
/proc/net/unix table we can check if a socket of that particular pid is connected to our.
If no, a "punish_criminal pid" program can be started.
Using /proc/[pid]/maps we can check the shared libraries loaded by the program, and compare
their MD5 sum against a database built at system installation and signed with the admin
public key.
And if you are really paranoid the things can keep rolling on ...
Demo
This demo show a introductory version of the sys server. It load (in this moment from a hardcoded function)
a set of tasks for each process who connect to the server. At this time, if the client is trusted(uid was sys) it get access
to task1 too, oterwise it get access only to task2. The client also call a function from a library, so you can see that when
setuid sys
the Shared library attack won't work. You can download it from here.
Back to advanced Advanced Unix programming techniques page
Sys++ Project Home page
Visit M.T.M. Home Page