a c x I. .7 (1.! ‘ "r {555? 3'1 ‘7 ,. “52:5: I l.!{ .f 3. irfai K5336}. , .urfi 55%.... 1: ‘ :9.” .32.“ {Va} 1 5,le (In)? xi... :flrthf. PM..." . . at; 1. ii . ‘ , c... w...»:1vlf .a .u “41.2)... 3.8 4121'... ,.. 3.23.. ../3, ., . .. .4. .. < :5 . . V 44') . , ‘zunn_.J...f.a. : .\.na. “1538 ’n .7 00", 55,4 ”30,, LIBRARY & a a? Michigan State University This is to certify that the thesis entitled The Last Line of Defense: A Host-based, Kemel-Ievel Intrusion Detection System presented by Timothy R. Westran has been accepted towards fulfillment of the requirements for the MS. degree in Computer Science Major Progdsor’s Qfinature /1 / 1/ o “e I I / Date MSU is an Affirmative Action/Equal Opportunity Institution PLACE IN RETURN Box to remove this checkout from your record. To AVOID FINES return on or before date due. MAY BE RECALLED with earlier due date if requested. DATE DUE DATE DUE DATE DUE 6’01 cJCIRC/DateDuepGS-sz THE LAST LINE OF DEFENSE: A HOST-BASED, KERNEL-LEVEL INTRUSION DETECTION SYSTEM By Timothy R. Westran A THESIS Submitted to Michigan State University in partial fulfillment of the requirements for the degree of MASTER OF SCIENCE Department of Computer Science 2003 ABSTRACT THE LAST LINE OF DEFENSE: A HOST-BASED, KERNEL-LEVEL INTRUSION DETECTION SYSTEM By Timothy R. Westran This paper describes a variation of a kemel-level Intrusion Detection System (IDS). In addition to looking at system calls as others have done, we also look at arguments to system calls as well as Process ID’s and parent Process ID’s all generated with low overhead. This enrichment of the data logging dramatically reduces false positives—in fact, false positives have been eliminated for the attacks we have tested so far. Since we capture a class of host intrusions our technique will also flag unknown but related attacks. We tested the IDS with a variety of intrusions on a Linux machine while in use by a user and flagged all the intrusions with no false positives. ACKNOWLEDGEMENTS First, I would like to thank my advisor, Dr. Enbody for his many hours of assistance with both the research and the authoring of this Thesis. Dr. Enbody is the one who came up with the idea for this research and thesis. I would also like to thank Dr. Punch for offering his ideas and thoughts on this project. I would like to thank Dr. Esfahanian for accepting the invitation to serve on this thesis. I would also like to thank Michael Mack, Pat Grau, Chris Osborn, and Matt Mctts for assistance with authoring the first paper and with building the IDS itself. iii TABLE OF CONTENTS A CKNO WLEDGEMEN T S iii TABLE OF CONTENTS iv LIST OF TABLES KEY T O SYMBOLS OR ABBRE VIA T IONS vii viii Chapter I - An Introduction 1 A. Last Line of Defense 1 B. Concept 3 C. Method 4 D. Paper Organization 5 Chapter 2 - The Approach 6 A. Motivation 6 B. What we can and cannot do 6 I) What we can do: 7 2) What we cannot do: 7 Chapter 3 - Design Methodology 9 A. What are we looking for? B. How will we detect these events? C. How are we different from other approaches? 10 D. Why system call arguments? 10 Chapter 4 - Preliminary Testing 1 1 Chapter 5 - High-level IDS Logic 12 Chapter 6 - Implementation 15 A. Kernel modifications 15 I) Log system calls 16 iv 2) Log system call parameters 16 3) Log file open calls 17 B. Detection 18 Chapter 7 - File Protection 20 Chapter 8 - Exploits 31 A. Sendmail 8.11.1: exploit (aka. SXP), a Buffer Overflow. 31 B. Redhat Dump exploit, a buffer overflow. 32 C. XperLsh aploit, a SetUID exploit. 33 D. The ptrace exploit, a race condition. 34 E. The ftp exploit (akaflpexp), a buffer overflow. 34 F. The prlnx.sh exploit, SetUID 35 Chapter 9 - Limitations 3 7 Chapter 10 - Where our Scheme Fits in the World of IDS 38 Other products 40 Chapter 11 - What '5 Left to Do 51 APPENDICES 53 APPENDIX A - Source Code 54 A1 — parser pseudocode 55 File parsing 55 Process parsing 57 A2 - System Logger Modifications 58 A3 - Parser Source Code 61 A4 — Parser Source Code Description and Commentary 79 APPENDIX B - Test of the IDS 108 Bl - Parser Test For Process-Based Exploits 109 Test 1: 109 Test 2: ftpexp: 112 Test 3: mount exploit: 114 Test 4: prlnx: 117 Test 5: ptrace 119 Test 6: resdump: 120 Test 7: smlnx: 122 Test 8: su: 124 Test 9: 130 BZ - Parser Test For File-Based Exploits 133 82a - Security Level 1: 134 Test 1 and 2 run: 134 Test 1: Run passwd and fail. (normal user): 135 Test 2: Run passwd and succeed. (normal user): 136 Test 3 and 4 run: 137 Test 3: Run passwd and succeed. (root user): 137 Test 4: Run passwd and succeed. (normal user su'ed): 139 Test 5 and 6 run: 140 Test 5: Run passwd on other user and succeed (root): 141 Test 6: Run passwd on other user and succeed (su): 142 Test 7 and 8 run: 143 Test 7: Directly edit shadow as root (<<): 144 Test 8: Directly edit shadow as su (<<): 144 Tests 9 - 14: 146 Test 9: Pico shadow as root: 146 Test 10: Emacs shadow as root: 147 Test 11: Touch shadow as root: 148 Test 12: Pico shadow as su: 149 Test 13: Emacs shadow as su: 150 Test 14: Touch shadow as su: 151 Test 15 - 17: 152 Test 15: Pico shadow as normal user (Fail): 152 Test 16: Emacs shadow as normal user (fail): 153 Test 17: Touch shadow as normal user (fail): 155 Test 18: various cronjobs 156 Test 19: 158 Test 20: 161 Test 21 - extensive cron tests (all_elements.doc) 163 B2b - Security Level 2: 166 Tests 1 - 2: 167 Tests 3 - 4: 167 Tests 5 - 17: 167 Test 18: 168 Test 19: 168 Test 20: 168 Test 21: 168 32c - Security Level 3: 170 Test 1 - 2: 170 Test 3 - 4: 171 Test 5 - 17: 171 Test 18: 171 Test 19: 173 Test 20: 173 Test 21: 173 vi LIST OF TABLES Table 1 - Overview of Attacks Caught Table 2 - Process—based Exploits Test Table 3 - File test - Security Level 1 Table 4 - File Test - Security Level 2 Table 5 - File Test - Security Level 3 vii 109 134 166 170 KEY TO SYMBOLS OR ABBREVIATIONS IDS. . . . . ......................................................... Intrusion Detection System 11) ................................................................................... Identification PID....... ......................................................................... Process ID’s UID......... ............................................................................. User [D’s FTP. . . . . .............................................................. File Transfer Protocol DoS. .................................................................... Denial of Service SU ............................................................. Substitute User (or Super User) SANS ......................................... SysAdmin, Audit, Network, Security institute SUID .................................................................................. Set User ID OS ............................................................................. Operating System PAM ...................................................... Pluggable Authentication Modules PPID ........................................................................... Parent Process ID PUID .............................................................................. Parent USer ID LTT. . . . . ................................................................ Linux Trace Toolkit TTY. . . . . ...................................................................... TeleTypeWriter GID......... ............................................................................. GroupID SRI .................................................................. Stanford Research Institute BSM. . . . . ............................................................. Basic Security Module PAID. . . . . ................................. Program—Semantics Aware Intrusion Detection LIDS. . . . . ................................................ Linux Intrusion Detection System SE Linux. . .. ........................................................... Security-Enhanced Linux GNU......... .................................................................... GNU's notUNIX viii Chapter 1 An Introduction We propose a new variation of a kemeI-level Intrusion Detection System (IDS), one which looks not simply at system calls, but also at their arguments and Parent ID’s (PIDs). In addition, we focus on the “lowest-common-denominator" of intrusions. Combining that focus with the increased richness of data yields a significant increase in detection accuracy. Additionally, the resulting IDS can recognize certain classes (both large and significant) of unknown attacks. This idea harkens back to earlier host-based IDS where only system calls were cxaminedl”. Our proposed system differs by not only examining the system calls themselves, but also examining the arguments passed to these calls and the process ID’s of these various system calls. In addition, at no extra cost, we will know the parent process ID, and can monitor file access. Finally, we can focus on the common intrusion features at the lowest level to increase accuracy. Of particular importance is that, within the class of attacks we target, we are finding high true positives with no false positives. If you’ll note the table on page 5, you will see how successful we have been with achieving these goals. ¥ [1] IHofrneyr, S.A., S. Forrest, and A. Somayaji. “Intrusion detection using sequences of system calls.” Journal of Computer Security, 6:151--180, 1998. [2] 2 Lindqvist, U. and P. A Porras, “eXpert-BSM: A Host-based Intrusion Detection Solution for Sun Solaris,” Proceedings of the I7th Annual Computer Security Applications Conference (A CSAC 200]). IEEE Computer Society, New Orleans, Louisiana. December 10-14, 2001. Pages 240-251. [3] 3 Provos, N. “Improving Host Security with System Call Policies” Proceedings of the I2" USENIX Annual Technical Conference, 2003 A. Last Line of Defense The security establishment accepts multiple levels of defense as the most effective technique“. We target the last line of defense. Consider concentric rings of different defense types protecting your investment. When you think of a heavily guarded building, you may visualize a high fence around the perimeter, some armed guards around, perhaps some vicious dogs wandering, then you get to the building itself. We concentrate on that last line of defense for computer security, just as the last line for building security may use a security camera. As such, our method assumes the filtering of whole classes of attacks at outer defensive layers—Denial of Service, for example. If one assumes that certain classes of attacks are filtered, a small set of attack classes remain for consideration—increased privileges in particular. For example, the defining characteristic of a large number of attacks is, in the course of some normal transaction, the spawning of a privileged shell (such as a root shell). Existing attacks have spawned a root shell during FTP sessions, during web sessions, during email transactions, as well as at other times. If our IDS can track shell spawning and their characteristics, we can detect the occurrence of this sort of attack. Differentiating attack shells from non-attack shells is critical, but feasible with our rich data. Other classes of attacks on the last line of defense involve the modification of a small set of files which could allow privileged access. Examples include, but are not [4] ‘ Vandenwauver, M., Clacssens, J., Moreau, W., Vaduva, C., and Maier, R. (1999). “Why Enterprises Need More than Firewalls and Intrusion Detection Systems.” Proceedings of the Eighth IEEE International Workshops on Enabling Technologies: Infrastructure for Collaborative Enterprises (WE TICE '99), pages 152-157 limited to, the password file or configuration files such as for INETD. If our IDS can track changes to such files, we can detect the occurrence of this sort of attack. Note the difference in our kemel-level approach when compared to a tool such as Tripwires. Our system would not replace Tripwire (which is not generally considered to be an IDS), but would instead provide more immediate response for attack-critical files. B. Concept All of the attacks we have researched which allow the user to gain root (or admin) require some sort of elevation of privileges (assuming that the user is not already root). This elevation of user privileges will show up as an unauthorized privileged shell being spawned or as a particular system file being changed—both scenarios our proposed IDS would be able to detect because of the system call signature and associated parameters. One benefit of tracing system calls is that if a malicious user changes the name of the shell, our system would still be able to determine if an intrusion was occurring. Our goal for this project is to develop an IDS which can catch a specific group of both existing attacks and new attacks (high true positives) while not ringing the alarm every time a user checks their email or logs into the system legitimately (low false positives). Importantly, we also want to catch new exploits for which signatures do not yet exist. ‘ [5] 5 Kim, (3.1-1 and E. H. Spafford. “The design and implementation of tripwire: a file system integrity checker.” Technical Report CSD-TR-93-O7l, Purdue University, Dept. of Cmputer Sciences, Purdue University, West Lafayette, IN 47907-1398, 1993 C. Method By examining system call parameters and PIDs, we can determine a clear difference between logging in legitimately to a privileged account and exploiting the system to become a privileged account. In addition, by looking at the file system open call, its associated parameters, and PID relationships, we can determine the opening of a ‘restricted’ file by anon-privileged user. Since the basis of our approach is that a privileged account must be obtained or a specific file must be modified, this method allows us to not only catch known attacks, but also similar unknown attacks. Because of the clear-cut distinction that exists within our data-rich environment between a user obtaining privileged access legitimately and a user elevating to a privileged shell, false positives are reduced or eliminated. On the “last line of defense” identifying an intrusion requires examination of only a few items. This same approach applies to file access. Our approach assumes that certain classes of attacks are detected in outer security rings, and it would be foolish to claim that we can recognize all remaining attacks. However, we claim that we can detect an important class of attacks. In general, we are looking for a signature indicative of privilege elevation, not an overall signature of any particular attack. By only looking for the privilege elevation, we can capture any future attack which exploits privilege elevation. It should be noted that most attacks will either try to elevate privileges or else will try to edit an important system file (such as shadow). D. Paper Organization In this paper we present an overview of our approach, describe the kernel modifications we made, show how the detection is implemented, discuss the intrusions tested, present our results, and then cover limitations and future work. Table 1 - Overview of Attacks Caught Exploit name subsystem attacked classification type of attack caught? dunrpexp garbage collection Process buffer overflow Yes ftpexp FTP Process buffer overflow Yes mount Mount daemon Process buffer overflow Yes prlnx sendmail / procmail Process Set UID exploit Yes ptrace ptrace application Process race condition Yes resdump garbage collection Process buffer overflow Yes srnlnx sendmail Process Set UID exploit Yes su SU application Process buffer overflow Yes xpcrl XPERL package Process Set UID exploit Yes sxp sendmail Process buffer overflow Yes Table 1 - The table above shows a list of attacks we tested on our IDS catches. Note that our IDS knows no specific signatures. This list shows a preliminary list of the attack name, the system attacked, if it’s a file or a process attack, what type of attack it is, and whether or not we caught the attack. Chapter 2 The Approach A. Motivation Our motivation comes from the observation that most attacks on a host boil down to 1) gaining privileged access through elevating privileges through a shell or 2) modifying a file to create a privileged account. While that does not cover all attacks, it does cover a large and important number of attacks worthwhile to detect. One motivating source was the poster provided by the people of Tripwire5 which attempted to present a (large) snapshot of existing intrusions. From that large set, we observed that all those attacks could either be effectively caught with some existing tool (e.g. network vulnerability detection), involved modifying a file, or else involved obtaining privileged access illegitimately. The DARPA test set6 and the SANS/FBI “top 20” list7 further support this observation. B. What we can and cannot do Essentially, anything which will (and should) be caught by outer rings of defenses is not of interest to us, e.g. DOS. We focus our effort on what has penetrated those other layers of security. k [6] ° Lippmann, R., et al., "The 1999 DARPA Off-Line Intrusion Detection Evaluation", Computer Networks 34(4) 579-595, 2000. [7] 7 “The Twenty Most Critical Internet Security Vulnerabilities—the Expert’s Consensus”, http://www.sans.org/top20/ 1) What we can do: At this point, we have documented the ability of our system being able to catch: 1. Buffer and heap overflows (SXP, dump, ftpexp) 2. Improper use of the SUID bit (xperl, prlnx) 3. Race conditions (ptrace). We are not done documenting which attacks we can successfully detect. We expect to be able to demonstrate our ability to catch a whole range of privilege-raising attacks which use shells and file manipulation. 2) What we cannot do: Some examples of items (mostly attacks) which we are not interested in detecting or are unable to detect are: a. Denial of service b. Port scan c. Password cracking (1. Ethernet sniffing e. Network session hijacking f. Physical attacks i. Booting into an alternate OS ii. Swapping the hard drive iii. Offline password hash editing Chapter 3 Design Methodology We base our approach on the detection in the kernel of privilege-raising attacks by monitoring shells and particular files. This paper describes our Linux implementation; a Windows implementation comes next. A. What are we looking for? 1. The elevation of a user’s privileges by circumventing authentication mechanisms. 2. An outside user gaining privileged access without properly logging in. 3. Unauthorized elevation of user privileges or creation of a privileged account by modifying a file (e.g., shadow, INETD configuration file) B. How will we detect these events? We will look for inappropriate spawning of a privileged shell (root or admin) or access to a special file (e.g. shadow). For example, consider a shell spawned during a web session or during an FTP session. We can look for a user gaining root access without checking the password shadow file—the shadow file holds hashed passwords accessible only to root on Linux. For example, we can look for access using the PAM— pluggable authentication modules. Exploits do not use PAM to authenticate while legitimate privilege escalation will always use PAM to authenticate. We can look at files being opened and the PID’s involved with these file operations to determine if a sensitive file has been opened at an inappropriate time or by an inappropriate user. C. How are we diflerent from other approaches? When we look at system calls we include both arguments and process ID’s. Other approaches have tended to look either at the ordering of system calls or at network trafficl’u'g' While these methods have their merits, the logging data they generate lacks richness which creates unwanted false positives. We focus our logging to facilitate the detection of very specific sets of circumstances which indicate intrusions. In a nutshell, kemel-level logging differentiates us from most IDS, looking at system call parameters and PID’s differentiates us from other kemel-based IDS’. D. Why system call arguments? The arguments of system calls allow us to uniquely identify intrusion characteristics resulting in simple, accurate, and generic intrusion signatures. Without arguments previous system-call-based IDS’ have either resorted to profiling or to complex, attack-specific signatures which increase false positives. [8] 8 Allen, 1., Christie, A., Fithen, W., McHugh, J., Pickel, J., and Stoncr, E. 2000. “State of the practice of intrusion detection technologies.” Technical Report CMU/SEI-99TR -028 10 Chapter 4 Preliminary Testing This section is intended to provide some insight into our testing methodology and the thought process with respect to ensuring integrity. The actual implementation details and test results are available in a later chapter. We ran several tests to demonstrate our goal of low false positives and high true positives. Our testing methodology involved running each exploit individually, and then parsing the logs to ensure we catch each category of exploit (exploits are described below). Next, we tested the ability of our IDS to deal with normal user behavior while not alerting us to false positives. We tested this ability by logging in as a normal user, starting up xwin, checking email, telnetting about, using tip and ssh to connect to other systems, successfully and unsuccessfully using SU to gain root access, and rebooting the system. Our IDS did not ring the alarm for any of these activities, i.e. no false positives. We ran for about 30 minutes as a normal user to ensure that an adequate sample was taken. Finally, when logged in as a normal user, we performed some legitimate operations, exploited the system, and then performed some more legitimate operations. Ideally, the IDS should only detect the exploits, not the normal usage. Again, our IDS caught every exploit we ran, and it did not ring the alarm once for normal behavior, i.e. all true positives and no false positives. From our tests, we can comfortably say that our IDS has been proven to detect buffer overflows, SetUID abuse, and race conditions while not flagging any legitimate user activity as an intrusion for the duration of our tests. 11 Chapter 5 High-level IDS logic In this section, we discuss the higher-level logic of both our parser and our system-logger modifications. As mentioned before, our IDS is split into two pieces; a logger which always runs, and a parser which is what actually detects the intrusions. Since the parser will drive all modifications to the logging system, we should discuss the parser first. The parser has two basic parts to it; a part to find malicious processes, and a part to find malicious file accesses. By malicious we mean that the process or file access is resulting in an elevated privilege level without any form of authentication to this higher privilege level. As a point of clarification, we would like to highlight how the native authentication of Linux works. When a user attempts to login, they are asked to enter their userID and password. The password is then encrypted using the password encryption schema and compared against the recorded encrypted hashes of the proper password. If the two hashes match, the user is allowed in (a shell is spawned for the user). It should be noted that these password hashes are stored in a file known as ‘shadow’ on modern systems and ‘passwd’ on older systems. On systems which are ‘shadowed’, passwords are stored in the shadow file. The passwd file then contains placeholders which point into the shadow file. By using a level of indirection, the designers of *nix systems help to prevent unauthorized reading of user passwords. So what happens is that the user tries to get a shell, the system asks the user to authenticate 12 themselves (userid and password), the system checks this information against the passwd or shadow file. If the userid and password are both correct, a shell is spawned for the user. If the userid or password is wrong, no shell is spawned and the user is (usually) asked to enter the userid and password again. So what we know is that a user must verify their identity against the shadow file in order to login. If they do not verify their identity against shadow (or passwd in older systems), then the system could not possibly know they are authorized to use the shell. We begin by addressing the process-monitoring functionality of our parser. We are looking for three basic anomalies with respect to processes. First, we check to see if the Parent Process II) (PPID) of the open call to your shell is the same as the PID of the open call to shadow. If these two values are different, we then check to see if the shell’s Parent UID (PUID) is larger than the shell’s UID. If the parent UID is larger, the process has somehow elevated it’s privileges without checking shadow. This would be a bad thing as shadow must be checked in order to authenticate. We should note that we expect the parent UID to be less than or equal to it’s child UID’s. When you have a Parent UID greater than the child UID, this means that the child has a higher privilege than the parent did. If the shell’s PID is the same as the shadow’s PID, we need to investigate further. We check to see if the shell’s UID and PUID are both 0. If both are 0, this implies that this shell is a root shell and that the parent of this shell had root privileges. If both conditions hold, we then check to see if the shell’s PUID is less than the PUID of the 13 parent. That is, we check the parent of the parent. In doing this, we have proceeded one step up the process-tree hierarchy from the first check. If the second test fails, it implies that the process never checked shadow, this shell is privileged and it’s parent was privileged. We also know that the shell’s parent is privileged, but the parent of the parent is not privileged. We can conclude this is an attack along the same lines as the previous test. Buffer overflows invariably elevate privileges which the above technique will catch. However, it is trivial within our implementation to explicitly check for overflows, so we have added this likely redundant check. We actually check in three different ways to see if we have an overflow. First we check to see if the length of any shell command is over 400 characters long. We also check to see if any argument has more than 400 characters in it. Lindqvist and Porras [5] determined a threshold for buffer size to be 400 after tracing 4 million events. If either the command or any of its arguments is longer than 400 characters, we raise an alarm as a buffer overflow candidate. It should be noted that our IDS is able to catch both buffer overflow and race condition attacks, even though the IDS itself does not explicitly scan for either form of attack. We can do this because of the root exploitation with these exploits. When a system is exploited, the IDS does not discern the method used to gain root access. What matters is that privileged access is given without authentication. If authentication were to occur, the session would be rejected and the system would not be exploited. We know that authentication is circumvented in nearly every type of exploit. 14 Chapter 6 Implementation We used Redhat 6.2 for our test machine, an arbitrary choice which represents relatively generic Linux. A. Kernel modifications Our Kernel modifications are detailed in Appendix A. We originally tried to build our IDS within LTT, the Linux Trace Toolkit9—a tool which can output system calls, but we needed details which it did not provide such as parameters. However, LTT was useful to help us in understanding ways to extract information from the kernel. We began by trying to modify LTT, but then decided that we could directly modify the kernel allowing us both finer control and lower overhead. It is worth detailing further how we are capturing system calls. Within the native Linux kernel, a system call known as sys_execve is provided. This system call was convenient for us, because all system calls are routed through the sys_execve system call. So we are able to keep the IDS small and fast by looking in just one location for all system calls. This made it easy for us to pull out the system calls themselves. For each system call, the various parameters associated with the system call are stored in a struct referred to as ‘current’. So by simply referencing the current struct with the name of [9] 9 Yaghmour, K., and M. R. Dagenais, “Measuring and Characterizing System Behavior Using Kemel- Level Event Logging”, Proceedings of the 9’” USENIX Annual Technical Conference, 2000. 15 whatever variable you want to read, you can grab the current system call’s data. One may also use current->p_pptr to grab parent data. For example, one may reference the PID (Process ID) of the current process by looking at the value contained in: current->pid. As a further example, one may reference the parent’s PID by looking at: current->p_pptr->pid. This structure was quite convenient and made our modifications go much smoother. 1) Log system calls First, we needed to monitor the execution of system calls so we added a printk to the sys_execeveO function to identify the process and its parent. This one line logs an exec system call, prints out the Process ID, the Parent Process ID, the User ID, and the Parent User II). System calls which actually execute something will get logged here. 2) Log system call parameters Next, we added code to log the parameters to system calls. We added a printk to do_execveO. It’s worth noting that do_execveO is called by sys_execeveO and the parameters are easier to access in do_execve(). All we do here is print the system call parameters to our logfile in a format which is convenient to parse. The parameters will follow closely the original system calls. 16 3) buffer overflow check We now check for the passing of large buffers. At this point, flagging potential buffer overflows is unnecessary for detection since we capture the privilege-raising in our logging—we originally added code to eliminate the clutter of large buffers from our logs. Lindqvist and Porraslo determined a threshold for buffer size to be 400 after tracing 4 million events. If we find an argument larger than 400 characters, we flag the event as a potential buffer overflow. Otherwise, we print out each argument which was shipped to this system call. 4) Log file open calls Finally, we did the same thing here as we did for logging system calls, except that instead of printing information concerning execution, we print information concerning the opening of files. This bit of information helps us to determine what sort of exploit is running, be it a race condition, buffer overflow, or some other sort of exploit. As you can see, we made minimal modifications to the kernel. We strived to keep things simple so we both minimize impact upon performance and minimize the kernel [10] '0 Lindqvist, U. and RA. Porras. “Detecting computer and network misuse through the Production- Based Expert System Toolset (PBEST).” Proceedings of the 1999 Symposium on Security and Privacy, Oakland, California, May 1999. IEEE Computer Society. pp. 146-161 17 modifications. B. Detection The script we use for detection of attacks in the log files primarily searches for a command shell call with elevated privileges without prior authentication. This situation occurs in two cases, both of which are explained below. Case 1: If a command shell’s parent process has not opened the shadow file (i.e. no prior authentication) and the command shell process has greater privileges than the command shell’s parent process, then an attack has occurred. shell _pid = process id (PID) of command shell shell _ppid = PID of parent process of command shell shell_uid = privilege id of command shell shell _puid = priv. id of parent process of command shell shadow _pid = process id of last process to call shadow file if (shell _ppid != shadow _pid && shell_uid < shell _puid) attack=true; Case 2: If a command Shell’s parent process has not opened the shadow file and the command shell process and the command shell’s parent process have the same 18 privileges, then if the command shell’s parent process’s privileges have elevated since its initial execution, then an attack has occurred. We know this has occurred when no check to shadow is done and the PUID of this call is different from the UID listed in the parent call. As we are only looking for privileged shells, we only care if the UID has been lowered without any check to shadow. init_puid = privilege id of parent process of command shell at initial execution if (shell _ppid != shadow _pid && shell_uid == 0 && shell _puid == 0) { if (shell _puid < init_puid) attack=true; l9 Chapter 7 File Protection In addition to flagging privilege elevations, a major piece of our IDS involves the protection of various files deemed as 'critical' to security. For example, we would want to protect inetd config files, the shadow file, crond config files, etc, since root modifications of these files would allow an intruder to create a new account with root or admin privileges. When we speak of protection, the goal is to ensure that a normal user cannot write to these files, even through exploiting a privileged application (one which has setuid root). The concept is simple, but the details were complex with respect to this goal of protecting special files from privileged processes and daemons. Originally, we thought to monitor the shadow file by simply looking for writes to the shadow file itself. We don’t care about reads, as we are not concerned with the password file being read. With respect to writes, we were going to see if the shadow file was written only by a legitimate Linux command. For example, the command ‘adduser’ is one method to create a new account. When you create a new account, it makes sense that you will need to write something to the shadow file. Since normal users can’t write to the shadow file, you either have to exploit a program with root privileges or else be root yourself. Since we are monitoring for privilege elevation on the process side, we can assume that one will not be able to gain root access using an exploit. So this rules out a normal user becoming root without authenticating, leaving the method of exploiting a program with root—level privileges. 20 The original idea was fairly simple. We check to see if shadow is written to, then whatever is writing to shadow needs to be either a user session or else a program which authenticates the user and is allowed to write to shadow. It should be noted that we want to disallow users writing to shadow and only allow specific programs write-access to shadow. The problems begin to arise when the idea of using a cronjob to create new accounts. Now we have a case where an application which isn’t attached to a user session needs legitimate write access to shadow. This simple problem is what made the file protection portion of our IDS so complex. We end up with a problem of not being able to distinguish between an application legitimately changing a file and a user exploiting an application to change a file. An example we thought of to illustrate why this is such a large problem is the following. Most systems (hopefully all) would never want to allow a normal user write-access to the shadow file without some form of control. We should either check to make sure the user is only modifying their own entry within shadow (through an application, such as adduser or passwd). This part is easy, we simply restrict write access to shadow. We also allow users to use adduser or passwd to write shadow if they properly authenticate. No other application should touch shadow in a secure system. The problem arises when a system administrator wishes to have cron jobs add large batches of new users. So the administrator will feed a list of users and default passwords to a cron job which runs nightly / weekly. The problem is what happens if a malicious user exploits cron so that 21 this malicious user can write their own privileged cron jobs? How do we differentiate between legit root cron jobs and malicious cron jobs? While the possibility of this occurring is quite small, we still must consider it to have a truly secure system. Let us partition the problem into three levels of security. At the highest level (level 1), we allow nothing but the passwd application, or its eventual replacement, to touch the shadow file. Root cannot touch it, normal users carmot touch it, and no applications can touch it, except for passwd. This would result in a quite secure system, short of someone exploiting the passwd application. The IDS on the process side will catch any exploits of the passwd application as a failure to authenticate due to how passwd works. At a medium security setting (level 2), the IDS will allow root and passwd access to shadow, nothing else. At the lowest security setting (level 3), the IDS will allow root, passwd, and a list of specified applications to access shadow. While this 3rd level affords the greatest flexibility, we have reservations about allowing a large number of applications to access shadow, which should be quite restricted. Now, we examine the parser’s file monitoring functionality. In our current implementation, we are essentially checking for operations on the shadow, namely write operations. It is trivial to expand functionality to include protection for other files, as I will show shortly. We decided to protect the shadow file first and foremost because we admit our parser cannot detect compromised passwords. We are not concerned with reads to the shadow file. There are two reasons for this. First, in the course of normal operation of the OS, many reads are made to shadow for various reasons. Every login entails a read, processes which run at elevated privilege levels, and attempted logins all 22 check shadow for various reasons. Some of the above noted processes check shadow multiple times. Due to the number of processes which check shadow and the rate at which shadow is checked in the course of normal operation, we decided that it would reduce false alarms to focus on the writes as opposed to blanket coverage of the shadow file. Another reason for not monitoring reads to shadow is that the file system provides adequate protection of reads to shadow. For a regular user to read shadow they already have to have gained root access, which we should have detected earlier. While this IDS does stick to detecting edits to the ‘shadow’ file, it is trivial to modify the IDS to instead search for edits to the ‘passwd’ file. Should an administrator decide they don’t want to turn on password shadowing, they would need to change the parser file. All that needs to be done is change all instances of ‘shadow’ to ‘passwd’ in the parser. So instead of looking for, say, something without a TTY parent changing ‘shadow’, we would end up looking for something without a TTY parent changing ‘passwd’ instead. However, turning on password shadowing is highly recommended. Unless you are running some very old legacy systems which absolutely dictate no shadowing, turn password shadowing on. The extra hassle is definitely worth the added protection. Let’s examine in more detail the file monitoring from the perspective of protecting shadow. When the parser is first run, the user is asked for a filename to parse, then a level of security to parse with. Four levels of parsing are offered, with level I being the most secure and restrictive, while level 3 is the least secure and restrictive. At 23 level 1, the only way for the shadow file to be changed at all is to use the ‘passwd’ command. This rule applies for all users and processes, root included. At level 2, no non-root users may directly edit the shadow file. Anyone who is not root must use the ‘passwd’ command. Root users (or anyone who runs the ‘su’ command) may change shadow however they feel. Note that at level 2 security, cron jobs may not touch the shadow file for writing. At level 3, any root-level user can directly edit shadow, and now specific cron jobs may directly edit shadow. We will allow a cron job to write to shadow only if this cronjob is run from either: /etc/cron.* or else /etc/rc*. We will also not allow a cron job to write anything to either: /etc/cron."‘ or /etc/rc*. We still enforce that normal (non-root) users must use the ‘passwd’ command to edit shadow. At level 4, we only enforce that normal users can’t directly edit shadow. We allow all root-level users and cron-jobs to freely edit shadow. The reason for the four levels of security is flexibility. We believe that instances exist where system administrators would have a use for each level. Naturally, for greatest security, we recommend everyone run with security level 1 and force administrators to use the ‘passwd’ command to change user passwords. Accounts should be individually created with adduser for a decent level of security. However, when adding a large number of users, automation would be a necessity. For this reason, levels 2 and 3 have been added, to allow a system administrator the ability to add users with a cron job. If the user selects they want to parse the logfiles with security level 1 in mind, the parser looks at all open system calls and finds any call which opens either ‘/etc/shadow’ 24 or else ‘shadow’. The parser then takes the ‘flags’ value and converts it from decimal to binary. If the last two bits of this ‘flags’ variable are not both zero, a write has occurred. We then check to see if the UID is less than 500 and if the last two bits of ‘flags’ are zero. A UID of less than 500 means that this UID is privileged. Typically a UID of 500 or above is a “non-privileged” UID. For example, root has a UID of 0. If the UID is greater than 500, or the last two bits of ‘flags’ are zero, we skip this call and go onto the next call. Otherwise, we check to see if the PII) of this open call is the same as the PID of the adduser command or passwd command (if either of those commands were executed prior to this write to shadow). If the PID for this open shadow write is different than the PID of the adduser and the passwd commands, we ring the alarm. To clear up potential confusion, we are only checking for UID’s under 500. We can assume that the file system will not allow any user with a non-root UID to edit the shadow file. A bit of administrative work had to be done for the ‘magic’ of the parser to detect any level-1 abuses. As we parse the logfile, we also are looking for exec calls. If we detect an exec call with either ‘/usr/bin/passwd’ or else ‘/usr/sbin/adduser’, we save the current value of the PID. This symbolizes that the current PID is either linked directly to the ‘passwd’ or the ‘adduser’ commands, both of which are allowed to change the shadow file. If one wants to allow additional commands, we later describe how to add commands to the parser which are allowed to change the shadow file. The process itself involves adding three or four lines of code to the parser and running the logfile back through the newly compiled parser. 25 For level 2 parsing, the parser will look at all open system calls and searches for any calls which open either ‘/etc/shadow’ or ‘shadow’. The parser then checks to see if the last two bits of the ‘flags’ variable are both zero. If both bits are not zero, the parser then checks to see if the PID or the PPID is linked to a tty session. If neither the PID nor the PPID is directly linked to a tty session, an alarm is raised. A bit of extra work is required to determine which system calls are linked to a tty / console session. The difficulty with determining which system calls are related to a console is that many times a user will open other screens / shells. Suppose that a user logs in, then runs ‘xterm’. In this case, we would have a shell which isn’t hooked to a TTY session, it’s just a plain console session. What happens is that we need to use a level of indirection to successfully find console sessions. What I did was to look at each Open call and find anything which opens a file called .bash_history. As soon as we detect an open to .bash_history, the pid of this cpen call is recorded and a global variable is incremented. Then to determine if a write to shadow is linked to a console session, we just loop through all of the values we recorded for .bash_history opens. One may wonder why a malicious user couldn’t just make a file called .bash_history, open that, then write to shadow. This will not pass the parser’s tests as the PID will not match up. As an example, suppose a user runs the command: ‘echo .bash_history >> shadow’. Then the logfile would show .bash_history being opened with say PID 1974, PPID 804 and shadow being opened with PID 1975, PPID 804. However, when .bash_history is opened as part of logging into a console session, the PID is the same as the rest of the login process. Say the PID of our login process is 809, when 26 .bash_history is opened, we will record the PID as 809. Next, when the user tries to open shadow for a write, the PID may be 1705, but the PPID will be 809. This is permitted by our parser as we are only trying to prevent writes which are not linked to a console session from accessing shadow. Because of this behavior, it is acceptable and sufficient to only check for the presence of .bash_history having been opened to know the PID belongs to a console / tty session. Another important concept is how we can lump local console logins and remote logins together and distinguish them as a group from, say a cronjob. Whenever a user logs into a bash shell, the .bash_history file is accessed, regardless of how they access the shell. However, the .bash_history file is only accessed if the login is interactive. We should keep in mind that even if a malicious user writes a cronjob which accesses .bash_history then writes to shadow, the parser will still catch them due the PID / PPII) issue discussed earlier. Level 3 parsing shares much of the code that level 2 parsing uses. Level 3 parsing is split into two quite distinct pieces. The first piece looks for writes to anything in /etc/cron.* or /etc/rc*. The second piece looks for cronjob writes to shadow which were not run from /etc/cron.* nor /etc/rc*. With respect to the first piece, we look at each open call. If the file being opened is either “/etc/rc*” or “/etc/cron.*”, we then check to see if this open call is a write. Again we check the last two bits and see if either is non-zero to determine if a write is 27 taking place. If we are writing to either /etc/rc* or /etc/cron.*, we then check to see if the PID or PPID was used to open .bash_history. If the write P11) is the same as the PID or the PPID for the open to .bash_history, then we know this write to /etc/rc* or letc/cron.‘ is being done by someone on console. Console access is permissible and we don’t ring the alarm. However, if this write is not hooked directly to a console, we ring the alarm. We use the same logic as used in level 2 parsing to determine if the write is hooked to a console. The next part of level 3 parsing is determining if a write to shadow is done by a cronjob. If so, we then need to ensure that the cronjob was run from within /etc/rc* or /etc/cron.*. The logic here is that we are not allowing cron to elevate itself. If all cronjobs which write to shadow must read from a specific location and we do not allow a cronjob to ever write to this specific location, then cron cannot elevate itself. Someone with established root access must elevate privileges. We accomplish this detection by looking for any open calls to any of the following locations: /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.d/, /etc/cron.weekly/, /etc/cron.monthly/. If we see an open system call to any of these locations, we record the PID used. What we are doing here is trying to see where a cronjob is running from. If we detect a write to shadow which is not hooked to a console shell, we then look for the write to be hooked to a cronjob. If the PID or PPID wasn’t used to open something from within one of our cron directories listed above, we can conclude something is changing shadow, it’s not a user, and it’s not a valid cronjob. 28 As mentioned before, it’s trivial to add new shadow-editing commands which the parser will allow. To do so, follow the directions below. To add a new command which is allowed to edit the shadow file: Inside the parser, find the part which parses exec calls. Look for: if(strstr(app.c_str(),"/usr/sbin/adduser”)!=NULL) { adduser_pid = pid; To add a new command, just copy this if-statement and paste it directly below. Change the ‘/usr/sbin/adduser’ to whichever command you want to allow. You don’t have to enforce the strict path, but it’s a good idea to. Otherwise, a malicious user could create a new program with the same name as one of your ‘allowable’ programs and get past the IDS. You also need to create a new variable and offer it a distinctive name. Keep in mind it would be advisable to modify this program so that an array of PID’s is used instead of individual variables should the user decide to allow a number of commands the ability to edit shadow. 29 Next, you need to go into the open command parser and find the level 1 security check. Then, look for the line: If((pid != adduser_pid) && (pid != pwd_pid)) { To this if-statement, you need to check the pid against your new variable. String another && statement onto the above. If the PID != the new program’s pid and the PII) != pwd or adduser PID, then we should ring the alarm. 30 Chapter 8 Exploits In this section we describe the set of exploits selected to test our IDS. The set is not all inclusive, but it is representative of important types of host exploits. The set is not yet complete—it is limited by what we have been able to test up to the deadline. The tests include the following types 1. Buffer Overflows 2. SetUID / SetGID exploits 3. Race Conditions We feel that these three types of attacks cover the most popular methods of exploiting systems. We have provided the name of the exploit, its type (buffer overflow, etc), how it works, and its special characteristics for detection. We would like to direct the reader to appendix B, if they would like more information about any of these exploits. Appendix B contains log subsequences of the exploit captures, along with a look at how our IDS reacts to each exploit. A. Sendmail 8.11.x exploit (aka. SXP), a Bufler Overflow. We were able to gain a root shell with the generic intrusion script. This exploit takes advantage of a weakness in how Sendmail’s default setup works. When Sendmail is installed, it is usually installed with set-uid root: resulting in the Sendmail process 31 having root-privileges. The exploit runs Sendmail to make use of the setuid-bit. The error is actually due to the comparison between a signed and an unsigned integer when checking data passed to Sendmail on the command line. A high unsigned value is interpreted as a negative signed value. We detect this exploit by noticing that: a) We never call shadow, just make a call to passwd b) Our shell is spawned with a lower UID than its parent From these two items, we know that no authentication took place, yet we were passed a shell with elevated privileges. These characteristics indicate an attack. B. Redhat Dump exploit, a buffer overflow. Redhat version 6.2 was shipped with an exploitable tool called 'dump'. Dump examines files in a file system, determines which ones need to be backed up, and copies those files to a specified disk or tape. The buffer overflow allows users to execute arbitrary commands with root privileges through dump. One simply needs to send the dump command a script which tells dump to setuid O on a shell. The result is a root shell which can be spawned merely by running the file which was setuid to root. We detect this exploit by noticing that: a) We never call shadow; just make a call to passwd b) Our shell is spawned with a lower UID than its parent From these two items, we know that no authentication took place, yet we were passed a 32 shell with elevated privileges. C. Xperl.sh exploit, a SetUID exploit. The Xperl.sh attack exploits a setuid issue within SuidPerl. SuidPerl is a Perl interpreter for suid Perl scripts and comes as part of the Perl package. The suidPerl program performs a number of checks to make sure it cannot be tricked into executing a Perl script with root privileges when its not suid root. If one of these checks fails, the program will send a message to root. The name of the script to execute is inserted into the message, and is taken from the program’s argument list. SuidPerl then executes /bin/mail to send the message to root. It sends this message without cleaning the environment or dropping root privileges. The /bin/mail program interprets the sequence "~!" as an escape sequence to start a shell and execute commands. A malicious user could craft a file with an escape sequence and commands embedded in the file name. Then the user just needs to execute SuidPerl so that one of the security checks fails. SuidPerl will send a message to root with the escape sequence embedded in the message. This message will cause /bin/mail to start a root shell and execute whatever commands were sent. We detect this exploit by noticing that: a) no call is made to shadow b) Our shell says the parent UID is 0, yet the parent UID was 500. So we are passed a shell with elevated privileges, even though we never authenticated. 33 D. The ptrace exploit, a race condition. Ptrace exploits a vulnerability in Linux kernels prior to versions 2.4.9. By predicting a child processes call to sleep() within execve(), a malicious user can use the ptrace exploit to seize control over the child process. If the child process has setuid to root, the malicious user can execute arbitrary code with elevated privileges. We detect this exploit by noticing that: a) No call to shadow is made b) Our shell has a lower UID than its parent, yet no authentication took place. E. The ftp exploit (aka ftpexp), a bufler overflow. This exploit seems to be a standard buffer exploit, sending a large string of characters to the ftp server with shellcode at the end. The exploit also makes some attempts to get the proper return address. We detect this exploit by noticing that: a) No call to shadow is made b) The argument length is greater than 400 characters. This exploit caused some interesting problems which will be eliminated when we finalize our IDS implementation. This exploit broke the built-in logging capabilities of Redhat. After the arguments got sufficiently long, the message file had nothing written to it, save messages about users logging in and out. No more system calls were written. So 34 we never detected a shell being spawned because the log files never recorded that happening. When we implement this inside the kernel, we will parse arguments as they are processed, so this issue will not be a bother anymore. Upon further inspection, we noticed that the shell was indeed being spawned, with a UID higher than its parent, yet no authentication took place. We still caught this exploit by just looking for any large arguments. F. The prlnx.sh exploit, SetUID This exploit works by taking advantage of a vulnerability with SetUID. It targets the same vulnerability with Sendmail as discussed for exploit #1 (sxp). This exploit operates slightly differently than sxp, so it is worthwhile to discuss it here. The method is still the same: trick Sendmail into running a script which spawns a privileged account. We detect this exploit by noticing that: a) no call is made to shadow b) The shell call has a UID of 0 and a PUID of 500. From these two events, we again see that a privileged shell was given without authentication. After looking over the description of each exploit and how we detected it, one may ask why we just do not look for lack of authentication while logging in. Why not just detect a missing shadow call and be good with that? In detecting only shadow calls and spawned shells, we will flag a large amount of legitimate activity as an attack. It is 35 perfectly normal to spawn a shell with the same access level as before without authenticating. 36 Chapter 9 Limitations Earlier we listed classes of attacks which we do not address—many are best handled elsewhere in the defensive hierarchy. However, within our target intrusions what are the potential problems? Since we have not formally proved complete security within our target domain, and do not yet have a sufficiently robust test set, unforeseen problems could exist (even though we believe them to be unlikely). One sticky issue is that we are looking for “bad” behavior which means that “bad” must be defined, and a generic, universally accepted definition does not appear to exist. Privilege-elevation appears to be generally understood and, as a result, our detection of it appears to be robust. F ile- modification vulnerabilities are less well defined and our detection is less mature so it is a better candidate for problems. For example, it may be fine for root to change something in the shadow file or add a line to a configuration file, but it may be bad for a regular user to add anything to these files. If the security protocol is well-defined, we believe that we can detect improper behavior, but protocols are often not well defined so demonstrating success is problematical. For the time being, we allow the administrator (root) to do whatever they wish, while not allowing a standard user to access a privileged shell in any fashion outside of using accepted authentication mechanisms (su, logging in as root, etc). We also allow the administrator (root) to edit whichever files they wish, but do not allow standard users to edit certain files at all. We believe that this choice fits most notions of security, as once a malicious user gets privileged access (e.g. root), the IDS has already failed. 37 Chapter 10 Where our scheme fits in the world of IDS Intrusion Detection Systems (IDS) and host-based systems in particular are not new, but have been evolving rapidly. Allen et al.8 provide an excellent overview of the state of IDS in the year 2000. Here, we will focus on three host-based, kernel-level IDS which consider system calls, followed by a briefer look at systems we believe are less related. First, consider SRI’s comprehensive EMERALD packagell which has evolved over many years. SR1 describes EMERALD as “a distributed scalable tool suite for tracking malicious activity through and across large networks.” It includes attack isolation and automated response as well as distributed high-volume event-correlation. The EMERALD component most related to our work is eXpert-BSMZ: a host-based IDS for Sun Solaris. The eXpert-BSM component is a real-time expert system which analyzes the audit trails generated by the Solaris BSM. As an expert system it uses rules and ensures that data conforms to these rules. If a deviation is detected, an alarm is raised. To determine if a rule has been violated, the product looks at system calls generated by BSM. It compares runs of system calls against its rule set. SR1 claims a high detection rate coupled with a low level of false positives—the combination of system data with an expert system is a sound approach. Our system differs from the [l l] ” Porras, P. A. and RC. Neumann. “EMERALD: Event Monitoring Enabling Responses Anomalous Live Disturbances.” Proceedings of the Nineteenth National Computer Security Conference, pages 353--365, Baltimore, Maryland, 22-25 October 1997. NIST/NCSC 38 eXpert-BSM component of EMERALD by looking not only at the system calls, but also at parameters passed along with these system calls and process ID’s. By looking at the parameters and PID’s and focusing on the lowest common denominator of attacks, our rich data set improves precision without the complexity of the expert system. We further differ ourselves from EMERALD by profiling generic privilege elevation rather than profiling individual attacks. In looking at a general privilege elevation, we can build a more accurate IDS with fewer false positives and better accommodation of new attacks. Another IDS which considers system calls began with work by Hofrneyr & Forrest, et al.'. A number of subsequent studies have used their system-call data as the basis for a variety of system-trace log analysis, but with little improvement over the original work. The original work looked at short sequences of system calls, e.g. 5, and compared these sequences against a database containing profiles of normal behavior. Their observation was that patterns of calls looked different between normal usage and attacks. If system behavior deviates significantly from normal behavior, an alarm is raised. They claim few false positives, while being able to quickly catch all intrusions tested. However, simple estimates indicate that even their low false-positive rate will generate an unacceptable number of false alarms on a running system. The difficulty appears to be building realistic profiles, especially for large systems. Our proposed system differs by examining not only the system calls themselves, but also the parameters and PID’s. Again, we further differentiate ourselves by profiling a generic privilege elevation instead of profiling individual attacks. 39 The final kemel-level IDS related to our work is systrace3. Systrace differs by placing code in a system-call "sandbox" so inappropriate system calls cannot be made within an application. Policies for applications are developed by profiling normal usage to determine the system calls which should be used, and then other calls are prevented. For example, if a shell should not be spawned during an FTP session, it will be prevented. The approach even works for binaries whose details may be unknown. Its advantage is that it can prevent certain types of intrusions. Systrace's approach is orthogonal to our work since they analyze code known to run on a machine and prevent it from doing what it should not do, i.e. put it in a sandbox. Time will tell whether people find sandboxing or monitoring to be more useful-maybe a combination will be best. Another difference is our ability to monitor and protect particular files. Other products In the course of performing the literature survey and associated research, we came across several other products which attempt to catch intrusions by looking at system calls. While each one of these methodologies and software packages has its merits, we believe our system differs critically from these other systems. One of the major differences between our IDS and the other systems is that we are able to detect if an intrusion has occurred by looking simply at whether or not authentication takes place before a root shell is granted. Many of the other systems are profiling individual attacks, require a ‘learning’ phase in order to catch much of anything. This profiling is what breaks most other IDS’. Our IDS is different because we profile a generic privilege elevation. This enables the IDS to catch future, undefined attacks. Due to this generic profiling, our IDS 40 generates fewer false positives than other IDS’. While other IDS’ surely exist which we have not discovered at this time, we have found a few other products which warrant discussion. One of the IDS’s which we examined is proposed by K0 and Fink, et a1”. We have found that the proposed HDS, while similar to our proposed IDS, still does profiling. The authors mention that they look for ways which privileged programs misuse their privileges. This implies that a list of privileges which are allowable must be provided. This equates to profiling as the initial list of privileges must be populated. This model suffers from the same issues as other profile-based IDS, namely what happens if the profile is wrong or if the working habits of users changes? This just looks like profiling, only this uses a special, invented language. We somehow describe "normalcy", then ring an alarm if we deviate. While the idea is novel, it still requires a person to "encode" normal behavior for the system. We feel that our IDS differs from “Execution Monitoring” by not requiring anybody to enter normal behavior. We know that normal behavior doesn’t entail gaining system resources without authenticating. Next, we reviewed the IDS proposed by Kumar and Spafford, et a113 . This IDS seems to be a profiling-based IDS in a similar vein as the others. This IDS works by defining a start and end state, then looking at the paths between each of these states. '2 Ko, C., Fink, G., and Levitt, K., “Automated Detection of Vulnerabilities in Privileged Programs by Execution Monitoring. ” Proceedings of the 10th Annual Computer Security Applications Conference, pages 134-144, Orlando, FL, 1994. '3 Kumar, S., Spafford, E., “A Pattern Matching Model for Misuse Intrusion Detection” Proceedings of the 17th National Computer Security Conference, Pages 11-21, 1994. 41 They use a variation of state-transition analysis to determine a signature of a running process. The IDS then compares this generated signature with the database of known bad signatures. An alarm is rung if the signature finds a match. This IDS has the usual set of problems associated with profiling-based systems, as described above. Our IDS has also been compared to the Program-Semantics Aware Intrusion 114,15 . The associated Detection scheme (PAID), written by Chiueh and Hsu, et a document describes how PAID extracts system call runs of process runs and compares these system call patterns against a database of known system call patterns to detect intrusions. When something runs, PAH) examines the system calls and compares them to a list of allowable system calls. If the system call of the running process isn’t in the list of allowable system calls, the process is halted. As the PAID system again uses a form of profiling, we find that our IDS differs significantly from PAII). Some of the reviewers have also mentioned that several of the “secure” Linux releases provide the same protection as our IDS. We have decided to investigate this further and have discovered that, while some secure Linux releases do provide important security properties, no existing version of Linux affords the protection which our IDS provides. We would like to explore two particular products in depth; the LIDS release” “ Chiueh, T., Hsu, F "RAD: A Compile-time Solution to Bujfer Overflow Attacks," International Conference on Distributed Computing Systems (ICDCS), Phoenix, Arizona, USA, April 2001. '5 Hsu, F., " The Principle, Attack Patterns, and Defense Methods of Bufler Overflow A ttacks," RPE I"312011. October 2000. '6 “Linux Intrusion Detection System (LIDS)”, http://www. lids. org/index.html 42 and SE Linux”. First up, we would like to explore the LIDS project a bit. LIDS provides protection of specific files, protection of specific processes (nobody can kill specific processes), finer granulated ACL’s, kernel security alerts, port scanner detection, as well as a host of other protections. We have found that LIDS protects some very specific issues with Linux. Of the many features which it provides, one in specific is the option to limit the transfer of a User H) (UID) from process to process. Our IDS differs from LIDS in two fundamental ways. First, we are looking at individual system calls, not functions as LIDS does. Second, our IDS is simpler than LIDS as we are only checking for non- root access on a small collection of files and checking for shell without authentication, rather than checking for the wide collection of transgressions, as LIDS does. Last, I would like to examine SE Linux. SE Linux (or Security-Enhanced Linux) is a project out of the NSA. SE Linux works by enforcing mandatory access control policies which ensure that users possess the smallest set of capabilities they can possibly have and still perform their task. We feel that SE Linux is a fine product, yet it doesn’t address the core issue that our IDS addresses. Our IDS addresses the issue of a user gaining privileges without authenticating themselves. SE Linux works by limiting what everyone can do. It doesn’t actually address the fundamental issue that unauthorized users shouldn’t be able to gain access to a system. '7 “Security-Enhanced Linux”, http://www.nsa.gov/selinux/ 43 Next up, I would like to address a system called St Jude. The St Jude system bills itself as a "Kernel-based IDS that achieves a level of intrusion resiliency for root- privilege escalation intrusions on Linux systems by monitoring privilege transitions." This certainly sounds close to what we aim to accomplish with our IDS, so we figured it warranted a closer look. The St Jude system is highlighted in a paper released by Tim Lawless titled 0n Intrusion Resiliency/8. We have examined both the paper and the actual source code from the application. The paper claims that St Jude can identify root privilege escalation attacks of "a known and unknown type". The paper also claims that St Jude can recognize and prevent attacks from both internal and external sources. The St Jude system works by recognizing an attack "at the last possible moment prior to the protected system being transitioned into a root-compromised system". System calls which are utilized for privilege escalation are monitored by St Jude. At the heart of the St Jude IDS is the St Jude Model. The model works by associating a set of permissible transitions to each process operating with elevated privileges. Each privileged process can only perform this set of transitions. If an unprivileged process tries to gain access through a process running with elevated privileges, the set of system calls executed will be different than the set executed for legitimate access. As a further limitation of the system, the set of allowable transitions is only allowed to shrink, not expand. '8 Lawless, T., “On Intrusion Resiliency”, [tr/Jlg’i'pmItem/«nun cunt/jury I, 1:111): Dilgfilgl 1:13:11, Packet Storm Security, February 2002. 44 Essentially the St Jude model works as a rule-based anomaly detection, profiling in a word. A rule base is required for the system to work, as is a 'profiling' phase. The rules will need to be changed as the system configuration or user restrictions change. Once the rule base is created, anything which deviates from the norm will be flagged as an intrusion. The paper claims that slight modifications to the kernel, such as patches or new applications, will not affect the performance of the IDS. I should note that the St Jude model was initially developed for a Solaris-based system. We next examined the source code, and it seems the authors have abandoned the project. No source code updates have occurred for over a year, even though comments throughout the code pointed to the fact that certain segments were kluged together and needed some serious revisions. The source code is offered for both Linux-based systems and Solaris-based systems. The source included a lot of GNU code straight from existing Linux kernels. The authors seem to put a wrapper around all exec calls. Looking first at this execve_wrapper, I noticed that they first check to see if the process is privileged. If it's not, they let the process execute. If the process is privileged, they check to see if it's ok to execute. A call to a function called check_priv_record takes place. This function checks a privileged structure for existence of a flag. If it is decided the system call is allowed to execute, St Jude updates records for this system call and adds to a list of commands they're keeping track of. As a side note, I can see this process taking a lot of time, as the record keeping is neither simple nor straight-forward. 45 As noted earlier, the St Jude IDS must first operate in a "learning mode", which is designed to build the rule base. While in leaming mode, the system identifies normal operation of the system and builds rules based upon this observed behavior. Afier compiling the rule base, the module will be started in normal mode, where St Jude will detect any variance from the allowable rule set. As with other systems which are based on profiling, errors can creep in if an intrusion occurs during the learning mode. Problems would also arise if user behavior changed significantly after the learning takes place. Lets say we don't allow users to run sendmail during the learning process. Later we allow users to invoke sendmail without authenticating into anything other than their user accounts. Most profiling IDS would view this behavior as a potential intrusion, opening the system to false positives. What's worse is that if the administrator tells St Jude that normal users running sendmail is fine and a sendmail exploit gets used, the IDS may not detect the intrusion. These are some reasons why we decided to stay away from a profiling-based IDS. I'll cover more of the differences at a later time. The comments in the source code provide insight. For example, it's noted in comments that attacks against the St Jude module itself may be successful. In fact, early versions didn't allow the loading and unloading of modules. To me, it seems that crippling the OS to such a degree would make the IDS fairly useless. The ability to load modules is a core function of most Unix-based operating systems. The newer versions of St Jude include an application known as St Michael which does integrity checking prior to loading or unloading any modules. St Michael monitors the kernel and periodically 46 validates its integrity and prevents the loading and unloading of modules. To me, it still seems one would be able to attack the module directly, especially if it wraps the exec system call in Linux. As we'll see later, St Jude also puts a wrapper around fork, pointing to a possible DoS attack on the IDS itself. As a side note, we feel that our IDS does not have any of the problems addressed above about the St Jude package. For example, we have alluded to the fact that wrapping the exec system call isn’t a good idea. We don’t wrap any system calls, we actually have added code directly to the system calls themselves. Since the OS is already doing the work, very minimal overhead is added. Technically one could overload our IDS, but the system would be crippled in other, more serious ways by that point. If our IDS is overloaded, the core functionality of the kernel is also overloaded. We do no checks on the loading and unloading of modules directly. If someone loads a module which writes to the shadow file, we will not allow this unless they first authenticate as root. Thus there is no need to prevent the loading and unloading of modules. It’s also worthy to note that we never consider wrapping fork. To us, this seems to be a bad idea. St Jude also marks a set of files as 'immutable'. In our opinion, this does get the job done but doesn't protect against all forms of intrusions. By making a file immutable, you are not allowing the file to be modified or replaced on disk. The list with St Jude is designed to protect all files used for boot-up. St Michael provides the immutable functionality. With the files set as immutable, not even root can change them. I see issues with designing your system so that root is blocked out. In our opinion, if you 47 ensure that root privileges can't be exploited, then you don't need to protect the system from root. As long as you keep normal users and unauthenticated remote users out of root, you can leave root alone. Some of the files which St Jude monitors are as follows: lusr/local/sbin/sshd, /usr/sbin/atd, /usr/sbin/crond, /usr/sbin/rpc.nfsd, /usr/sbin/rpc.mountd, /sbin/rpc.statd, /usr/sbin/syslogd, /usr/sbin/pppd, /sbin/portmap. We wonder where letc/shadow and hosts.allow / hosts.deny are? It seems to me that one would want to protect the shadow file against unauthorized access. Once a hash is illegally injected into the shadow file, no IDS will be able to protect you. Messing around with hosts.allow and hosts.deny could also render your IDS useless as your authentication rules would change. I would also recommend protecting IPtables to keep your firewall rules safe. Next, I'd like to look at how St Jude handles forks. An interesting point is the following comment was taken directly from the source: "printk("(StJude) sj_fork: Brace yourself, we are going to crash!\n");". To me, it seems redundant to handle both forks and wrapping the execve system call. This would also seem to create a large amount of unnecessary overhead. With forks, they check to see if the process is privileged. If it is, they then check to see if the process has a privilege record. If the process is privileged and has no privilege record, the user is elevating their privileges. They assume this to be a setuid program / hack. They then generate a privilege record. If a privilege record exists, then they generate a privilege record based upon the parents’ privilege level. In the source code, they talk about only setuid exploits. I would assume that their 48 application can catch other forms of exploits, but they only discuss setuid's. Another point with respect to privileges they make is that the parent’s privileges must be a superset of the child’s privileges. I do wonder how they caught someone legitimately elevating their privileges with a command such as su. If the parent has no privileges, they have no restrictions on what the child can have. This almost appears counter- intuitive. If a process has no privilege level (guest-access), we don't put any restrictions on what it's children can have with respect to privilege. With that look at the inner-workings of St Jude, let us contrast our IDS with the St Jude package. One of the most obvious differences which I mentioned earlier is that we are not using any sort of profiling to catch intrusions. I will admit that profiling works with stable systems. However, there is room for error. If you take a several-hour-long profile of your system on a standard week-day, you could be profiling while an exploit is occurring. Your IDS would never pick it up later. The bad part here is that more than just one exploit could get through. Since we are looking at system calls, we could let through an entire class of exploits just by profiling when a single exploit is occurring. If you profile with no users on your system (as to not get any exploits in the profile), then you will not have an accurate profile when the users get back on. Another drawback to profiling is if your users change their behavior suddenly. Say a new corporate policy is instituted forcing all employees to use Elm to check their email, as opposed to forcing everyone to use Outlook Express. The administrators must either take a new profile, or else they run the risk of missing intrusions and flagging normal user behavior as malicious. 49 Other differences between our IDS and the St Jude package is that we are not doing any wrapping of legitimate system calls. We are parsing the system calls before they are processed, not as they are processed. This has several advantages, namely that if our IDS breaks, and the system as a whole will continue to operate fine. Albeit your IDS capabilities will be diminished, your system will continue to function. For any system which requires near 100% uptime, I can see this functionality being demanded. Another disadvantage of wrapping the exec system call is you will generate a lot more overhead than using a simple if-statement to filter out what you don't want. For a half-hour run of our IDS, it takes only 1.5 seconds to parse all of the system calls. This is truly negligible overhead. I'm not sure of the statistics for St Jude, but I've heard of other wrapper-based IDS taking in the neighborhood of 5% to 10% of system resources just to run. Our IDS focuses only on elevation of privileges without much record keeping or overhead needed. We don't require any complex structures to save system state information as very little state information is even kept. It seems to me that the St Jude package has a bit more complexity than may be required. They seem to be trying to classify different types of exploits which work in the same fashion; namely circumventing the authentication mechanism for the computer. 50 Chapter 11 What’s left to do A lot of work remains on this project. Our “to do” list helps indicate the state of the project: 1. Test More: Test a wider range of attacks (currently we have 8) and run the IDS under normal usage for an extended period of time to make our test for false positives more rigorous. 2. Test in the Wild: Install our IDS in a honeynet and see how it handles attacks “in the wild”. If we can detect new intrusions without updating our IDS, we will have further validation of our methods. 3. Windows: We plan to craft a Windows version of our IDS. The open model of Linux made it an obvious starting point. Microsoft’s assistance will be sought for a Windows implementation. Lack of a hierarchy with respect to system calls and a different kernel structure have the potential to make our method difficult to implement. However, informal discussions with former students now within Microsoft indicate that our approach can be ported. 4. Handle shell renaming: currently we key on specific names for recognizing shells, but we have observed that shell creation has an identifiable signature so we believe that we will be able to handle renaming. 5. Handle authentication mechanism changes: currently, we look for a call to be made to /etc/shadow to signal that the user has authenticated. We have observed that authentication has an identifiable signature as well, so we can handle any attempts to 51 'trick' our IDS into thinking a malicious user has authenticated. 52 APPENDICES 53 APPENDIX A Source code 54 Al — parser pseudo code - File parsing Ask for filename and security level to parse with Check for existence of file If file doesn’t exist, exit Else, read in file and populate variables Scan through entire logfile line-by-line For each line in logfile: If (system_call) = sys_access Grab line and parse it into manageable variables If this PPII) = any cronjob, store the PH) and the file being accessed in array If (system_call) = open call Grab line and parse it into manageable variables If the file being opened = any cronjob, store the PID into a global If ( file being accessed = “shadow” ) Store PID of shadow If ( file being accessed = “.bash_history” ) Store PII) into array If ( file being accessed = “nshadow”) If ((( we haven’t seen the ‘passwd’ command ) and ( if our User II) > 0)) or (( if the current PID != the passwd PID) and (the User II) > 0))) If ((( we haven’t seen the ‘adduser’ command ) and ( if our UID > 0)) or ((if the current PII) != the adduser PII) ) and (UID > 0))) Ring alarm Else Reset the passwd PID and adduser PII) If ( the file being opened resides in “/etc/cron.*” or /etc/rc*” ) If our security level is 3 If we are writing to the file if this open call is being done by a process (not a person) ring alarm (cronjob writing another cronjob) If we are writing to “letc/shadow” or “shadow” Record the PID 55 If our security level is 1 and our UID < 500 If we are writing to shadow Ring the alarm (someone writing to shadow) If our security level is 2 If we are writing to shadow If this write is being done by a process Ring alarm (cronjob writing to shadow If our security level is 3 If we are writing to shadow If this write is done by a process which is not a cronjob Ring alarm (something other than cronjob writing shadow) If (system_call) = exec call If this execute was done by a cronjob, record the P11) and PPII) in an array If the execute is operating on the “passwd” instruction, record the P11) If the execute is operating on the “adduser” instruction, record the P11) 56 A2 — Parser Pseudocode - Process parsing Ask for filename and security level to parse with Check for existence of file If file doesn’t exist, exit Else, read in file and populate variables Scan through entire logfile line-by-line For each line in logfile: If ( system_call ) = open call If we are opening “/etc/shadow” or “shadow” Record the PID If (system_call ) = exec call If we are executing a shell (bash or otherwise) If (( shell Parent PID != shadow PII) ) and ( shell PUII) > shell UII) = 0 )) Ring alarm If (( shell PPII) != shadow PID) and (shell UID = 0 ) and (shell PUID = 0)) If ( shell PUID < parent of shell PUII) ) Ring alarm If ( length of entire command >= 275 ) Ring alarm If (length of any argument > 400 ) Ring alarm If (bash_history found) Reset all variables 57 A3 - System Logger Modifications Listed below are the modifications which we have made to the Linux system logger. Note that these modifications will change syntactically but not logically with the implementation of the real—time component. // In file: /usr/src/linux-2.4.18-3/fs/open.c asmlinkage long sys_access(const char * filename, int mode) { /* Clear the capabilities if we switch to a non-root user */ if (current->uid) cap_clear(current->cap_effective); else current—>cap_effective = current—>cap_permitted; // These three printk's added. printk("sys_access: Filename: %s, mode: %i, UID: %i, GID: %i,", filename, mode, current->uid, current- >gid); printk(" PID: %i, PPID: %i, UID: %i, PUID: %i,", current->pid, current->p_pptr—>pid, current—>uid, current->p_pptr->uid); printk(" euid: %i, suid: %i, fsuid: %i, egid: %i, sgid: %i, fsgid: %i\n", current->euid, current- >suid, current->fsuid, current->egid, current—>sgid, current->fsgid); res = user_path_walk(filename, &nd); if (lres) { res = permission(nd.dentry->d_inode, mode); /* SuS v2 requires we report a read only £3 too * / if(lres && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) && Ispecial_file(nd.dentry->d_inode->i_mode)) res = -EROFS; 58 path_release(&nd); asmlinkage long sys_open(const char * filename, int flags, int mode) { char * tmp; int fd, error; // These three printk's added. printk("open: %s, PID: %i, PPID: %i, UID: %i, PUID: %i,", filename, current->pid, current->p_pptr->pid, current->uid, current->p_pptr->uid); printk(" flags: %i, mode: %i,", flags, mode); printk(" euid: %i, suid: %i, fsuid: %i, egid: %i, sgid: %i, fsgid: %i\n", current->euid, current- >suid, current->fsuid, current->egid, current->sgid, current->fsgid); // In file: /usr/src/linux-2.4.18- 3/arch/i386/kerne1/process.c asmlinkage int sys_execve(struct pt_regs regs) { filename = getname((char *) regs.ebx); error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; // Added these two printk's printk("exec: %s, PID: %i, PPID: %i, UID: %i, PUID: %i,", filename, current—>pid, current->p_pptr->pid, current->uid, current->p_pptr->uid); printk(" euid: %i, suid: %i, fsuid: %i, egid: %i, sgid: %i, fsgid: %i\n", current->euid, current- >suid, current->fsuid, current->egid, current->sgid, current->fsgid); 59 **) } error = do_execve(filename, (char **) regs.ecx, (char regs.edx, ®s); // In file: /usr/src/linux-2.4.18-3/fs/exec.c int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs) { O) struct linux_binprm bprm; struct file *file; int retval; // Added this variable int j; file = open_exec(filename); if ((bprm.argc = count(argv, bprm.p / sizeof(void *))) { allow_write_access(file); fput(file); return bprm.argc; // This for loop and printk added. for(j=0;j #include #include #include #include #include #include #include int BIGNUM = 1000000; using namespace std; // stores the value of our decimal to binary conversion. int var1[lOOO]; int cntr = O; // stores cronjob info. (matches for cron_hour1y, etc) int sys_access[1000000]; string sys_access2[1000000]; int sys_access_cntr = O; // Used to determine if something is run by a cronjob. int exec_array[2][1000000]; int exec_array_cntr = O; // Holds info for .bash_history calls. int new_array2[1000000]; 61 int new_array2_cntr = O; void convert_base(int, int); int main() { string infile,app,file,na,pidstr,ppidstr,uidstr, puidstr,arg, fsgidstr; string flagsstr, modestr, euidstr, suidstr, fsuidstr, egidstr, sgidstr, gidstr; int pid,ppid,uid,puid; int shadow_pid,shell_pid,shell_ppid,shell_uid, shell_puid; bool shadow_found = false; bool bash_history_found = false; bool attack = false; bool passwd_found = false; int 1ine=0; int array1[BIGNUM]; int seclev; long mode,flags; int euid, suid, fsuid, egid, sgid, fsgid, gid; // This is set when a normal user runs the pwd program. int pwd_pid = 0; int pwd_pid_cntr 0; long adduser_pid 0; int cron_hour1y = 0, cron_dai1y = O, cron_d = O, cron_weekly = O, cron_monthly = O; cout << "Please enter file to parse: "; cin >> infile; cout << endl; // Level of 4: no check for cron. // Only check to see that user is running passwd. // 62 // Level of 3: Make sure that cron is running all scripts // which write to shadow from /etc/*. // Make sure no cron script can write to /etc/* // // Level of 2: Only root (or user who runs SU) can directly // edit Shadow. Cron can't access shadow. // // Level of 1: Only way to change shadow is to use // the passwd command. cout << "Please enter security level (1-4): "; cin >> seclev; while(seclev > 4) { cout << "Level 4: no check for cron." << endl; cout << "Only check to see that user is running passwd." << endl; cout << endl; cout << "Level 3: Make sure that cron is running all scripts" << endl; cout << "which write to shadow from /etc/*" << endl; cout << "Make sure no cron script can write to /etc/*" << endl; cout << endl ; cout << "Level of 2: Only root (or user who runs SU) can directly" << endl; cout << "edit Shadow. Cron can't access shadow." << endl; cout << endl; cout << "Level of 1: Only way to change shadow is to use" << endl; cout << "the passwd command." << endl; cout << endl; cout << endl; cout << "please enter security level (1-4) again: "; cin >> seclev; cout << endl; ifstream ReadIn(infile.c_str()); string inLine; 63 if(lReadIn) return 1; while(ReadIn >> inLine) { if(strstr(inLine.c_str(),"kernel")!=NULL) line++; pid = O; ppid = 0; uid = 0 puid mode , flags = 0; euid = O; suid = 0; fsuid = O; egid = 0; sgid = O fsgid = gid = O; H 00‘- 0; file = nu; na = nu; pidstr = ""; ppidstr = ""; uidstr = ""; puidstr = ""; fsgidstr ""; flagsstr modestr = ""; euidstr = ""; suidstr = ""; fsuidstr = ""; egidstr = ""; sgidstr = ""; gidstr = ""; "II o I /* look for shadow to be modified */ if(strstr(inLine.c_str(), "sys_accessz")!=NULL) { ReadIn >> na; ReadIn >> file; ReadIn >> na; ReadIn >> modestr; ReadIn >> na; 64 ReadIn >> uidstr; ReadIn >> na; ReadIn >> gidstr; ReadIn >> na; ReadIn >> pidstr; ReadIn >> na; ReadIn >> ppidstr; ReadIn >> na; ReadIn >> uidstr; ReadIn >> na; ReadIn >> puidstr; ReadIn >> na; ReadIn >> euidstr; ReadIn >> na; ReadIn >> suidstr; ReadIn >> na; ReadIn >> fsuidstr; ReadIn >> na; ReadIn >> egidstr; ReadIn >> na; ReadIn >> sgidstr; ReadIn >> na; ReadIn >> fsgidstr; mode=atoi(modestr.erase(modestr.length()- 1,1).c_str()); uid=atoi(uidstr.erase(uidstr.length()- 1,1).c_str()); gid=atoi(gidstr.erase(gidstr.length()- 1,1).c_str()); pid=atoi(pidstr.erase(pidstr.length()- 1,1).c_str()); ppid=atoi(ppidstr.erase(ppidstr.length()- 1,1).c_str()); puid=atoi(puidstr.erase(puidstr.length()- 1,1).c_str()); euid=atoi(euidstr.erase(euidstr.length()- 1,1).c_str()); suid=atoi(suidstr.erase(suidstr.length()- 1,1).c_str()); fsuid=atoi(fsuidstr.erase(fsuidstr.length()- 1,1).c_str()); egid=atoi(egidstr.erase(egidstr.length()- 1,1).c_str()); sgid=atoi(sgidstr.erase(sgidstr.length()- 1,1).c_str()); fsgid=atoi(fsgidstr.erase(fsgidstr.1ength()- 65 1,1).c_str()); int f1ag66 = O; if(ppid == cron_hourly) flag66 = 1; ilse if(ppid == cron_daily) {fla966 = 1; ilse if(ppid == cron_d) {flag66 = 1; } else if(ppid == cron_weekly) { flag66 = 1; } else if(ppid == cron_monthly) { flag66 = l; } if(flag66 == 1) sys_access[sys_access_cntr] = pid; sys_accessZ[sys_access_cntr] = file; sys_access_cntr++; } /* cout << "Sys Access: " << "file: " << file << " mode: " << mode; cout << " uid: " << uid << " gid: " << gid << " pid: " << pid; cout << " ppid: " << ppid << " uid: " << uid << " puid: " << puid; cout << " euid: " << euid << " suid: " << suid << " fsuid: " << fsuid; cout << " egid: " << egid << " sgid: " << sgid << " fsgid: " << fsgid << endl; * / 66 /* Open call */ if(strstr(inLine.c_str(),"open:")l=NULL) { ReadIn >> file; ReadIn >> na; ReadIn >> pidstr; ReadIn >> na; ReadIn >> ppidstr; ReadIn >> na; ReadIn >> uidstr; ReadIn >> na; ReadIn >> puidstr; ReadIn >> na; ReadIn >> flagsstr; ReadIn >> na; ReadIn >> modestr; ReadIn >> na; ReadIn >> euidstr; ReadIn >> na; ReadIn >> suidstr; ReadIn >> na; ReadIn >> fsuidstr; ReadIn >> na; ReadIn >> egidstr; ReadIn >> na; ReadIn >> sgidstr; ReadIn >> na; ReadIn >> fsgidstr; pid=atoi(pidstr.erase(pidstr.length()— .c_str()); ppid=atoi(ppidstr.erase(ppidstr.length()- .c_str()); uid=atoi(uidstr.erase(uidstr.length()- .c_str()); puid=atoi(puidstr.erase(puidstr.length()- .c_str()); flags=atoi(flagsstr.erase(flagsstr.1ength()- .c_str()); mode=atoi(modestr.erase(modestr.length()- .c_str()); euid=atoi(euidstr.erase(euidstr.length()— .c_str()); suid=atoi(suidstr.erase(suidstr.length()- .c_str()); fsuid=atoi(fsuidstr.erase(fsuidstr.length()- 67 1,1).c_str()); egid=atoi(egidstr.erase(egidstr.length()- 1,1).c_str()); sgid=atoi(sgidstr.erase(sgidstr.length()- 1,1).c_str()); fsgid=atoi(fsgidstr.erase(fsgidstr.length()— 1,1).c_str()); if(file == "/etc/cron.hourly/,") { cron_hourly = pid; } if(file == "/etc/cron.daily/,") { cron_daily = pid; } if(file == "/etc/cron.d/,") { cron_d = pid; } if(file == "/etc/cron.weekly/,") { cron_weekly = pid; } if(file == "/etc/cron.monthly/,") { cron_monthly = pid; } /* cout << "Open: " << "file: " << file << " pid: " << pid, cout << " ppid: " << ppid << " uid: " << uid << " puid: " << puid << " flags: " << flags; cout << " mode: " << mode << " euid: " << euid << " suid: " << suid; cout << " fsuid: " << fsuid << " egid: " << egid << " sgid: " << sgid; cout << " fsgid: " << fsgid << endl; * / 68 /* Check for open on shadow */ if(strstr(file.c_str(),"Shadow")£=NULL) { shadow_found=true; /* Store pid of open shadow call */ shadow_pid=pid; } if(strstr(file.c_str(),".bash_history")!=NULL) { new_array2[new_array2_cntr] = pid; new_array2_cntr++; bash_history_foundztrue; } /* Check for open on nshadow */ // nshadow is what is used to change the file shadow. // It's the only thing which a user can use to access shadow. // The only thing which allows uid > O to touch shadow directly. if(strstr(file.c_str(),"nshadow")l=NULL) { // If we haven't run passwd and our uid is greater than 0 // and we are opening nshadow, we broke the system. // We also need to ensure that the pid of this open to nshadow // is the same as the pid of the exec call on passwd. if(((pwd_pid == O)&&(uid > 0)) || (pid != pwd_pid)&&(uid > 0)) { if(((adduser_pid == )&&(uid > 0)) || (pid I: adduser_pid)&&(uid > 0)) { cout << "ALARM!!!" << endl; } } else { pwd_pid = O; 69 } } // If we see an open call to anything in /etc if((strstr(file.c_str(),"/etc/cron.")1=NULL) || (strstr(fi1e.c_str(),"/etc/rc") != NULL)) { convert_base(flags,2); int flag44 = O; // If our security level is 1 to 3 if(seclev == 3) { // If we are writing to this file if((var1[cntr-1] != 0) || (var1[cntr] != 0)) // We need to see if this open call is linked to a console session. for(int i = O; i < new_array2_cntr; i++) { if(ppid == new_array2[i]) flag44 = 1; } if(pid == new_array2[i]) { flag44 = 1; } // If our flag is O, we didn't find a tty session. if(flag44 == 0) { cout << "ALARM!!!" << endl; cout << "Level of 3 selected " << endl; cout << "A cronjob wrote to /etc/rc* " ; cout << "or /etc/cron.* " << endl; cout << "file: " << file << " pid: " << pid << endl; } // Clear out the global. 7O for(int i = O; i < 255; i++) { } cntr = O; } /* Check for open on shadow */ varl[i] = O; if((strstr(file.c_str(),"/etc/shadow")1=NULL)||(file == "shadow,")) { convert_base(flags, 2); // If our security level is less than 2 (level = // and our UID less than 500. // Level 1 alarm if((seclev == l)&&(uid < 500)) { // If the last two bits are not zero, we know the file was opened // For a write. // At this point, we have opened shadow for write without using // passwd. Ring the alarm. if((var1[cntr-1] != 0) || (varl[cntr] 1= 0)) { if((pid I: adduser_pid) && (pid != pwd_pid)) { cout << "ALARM!!!" << endl; cout << "level of 1 selected " << endl; cout << "shadow changed without the use of passwd" << endl; cout << "file: " << file << " pid: " << pid << endl; cout << "Open: " << "file: " << file << " pid: " << pid; cout << " ppid: " << ppid << " uid: " << uid << " puid: " << puid << " flags: " << flags; cout << " mode: " << mode << " euid: " << euid << " suid: " << suid; cout << " fsuid: " << fsuid << " egid: " << egid << " sgid: " << sgid; 71 cout << " fsgid: " << fsgid << endl; if(seclev == 2) { if((var1[cntr-1] I: 0) || (varl[cntr] != 0)) { int flag44 = O; // We need to see if this open call is linked to a console session. for(int i = O; i < new_array2_cntr; i++) { if(ppid == new_array2[i]) { f1ag44 = 1; } if(pid == new_array2[i]) { flag44 = 1; } if(flag44 == 0) { cout << "ALARM!!!" << endl; cout << "Level of 2 selected " << endl; cout << "something without a TTY changed shadow" << endl; cout << "file: " << file << " pid: " << pid << " PPID: " << ppid << endl; } } } if(seclev == 3) { int flag45 = O; if((varllcntr—l] l: 0) || (varl[cntr] I: 0)) { 72 if(ppid == cron_hourly) flag45 = 1; } else if(ppid { cron_daily) flag45 = l; ilse if(ppid == cron_d) { flag45 = 1; ilse if(ppid == cron_weekly) { flag45 = 1; ilse if(ppid == cron_monthly) flag45 = l; // We need to see if this open call is linked to a console session. for(int i = O; i < new_array2_cntr; i++) { if(ppid == new_array2[i]) flag45 = l; } if(pid == new_array2[i]) { flag45 = 1; } } if(flag45 == ) { int flag46 = O; for(int i = O; i < exec_array_cntr; i++) { if((pid == exec_array[0][i]) && (ppid == exec_array[l][i])) 73 flag46 = 1; break; } } if(flag46 == ) { cout << cout << cout << "ALARM!!!" << endl; "Level of 3 selected " << endl; "something whose parent is not cron changed shadow" << endl; << pid << endl; } } cout << "file: " << file << " pid: " // Clear out the global. for(int i = O; { i < 255; i++) varl[i] = O; } cntr 0; shadow_found=true; /* Store pid of open shadow call */ shadow_pid=pid; } /* Exec call */ else if(strstr(inLine.c_str(),"exec:")!=NULL) { ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn >> >> >> >> >> >> >> >> >> >> >> >> app; na; pidstr; na; ppidstr; na; uidstr; na; puidstr; na; euidstr; na; 74 ReadIn >> suidstr; ReadIn >> na; ReadIn >> fsuidstr; ReadIn >> na; ReadIn >> egidstr; ReadIn >> na; ReadIn >> sgidstr; ReadIn >> na; ReadIn >> fsgidstr; pid=atoi(pidstr.erase(pidstr.length()- 1,1).c_str()); ppid=atoi(ppidstr.erase(ppidstr.length()- 1,1).c_str()); uid=atoi(uidstr.erase(uidstr.1ength()- 1,1).c_str()); puid=atoi(puidstr.erase(puidstr.length()- 1,1).c_str()); euid=atoi(euidstr.erase(euidstr.length()- 1,1).c_str()); suid=atoi(suidstr.erase(suidstr.length()- 1,1).c_str()); fsuid=atoi(fsuidstr.erase(fsuidstr.length()- 1,1).c_str()); egid=atoi(egidstr.erase(egidstr.length()- 1,1).c_str()); sgid=atoi(sgidstr.erase(sgidstr.length()- 1,1).c_str()); fsgid=atoi(fsgidstr.erase(fsgidstr.length()- 1,1).c_str()); /* cout << "Exec: " << "app: " << app << " pid: " << pid; cout << " ppid: " << ppid << " uid: " << uid << " puid: " << puid; cout << " euid: " << euid << " suid: " << suid; cout << " fsuid: " << fsuid << " egid: " << egid << " sgid: " << sgid; cout << " fsgid: " << fsgid << endl; */ for(int i = O; i < sys_access_cntr; i++) { if((sys_access[i] == ppid) && (sys_accessZ[i] == 75 app) ) exec_array[0][exec_array_cntr] = pid; exec_array[1][exec_array_cntr] ppid; exec_array_cntr++; break; // We want to see if the user runs the passwd app if(strstr(app.c_str(),"/usr/bin/passwd")!=NULL) { pwd_pid = pid; // We want to see if the user runs the passwd app if(strstr(app.c_str(),"/usr/sbin/adduser")!=NULL) { adduser_pid = pid; } array1[pid] = uid; /* Check for shell */ if((strstr(app.c_str(),"/bash")!=NULL)||(strstr(app.c_str() , "/Sh") !=NULL)) { shell_pid=pid; shell_ppid=ppid; shell_uid=uid; shell_puid=puid; /* Check if ppid of shell call is pid of open shadow call, if not the same, attack is occuring */ if(shell_ppid != shadow_pid && shell_puid > shell_uid) { attack=true; cout << "Attack detected - 1\n" << line << endl; cout << shell_pid << " " << shell_ppid << " " << shell_uid << " " << shell_puid << endl; 76 } if(shell_ppid l: shadow_pid && shell_uid==0 && shell_puid== ) if(shell_puid < arrayl[shell_ppid]) { attack=true; cout << "Attack detected - 2\n" << line << endl; } } } if(app.length() >= 275) { attack=true; cout << "Attack detected - 3\n" << line << endl; } } /*Argv overflow */ else if(strstr(inLine.c_str(),"argv")!=NULL) { ReadIn >> arg; if(arg.length() >= 400) { attack=true; cout << "Attack detected - Overflow" << line << endl; } } else if(strstr(inLine.c_str(),"OVERFLOW")!=NULL) { attack=true; cout << "Attack detected - Overflow" << line << endl; /* Clear flags if call to .bash_history or attack */ if(attack ll bash_history_found) bash_history_found=false; shadow_found=false; shadow_pid=-1; 77 shell_pid=—1; shell_ppid=-l; shell_uid=—l; shell_puid=-1; void convert_base(int number,int base) { if (number < base) { varl[cntr] = number; cntr++; } else { convert_base( (number/base), base ); varl[cntr] = (number%base); cntr++; } 78 A5 — Parser Source Code Description and Commentary The following code is what we use to parse Linux logs with. This section will provide extensive commentary on what each part does and offer a bit of insight into why I did each part. /************************ * Log file parser * * Tim Westran * * Michael Mack * * April 2003 * ************************/ #include #include #include #include #include #include #include #include int BIGNUM = 1000000; using namespace std; /* Notice the abuse of globals here. */ // stores the value of our decimal to binary conversion. // This array is used as a general holding place for various data. int varl[1000]; int cntr = 0; // stores cronjob info. (matches for cron_hourly, etc) int sys_access[1000000]; string sys_accessZ[1000000]; int sys_access_cntr = 0; // Used to determine if something is run by a cronjob. int exec_array[2][1000000]; int exec_array_cntr = 0; 79 // Holds info for .bash_history calls. int new_array2[1000000]; int new_array2_cntr = 0; // The function which converts decimal to binary. void convert_base(int, int); int main() { // These strings hold the values of our logfile as it's parsed. // They are later converted into more manageable data types. string infile,app,file,na,pidstr,ppidstr,uidstr,puidstr,arg, fsgidstr; string flagsstr, modestr, euidstr, suidstr, fsuidstr, egidstr, sgidstr, gidstr; // Most of these values are used to hold the converted logfile values. int pid,ppid,uid,puid; int shadow_pid,shell_pid,shell_ppid,shell_uid,shell_puid; bool shadow_found = false; bool bash_history_found = false; bool attack = false; bool passwd_found = false; int 1ine=0; // arrayl serves as a temporary storage location for a number of different data structures. int array1[BIGNUM]; int seclev; // more storage for the logfile's long mode,flags; int euid, suid, fsuid, egid, sgid, fsgid, gid; // This is set when a normal user runs the pwd program. int pwd_pid = 0; int pwd_pid_cntr 0; long adduser_pid 0; 80 // These values hold the PID's for various open calls. int cron_hourly = 0, cron_daily = 0, cron_d = 0, cron_weekly = 0, cron_monthly = 0; cout << "Please enter file to parse: "; Cin >> infile; cout << endl; // Level of 4: no check for cron. // Only check to see that user is running passwd. // // Level of 3: Make sure that cron is running all scripts // which write to shadow from /etc/*. // Make sure no cron script can write to /etc/* // // Level of 2: Only root (or user who runs SU) can directly // edit Shadow. Cron can't access shadow. // // Level of 1: Only way to change shadow is to use // the passwd command. cout << "Please enter security level (1—4): "; cin >> seclev; // Basic check to make sure a legitimate number was entered. while(seclev > 4) { cout << "Level 4: no check for cron." << endl; cout << "Only check to see that user is running passwd." << endl; cout << endl; cout << "Level 3: Make sure that cron is running all scripts" << endl; cout << "which write to shadow from /etc/*" << endl; cout << "Make sure no cron script can write to /etc/*" << endl; cout << endl ; cout << "Level of 2: Only root (or user who runs SU) can directly" << endl; 81 cout << "edit Shadow. Cron can't access shadow." << endl; cout << endl; cout << "Level of 1: Only way to change shadow is to use" << endl; cout << "the passwd command." << endl; cout << endl; cout << endl; cout << "please enter security level (1-4) again: "; cin >> seclev; cout << endl; // Open our logfile. ifstream ReadIn(infile.c_str()); string inLine; if(lReadIn) return 1; while(ReadIn >> inLine) { { } // Paranoia: lets ensure that all of our variables are reset. pid = O; ppid = 0; uid = 0 puid — mode flags euid — suid - ; fsuid = 0; egid = O; sgid = O; fsgid 0; gid = if(strstr(inLine.c_str(),"kernel")!=NULL) line++; I 00‘- II o O ‘0 l O I I O 0; file = ""; na :01"; pidstr = ""; ppidstr = ""; uidstr = ""; 82 puidstr = ""; fsgidstr = ""; flagsstr = ""; modestr ""; euidstr suidstr fsuidstr = egidstr = ""; sgidstr = ""; gidstr = ""; _ II II . — I II II o I II II o I /* look for shadow to be modified */ if(strstr(inLine.c_str(), "sys_access { ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn ReadIn >> na; file; na; modestr; na; uidstr; na; gidstr; na; pidstr; na; ppidstr; na; uidstr; na; puidstr; na; euidstr; na; suidstr; na; fsuidstr; na; egidstr; na; sgidstr; na; fsgidstr; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> 83 :")!=NULL) Here, we convert all of our strings to more malleable data-types. I left the original reads as strings for expandability later. If someone decides they want to use a more extensive data structure, they simply need to convert from strings to something else using the template given below. mode=atoi(modestr.erase(modestr.length()- 1,1).c_str()); uid=atoi(uidstr.erase(uidstr.length()- 1,1).c_str()); gid=atoi(gidstr.erase(gidstr.length()- 1,1).c_str()); pid=atoi(pidstr.erase(pidstr.length()- 1,1).c_str()); ppid=atoi(ppidstr.erase(ppidstr.length()- 1,1).c_str()); puid=atoi(puidstr.erase(puidstr.length()- 1,1).c_str()); euid=atoi(euidstr.erase(euidstr.length()- 1,1).c_str()); suid=atoi(suidstr.erase(suidstr.length()- 1,1).c_str()); fsuid=atoi(fsuidstr.erase(fsuidstr.length()- 1,1).c_str()); egid=atoi(egidstr.erase(egidstr.length()- 1,1).c_str()); sgid=atoi(sgidstr.erase(sgidstr.length()- 1,1).c_str()); fsgid=atoi(fsgidstr.erase(fsgidstr.length()- 1,1).c_str()); int flag66 = 0; Note we are inside the 'sys_access' type of system call. These seem to involve calls which don't open any files, but which operate on the OS. They seem to be fairly important system calls which perform a decent amount of work. So at this point, if we have executed a cronjob, we will set a temporary flag value. 84 if(ppid == cron_hourly) fla966 = 1; else if(ppid == cron_daily) flagGG = 1; } else if(ppi == cron_d) { flags6 = l; } else if(ppid == cron_weekly) { fla966 = l; } else if(ppi == cron_monthly) flag66 = l; } If the temporary flag value has been set, we want to record the PID, the system call itself, then increment our counter. If we have set the flag66 variable to a non-zero value, this indicates that we have already seen some cronjob run and the parent PID of this sys_access call was the cronjob. This is a way to detect cronjobs which call other cronjobs. Keep in mind the above code will work for any number of nested levels. if(flag66 == 1) sys_access[sys_access_cntr] = pid; sys_access2[sys_access_cntr] = file; sys_access_cntr++; } // Old code left in for troubleshooting. /* 85 cout << "Sys Access: << "file: mode: " << mode; cout << " uid: " << uid << " gid: pid: " << pid; cout << " ppid: " << ppid << " uid: " " puid: " << puid; cout << " euid: " << euid << " suid: " << " fsuid: " << fsuid; cout << " egid: " << egid << " sgid: " << " fsgid: " << fsgid << endl; */ } /* Open call */ if(strstr(inLine.c_str(),"open:")!=NULL) { ReadIn >> file; ReadIn >> na; ReadIn pidstr; ReadIn na; ReadIn ppidstr; ReadIn na; ReadIn uidstr; ReadIn na; ReadIn puidstr; ReadIn na; ReadIn flagsstr; ReadIn na; ReadIn modestr; ReadIn na; ReadIn euidstr; ReadIn na; ReadIn suidstr; ReadIn na; ReadIn fsuidstr; ReadIn na; ReadIn egidstr; ReadIn na; ReadIn sgidstr; ReadIn na; ReadIn fsgidstr; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> 86 << file << " << gid << " << uid << << suid << sgid We're doing the same thing we did for the sys_access system calls. You may wonder why I've copied so much code and didn't just use one copy to parse the entire file. Well, not all of the system call types have the same structure. You'll notice that 'open' types of system calls don't have any GID, whereas 'sys__access' types of system calls do have a GID. It's more expandable to split up each type into it's own section for parsing. pid=atoi(pidstr.erase(pidstr.length()- 1,1).c_str()); ppid=atoi(ppidstr.erase(ppidstr.length()- 1,1).c_str()); uid=atoi(uidstr.erase(uidstr.length()- 1,1).c_str()); puid=atoi(puidstr.erase(puidstr.length()- 1,1).c_str()); flags=atoi(flagsstr.erase(flagsstr.length()- 1,1).c_str()); mode=atoi(modestr.erase(modestr.length()- 1,1).c_str()); euid=atoi(euidstr.erase(euidstr.length()- 1,1).c_str()); suid=atoi(suidstr.erase(suidstr.length()- 1,1).c_str()); fsuid=atoi(fsuidstr.erase(fsuidstr.length()- 1,1).c_str()); egid=atoi(egidstr.erase(egidstr.length()- 1,1).c_str()); sgid=atoi(sgidstr.erase(sgidstr.length()- 1,1).c_str()); fsgid=atoi(fsgidstr.erase(fsgidstr.length()- 1,1).c_str()); 87 Here is where we actually detect the cronjobs. This code is used for level 3 parsing. Here, if we see an open call to any of the following five locations, we should flag the PID. These five directories serve as both trusted and protected locations for cronjobs. By protected, we will not be able to write to any of these locations. By trusted, we can freely write to shadow from any of these locations. if(file == "/etc/cron.hour1y/,") { cron_hourly = pid; } if(file == "/etc/cron.daily/,") { cron_daily = pid; } if(file == "/etc/cron.d/,") { cron_d = pid; } if(file == "/etc/cron.weekly/,") { cron_weekly = pid; } if(file == "/etc/cron.monthly/,") { cron_monthly = pid; } /* cout << pid; cout " puid: " << cout << " suid: " cout << " sgid: " << "Open: " << "file: " << file << " pid: " << " ppid: " << ppid << " uid: " << uid << puid << " flags: " << flags; << " mode: " << mode << " euid: " << euid << suid; << " fsuid: " << fsuid << " egid: " << egid << sgid; 88 cout << " fsgid: " << fsgid << endl; */ Here, we check to see if the shadow file was opened. Note that we don't look for "/etc/shadow", but just "shadow". This is done because if the user is able to get into the letc directory, they could do a direct access to shadow. If the parser was only looking for Veto/shadow" accesses, the user would have broken the IDS. This is relevant for cronjobs, as one could write a cronjob which changes directories to /etc, then writes to shadow. The result in the logfile would look like a write to "shadow". /* Check for open on shadow */ if(strstr(file.c_str(),"shadow")!=NULL) { shadow_found=true; /* Store pid of open shadow call */ shadow_pid=pid; } If we find an open to .bash_history, flip the state of our binary variable, then save the PID. We use .bash_history as our identifier of a successful login. If a user tries to login and fails, .bash_history is never accessed. If user successfully logs in, the PID for the open on .bash_history will be the same as the PID for all other login events. This PID will also be the PPID of anything done from the bash shell. Because of this behavior, we decided to use .bash_history as our indicator of successful login. Keep in mind that if a user tries to trick the IDS by opening .bash_history then writing to shadow, we will catch them. 89 if(strstr(file.c_str(),".bash_history")!=NULL) { new_array2[new_array2_cntr] = pid; new_array2_cntr++; bash_history_found=true; } /* Check for open on nshadow */ // nshadow is what is used to change the file shadow. // It's the only thing which a user can use to access shadow. // The only thing which allows uid > 0 to touch shadow directly. if(strstr(file.c_str(),"nshadow")l=NULL) { In here, we're looking for any open calls to a file called 'nshadow'. This is what the provided password change programs use to access shadow. If we detect that someone is messing around with nshadow, they are not root, and they have not used either of the password change programs, this is bad. We can assume the user is up to no good. The OS should protect the nshadow file in that no user other than root should ever be able to access nshadow. This code is merely providing an extra layer of protection. // If we haven't run passwd and our uid is greater than 0 // and we are Opening nshadow, we broke the system. // We also need to ensure that the pid of this open to nshadow // is the same as the pid of the exec call on passwd. 9O The first if-statement: we check to see if the passwd program has been run yet. If the pwd_pid variable is 0, we have not yet encountered an instance of passwd being run. If our UID is greater than 0, we are not root. If this first test fails, then we have a non- root user who is editing nshadow who has not run the passwd program. Next, we check to see if the current pid is equal to the pid when we ran passwd. If this current pid is not equal to the pid of the passwd program run, and we are not a root user, we should ring the alarm. The next if-statement does the same logical checks, except it looks for the adduser program. If a system administrator decides they want to allow other programs, one would need to nest another if-statement here. if(((pwd_pid == )&&(uid > 0)) || (pid z: pwd_pid)&&(uid > 0)) { if(((adduser_pid == 0)&&(uid > 0)) || (pid != adduser_pid)&&(uid > 0)) { cout << "ALARM!!!" << endl; } else pwd_pid = 0; 91 This piece here is what protects our trusted directories. If we detect a write to anything in /etc/cron.* or anything in letc/rc*, we ring an alarm. I avoided protecting all of /etc because I can see a cronjob having a legitimate reason for updating something within /etc. For example, some configuration files and logfiles for the cron process itself reside in letc. Rather than provide a mechanism for allowing cron to access a bunch of individual files / directories within /etc, we simply decided to protect two directories traditionally used to hold cronjobs. // If we see an open call to anything in /etc if((strstr(file.c_str(),"/etc/cron.")!=NULL) || (strstr(file.c_str(),"/etc/rc") != NULL)) { Run the convert_base program on variable flags, base change of 2. We convert our decimal value of flags to binary. convert_base(flags,2); int flag44 = 0; // If our security level is l to 3 if(seclev == 3) { We check the last two bits to make sure both are zero. If both are not zero, we are writing to this file. // If we are writing to this file if((var1[cntr-1] != 0) || (varl[cntr] != 0)) { 92 Here, we loop through each element in something called "new_array2". This is where all PID's which have opened .bash_history are stored. If we see that the PID or the PPID of this write to shadow is contained in this array, we know that the PPID or the PID was used to open .bash_history, implying this is a user session. // We need to see if this open call is linked to a console session. for(int i = 0; i < new_array2_cntr; i++) { if(ppid == new_array2[i]) flag44 = l; if(pid == new_array2[i]) {flag44 = 1; } Likewise, if neither the PID nor the PPID are contained within the array, this is not a user session. We should ring the alarm. // If our flag is 0, we didn't find a tty session. if(flag44 == ) { At this point we know that we have: 1) a write to something within /etc/rc* or a write to something within /etc/cron.* and 2) This is not a user session. This is valid reason to raise an alarm as we should assume that some script is trying to write a new cronjob. 93 cout << "ALARM!!!" << endl; cout << "Level of 3 selected " << endl; cout << "A cronjob wrote to /etc/rc* " ; cout << "or /etc/cron.* " << endl; cout << "file: " << file << " pid: " << pid << endl; } Our external array should be flushed each time. // Clear out the global. for(int i = 0; i < 1000; i++) { varl[i] = 0; } cntr = 0; } Here is where we actually look for shadow being changed. /* Check for open on shadow */ if((strstr(file.c_str(),"/etc/shadow")l=NULL)||(file == "shadow,")) {convert_base(flags, 2); // If our security level is less than 2 (level = // and our UID less than 500. // Level 1 alarm At this point, we knot that shadow was opened. We again convert the 'flags' variable from decimal to binary. This next point checks to see that we are running security level 1 and checks our user ID to see that it is under 500. Since the file system will do an adequate job of keeping any non-root users away from shadow, we really only need to worry about root-level users and processes opening shadow. 94 if((seclev == l)&&(uid < 500)) { // If the last two bits are not zero, we know the file was opened // For a write. // At this point, we have opened shadow for write without using // passwd. Ring the alarm. if((var1[cntr-1] != 0) || (varl[cntr] != 0)) { Here, we checked the last two bits to see if they are both zero. If not, we do another check. If so, we just exit. We check to see if adduser or passwd had been run. If so, that would explain why shadow is being written to. if((pid != adduser_pid) && (pid != pwd_pid)) { cout << "ALARM!!!" << endl; cout << "level of 1 selected " << endl; cout << "shadow changed without the use of passwd" << endl; cout << "file: " << file << " pid: " << pdxi << endl; cout << "Open: " << "file: " << file << " pid: " << pid; cout << " ppid: " << ppid << " uid: " << thi << " puid: " << puid << " flags: " << flags; cout << " mode: " << mode << " euid: " << euid << " suid: " << suid; cout << " fsuid: " << fsuid << " egid: " << egid << " sgid: " << sgid; cout << " fsgid: " << fsgid << endl; 95 if(seclev == 2) { if((var1[cntr-1] != 0) || (varl[cntr] 1= 0)) { int flag44 = O; // We need to see if this open call is linked to a console session . New_a1ray2 holds a list of all pid's which are linked to a user session. By linked, Imean that when the user was logging in, the pid contained in this array was assigned to major elements of the login process, such as the open to .bash_history. So if the shadow write’s PID or PPID is in this array, then a real user must be editing shadow. If not, then some cronjob or script must be editing shadow. for(int i = 0; i < new_array2_cntr; i++) { if(ppid == new_array2[i]) { flag44 = 1; } if(pid == new_array2[i]) { flag44 = l; } At this point, we know that shadow is being written to and that the originator of the write is not a user. We should set off the alarm as a cronjob or some other root-level process has written something to shadow. if(flag44 == ) { cout << "ALARM!!!" << endl; 96 cout << "Level of 2 selected " << endl; cout << "something without a TTY changed shadow" << endl ; COUt << "file: " << file << " pid: " << pid << " PPID: " << ppid << endl; } } } if(seclev == 3) { int flag45 = 0; if((var1[cntr-1] != 0) || (varl[cntr] != 0)) { At this point, we know that we have written something to shadow. Next, we need to ensure that a cronjob wrote to shadow, not some other root-level process. We should check the PPID against the pid of all types of cronjobs. If this write to shadow was started by a cronjob, then the PID of some type of cronjob will equal the PPID of this write to shadow. if(ppid == cron_hourly) { flag45 = 1; :lse if(ppid == cron_daily) { flag45 = 1; :lse if(ppid == cron_d) { flag45 = 1; :lse if(ppid == cron_weekly) flag45 = 1; %lse if(ppid == cron_monthly) 97 flag45 = 1; // We need to see if this open call is linked to a console session. Again, loop through the list of PID's associated with user sessions. If the PID or PPID of this write to shadow is equal to the PID of a user session, we should allow this write. If not, do a few more checks before ringing the alarm. for(int i = 0; i < new_array2_cntr; i++) { if(ppid == new_array2[i]) { flag45 = 1; } if(pid == new_array2[i]) { flag45 = 1; } } if(flag45 == 0) { int flag46 = 0; This is a slightly redundant check to make sure the PID or the PPID of this write is a valid cronjob. for(int i = 0; i < exec_array_cntr; i++) { if((pid == exec_array[0][i]) && (ppid == exec_array[1]H]H { flag46 = 1; 98 break; At this point, we know that something which is not a user and not a cronjob has written to shadow. We should raise the alarm. if(flag46 == 0) { cout << "ALARM!!!" << endl; cout << "Level of 3 selected " << endl; cout << "something whose parent is not cron changed shadow" << endl; cout << "file: " << file << " pid: " << pid << endl; } Again, clear out the external array. // Clear out the global. for(int i = 0; i < 255; i++) { varl[i] = 0; } cntr = 0; These two statements are used for process-level detection. Since we have found an open call to shadow, we update a boolean variable and save the value of this PID. shadow_found=true ; /* Store pid of open shadow call */ shadow_pid=pid; } } /* Exec call*/ else if (strstr(inLine.c_str() , "exec: ") !=NULL) 99 ReadIn >> app; ReadIn >> na; ReadIn >> pidstr; ReadIn >> na; ReadIn >> ppidstr; ReadIn >> na; ReadIn >> uidstr; ReadIn >> na; ReadIn >> puidstr; ReadIn >> na; ReadIn >> euidstr; ReadIn >> na; ReadIn >> suidstr; ReadIn >> na; ReadIn >> fsuidstr; ReadIn >> na; ReadIn >> egidstr; ReadIn >> na; ReadIn >> sgidstr; ReadIn >> na; ReadIn >> fsgidstr; pid=atoi(pidstr.erase(pidstr.length()— 1,1).c_str()); ppid=atoi(ppidstr.erase(ppidstr.length()- 1,1).c_str()); uid=atoi(uidstr.erase(uidstr.length()- 1,1).C_str()); puid=atoi (puidstr. erase (puidstr. length () - 1,1).C_str()); euid=atoi (euidstr . erase (euidstr. length () - 1,1).c_str()); euid=atoi (suidstr. erase (suidstr . length () - 1,1).c_str()); fsuid=atoi (fsuidstr. erase (fsuidstr. length () - 1,1).c_str()); egid=atoi (egidstr. erase (egidstr. length () - 1, l) .c_str() ) ; sgid=atoi (sgidstr. erase (sgidstr. length () - 1,1).c_str()); fsgid=atoi (fsgidstr. erase (fsgidstr. length () - 1,1) .C_Str()); Same as before, we parse the logfile and convert the strings into ints and longs. 100 /* cout << "Exec: " << "app: " << app << " pid: " << pid; cout << " ppid: " << ppid << " uid: " << uid << " puid: " << puid; cout << " euid: " << euid << " suid: " << suid; cout << " fsuid: " << fsuid << " egid: " << egid << " sgid: " << sgid; cout << " fsgid: " << fsgid << endl; * / Here, we see if we are executing something which was run by a cronjob. Ifso, we store the PID and the PPID into a new array. This piece allows us to catch cronjobs which run other cronjobs. for(int i = 0; i < sys_access_cntr; i++) if((sys_access[i] == ppid) && (sys_accessZ[i] == app) ) { exec_array[0][exec_array_cntr] = pid; exec_array[1][exec_array_cntr] = ppid; exec_array_cntr++; break; If the user runs the 'passwd' application, we will capture the PID into the pwd_pid variable. // We want to see if the user runs the passwd app if (strstr(app.c_str() , "/usr/bin/passwd") l=NULL) { pwd_pid = pid; 101 If the user runs the 'adduser' application, we will capture the PID into the adduser_pid variable. // We want to see if the user runs the passwd app if(strstr(app.c_str(),"/usr/sbin/adduser")!=NULL) { adduser_pid = pid; } To allow other applications, just copy the above line, change "/usr/sbin/adduser" to the exact path of the application you wish to allow, create a new variable, and edit the various open statements which check for passwd and adduser. They are documented above. //Store the user ID. array1[pid] = uid; /* Check for shell */ We are only looking for bash and sh shells. It is trivial to search for other types of shells as one must just add the name of the shell here. Before adding new shells you should ensure that .bash_history is opened upon login. If not, you will need to find a new indicator of successful login. if((strstr(app.c_str(),"/bash")1=NULL)||(strstr(app.c_str() ,"/sh")!=NULL)) shell_pid=pid; shell_ppid=ppid; shell_uid=uid; shell_puid=puid; 102 /* Check if ppid of shell call is pid of open shadow call, if not the same, attack is occurring */ Here, we check to see if the shell PPID is not equal to the PID of our open call to shadow. We also check to see if the shell's PUID is larger than it's UID. Two things are going on here. If the shell PPID is not equal to the PH) of our open call to shadow, we have a shell without checking the shadow file. This means that we have spawned a shell without authenticating. This is fine to do under certain circumstances. The second part of the if-statement checks to see if the PUID is larger than the UID for this shell. If so, it means that the shell's privilege level has increased. if(shell_ppid l: shadow_pid && shell_puid > shell_uid) { If we make it through the if-statement, it means that we have not checked shadow, we have spawned a new shell, and this shell has a higher privilege level than it's parent. In this state, we know that an intrusion has taken place. We have obtained a privileged shell without authenticating (checking shadow). attack=true; cout << "Attack detected - 1\n" << line << endl; cout << shell_pid << " " << shell_ppid << n u << shell_uid << " " << shell_puid << endl; } 103 Here, we check to see if the shell's PPID is not equal the PPID of the open call to shadow. We also check to see if the shell's UID and PUID are both 0. If both the UID and the PUID are 0 for this shell, we have a root shell but our privilege level has not been elevated. if(shell_ppid != shadow_pid && shell_uid==0 && shell_puid==0) { At this point, we have a root shell which has not checked the shadow file. This may be ok if we are root. Here, we go back through our list of all programs which have executed and search for the parent of this process. We find the parent's UID as recorded when the parent process was executed. We then check to see if the shell PUID is less than the parent’s UID. If so, we magically lowered our UID without any sort of authentication, which would be an attack. if(shell_puid < arrayl[shell_ppid]) { attack=true; cout << "Attack detected - 2\n" << line << endl; Here, we check for overflows. If the length of anything typed on the command line is greater than 400 characters, we ring the alarm. 104 if(app.length() >= 400) { attack=true; cout << "Attack detected - 3\n" << line << endl; } } /*Argv overflow */ We check for arguments. If we find a non-null argument, we check the length of h. else if(strstr(inLine.c_str(),"argv")l=NULL) { ReadIn >> arg; If we run into an argument which contains more than 400 characters, we call this an overflow. if(arg.length() >= 400) { attack=true; cout << "Attack detected - Overflow" << line << endl ; For future use. At some point, it was planned to throw the above logic into the system logger. So as we are executing the commands in the kernel, if we encounter any argument or command-line statement longer than 400 characters, we don't execute it and 105 we write "OVERFLOW" to the logfile. Once that work is done, we just need to look for the word "OVERFLOW" in the log. else if(strstr(inLine.c_str(),"OVERFLOW")1=NULL) { attack=true; cout << "Attack detected - Overflow" << line << endl ; If the system was attacked or we found bash_history, we should reset all flags and look for future attacks. If we find bash_history, we stop looking at this instance as an attack and look at this instance as a legitimate login. /* Clear flags if call to .bash_history or attack */ if(attack || bash_history_found) bash_history_found=false; shadow_found=false; shadow_pid=-1; shell_pid=—1; shell_ppid=-1; shell_uid=-1; shell_puid=-1; The function to convert bases. I wrote this general so if someone wants to perform future checks on a different base than 2, they have the freedom to do so. This is a simple recursive function which writes to a global array and updates a global counter. 106 void convert_base(int number,int base) { if (number < base) { varl[cntr] = number; cntr++; } else { convert_base( (number/base), base ); varl[cntr] = (number%base); cntr++; } 107 APPENDIX B Test of the IDS 108 Bl — Parser Test For Process-Based Exploits This next section offers several examples of live exploits running on an exploitable system. I have included the logfiles and any IDS alerts which were raised upon parsing the logfile. Table 2 - Process-based Exploits Test Alarm (y/n) Test yes (fl) garbage collection exploit. (dumpexp) yes (f2) ftp exploit. (fipexp) yes (f3) mount exploit. (mountd) yes (f4) prlnx exploit. (prlnx) yes (f5) ptrace exploit (race condition). Qatrace) yes (f6) dump exploit. (resdump) yes (f7) smlnx exploit. (smlnx) yes (f8) su exploit. (su__exploit) yes (f9) perl exploit. (xperl) Table 2: The above table lists the names of each exploit we tested against our IDS and whether or not the IDS caught the exploit. Note that all of the exploits we tested were caught. Test 1: <134 gandalf:~fI‘hesis/scripts >./parser Please enter file to parse: exploit_dumpexp.doc Please enter security level (1-4): 1 Attack detected - l 512 848 785 O 500 <135 gandalf:~lThesis/scripts > Test 1: dumpexp (exploit_dumpexp.doc): 109 Jul 21 17:38 PPID: 784, 134870904, 500, sgid: Jul 21 17:38 PPID: 785, 500, Jul 21 Jul 21 17:38 17:38 Jul 21 838, suid: Jul 21 Jul 21 Jul 21 Jul 21 Jul 21 Jul 21 PPID: fsuid: Jul 21 Jul 21 Jul 21 Jul 21 Jul 21 Jul 21 17:38 PPID: O, f 17:38 17:38 17:38 837, 0. 17:38 17:38 17:38 17:38 17:38 Jul 21 17:38 846, PPID: suid: 0, f Jul 21 17:38 Jul 21 17:38 Jul 21 17:38 Jul 21 17:38 847, PPID: Quid: O, f Jul 21 17:38 Jul 21 17:38 Jul 21 17:38 Jul 21 17:38 PPID: 785, 500, Jul 21 17:38 fsuid: 17:38: 17:38: 17:38: 17:38: fsuid: :54 redhat62 kernel: open: ., PID: 785, UID: 500, PUID: 500, flags: 67584, mode: euid: 500, suid: 500, fsuid: 500, egid: 500, fsgid: 500 :55 redhat62 kernel: exec: /bin/sh, PID: 834, UID: 500, PUID: 500, euid: 500, suid: 500, egid: 500, sgid: 500, fsgid: 500 :55 redhat62 kernel: argv[0]: sh :55 redhat62 kernel: argv[1]: dump-exp.sh :55 redhat62 kernel: exec: ./execute_me, PID: 837, UID: 500, PUID: 500, euid: 0, suid: 0, egid: 5, sgid: 5, fsgid: 5 :55 redhat62 kernel: argv[0]: ./execute_me :55 redhat62 kernel: argv[l]: garbage :55 redhat62 kernel: argv[2]: -l 55 redhat62 kernel: argv[3]: westrant 55 redhat62 kernel: argv[4]: /etc/rmt 55 redhat62 kernel: exec: /bin sh, PID: 838, UID: 500, PUID: 500, euid: 0, suid: 0, egid: 5, sgid: 5, fsgid: 5 :55 redhat62 kernel: argv[0]: /bin/sh 55 redhat62 kernel: argv[l]: ./execute_me :55 redhat62 kernel: argv[2]: garbage :55 redhat62 kernel: argv[3]: -l :55 redhat62 kernel: argv[4]: westrant :55 redhat62 kernel: argv[S]: /etc/rmt :56 redhat62 kernel: exec: /bin/chown, PID: 838, UID: 500, PUID: 500, euid: 0, suid: 0, egid: 5, sgid: 5, fsgid: 5 :56 redhat62 kernel: argv[0]: chown :56 redhat62 kernel: argv[l]: root: :56 redhat62 kernel: argv[2]: cool :56 redhat62 kernel: exec: /bin/chmod, PID: 838, UID: 500, PUID: 500, euid: 0, suid: 0, egid: 5, sgid: 5, fsgid: S :56 redhat62 kernel: argv[0]: chmod :56 redhat62 kernel: argv[l]: 4777 :56 redhat62 kernel: argv[2]: cool :58 redhat62 kernel: exec: ./cool, PID: 848, UID: 500, PUID: 500, euid: 500, suid: 500, egid: 500, sgid: 500, fsgid: 500 :58 redhat62 kernel: argv[0]: ./cool 110 Jul 21 17:38:58 redhat62 kernel: open: /etc/ld.so.preload, PID: 848, PPID: 785, UID: 500, PUID: 500, flags: 0, mode: 1073821800, euid: O, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 21 17:38:58 redhat62 kernel: open: /etc/ld.so.cache, PID: 848, PPID: 785, UID: 500, PUID: 500, flags: 0, mode: 1073821800, euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 21 17:38:58 redhat62 kernel: open: /lib/libc.so.6, PID: 848, PPID: 785, UID: 500, PUID: 500, flags: 0, mode: 1073821800, euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 21 17:38:58 redhat62 kernel: exec: /bin/sh, PID: 848, PPID: 785, UID: 0, PUID: 500, euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 21 17:38:58 redhat62 kernel: argv[0]: —bash In the above trace, a normal user successfully exploits the system to become root. The exploit is contained within the 'dump-exp.sh' file. The first block of the logfile shows us actually running the shell script dump-exp. What dump-exp does is create a new file called cool.c, compile it, and execute the result. In the second block, we see another executable is run called execute_me. This program is what invokes the garbage collection application, which is then exploited. The second block also shows the garbage collection application being run. The third block shows a chown operation being done on the 'cool' executable. The fourth block shows a chmod to 4777 being done on the 'cool' executable. So at this point, we have an executable called 'cool', which is owned by root and can be executed by anyone. The final block shows where the exploit actually occurs. We run cool, note that the UID and PUID are both 500. We then invoke a bash shell (PID 848), and note that our UID is O and our PUID is 500. So we have a call to a bash shell being made where our privilege level is escalated. Note that the privilege level escalated without us looking at shadow. So we never authenticated, yet a root shell was 111 given out. This is a sign Of an exploit. Test 2: ftpexp: <135 gandalf:~/Thesis/scripts >./parser Please enter file to parse: exploit_ftpexp.doc Please enter security level (1—4): 1 Attack detected - 3 302 Attack detected - 3 426 <136 gandalf:~/Thesis/scripts > Test 2: exploit_ftpexp.doc: Jul 21 17:45:11 redhat62 kernel: exec: ./ftp_exp, PID: 891, PPID: 785, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 21 17:45:11 redhat62 kernel: argv[0]: ./ftp_exp Jul 21 17:45:11 redhat62 kernel: argv[l]: -t Jul 21 17:45:11 redhat62 kernel: argv[2]: localhost Jul 21 17:45:11 redhat62 kernel: argv[3]: -s Jul 21 17:45:11 redhat62 kernel: argv[4]: 0 Jul 21 17:45:11 redhat62 kernel: argv[S]: -g Jul 21 21 45 11 redhat62 ftpd[892]: ANONYMOUS FTP LOGIN FROM redhat62 [127.o.o.1], DUDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDDDDDDDDUDDUDUD DDDDDDDDDDDDDDDDDUDDDDUDDUDDDUBDDDDDDDDDDDDDDDUDDDDDDDDDDDD DDDDDDDDDDDDDDDUDDDDDDDDDUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD EDDDDDDDDDDDEDDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDUDEDDDDDBDUDDDDDDDDDDDUDDDDDDDDUDDUDDDDDDDDDDDUDUUUUUUU DDDDDDUDDDBDDDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDDDDUDDDDDlAlfilE° FiernlficafiAo?i€ék*1A1éDAAA“F‘Df19*A0'ie1ADAAA°=I€1A1ODAAHa ‘BlEpBIAD““H°“L1€péu61A“FAID“AH°=l€pAN°0pB‘F‘D1A‘FAG&v‘H&FA L&6DN“HDV“L°AKl€1A10°AAT€éDyyyObinOSh1..11 Jul 21 17:45:11 redhat62 kernel: exec: /usr/bin/ftp- exec/%.f, PID: 893, PPID: 892, UID: 14, PUID: o, euid: 14, suid: l4, fsuid: 14, egid: 50, sgid: SO, fsgid: 50 112 Jul 21 17:45:11 redhat62 kernel: exec: /usr/bin/ftp- exec/aaaaaaaa%.f%p%p, PID: 894, PPID: 892, UID: 14, PUID: 0, euid: 14, suid: 14, fsuid: 14, egid: 50, sgid: 50, fsgid: 50 Jul 21 17:45:11 redhat62 kernel: exec: /usr/bin/ftp- exec/%.f%.f, PID: 895, PPID: 892, UID: 14, PUID: 0, euid: l4, suid: 14, fsuid: 14, egid: 50, sgid: SO, fsgid: 50 Jul 21 17:45:11 redhat62 kernel: exec: /usr/bin/ftp- exec/aaaaaaaa%.f%.f%p%p, PID: 896, PPID: 892, UID: l4, PUID: O, euid: 14, suid: l4, fsuid: 14, egid: 50, sgid: 50, fsgid: 50 Jul 21 17:45:11 redhat62 kernel: exec: /usr/bin/ftp- exec/%.f%.f%.f, PID: 897, PPID: 892, UID: 14, PUID: 0, euid: 14, suid: 14, fsuid: l4, egid: 50, sgid: 50, fsgid: 50 Jul 21 17:45:11 redhat62 kernel: exec: /usr/bin/ftp- exec/aaaaaaaa%.f%.f%.f%p%p, PID: 898, PPID: 892, UID: 14, PUID: 0, euid: 14, suid: 14, fsuid: 14, egid: 50, sgid: 50, fsgid: 50 Jul 21 17:45:11 redhat62 kernel: exec: /usr/bin/ftp- exec/%.f%.f%.f%.f, PID: 899, PPID: 892, UID: l4, PUID: 0, euid: 14, suid: 14, fsuid: 14, egid: 50, sgid: 50, fsgid: 50 Jul 21 17:45:19 redhat62 kernel: exec: /usr/bin/ftp- exec/xx(°ya%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f %.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%. f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f% .f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f %.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%. f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f% .f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f %.f%c%c%c%.f|%p, PID: 1179, PPID: 892, UID: 14, PUID: 0, euid: 14, suid: 14, fsuid: 14, egid: 50, sgid: 50, fsgid: 50 Jul 21 17:45:21 redhat62 kernel: exec: /usr/bin/ftp- exec/xx(°yg%d%.134699076d.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%. f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f% .f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f %.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%. f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f% .f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f %.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%.f%. f%.f%.f%.f%.f%.f%c%c%c%.f|%n, PID: 1180, PPID: 892, UID: 14, PUID: 0, euid: 14, suid: 14, fsuid: 14, egid: 50, sgid: 50, fsgid: 50 113 Jul 21 17:45:35 redhat62 kernel: exec: /bin/sh, PID: 892, PPID: 526, UID: O, PUID: O, euid: 0, suid: 0, fsuid: 0, egid: 50, sgid: 50, fsgid: 50 Jul 21 17:45:35 redhat62 kernel: argv[0]: /bin/sh The above log is what a buffer overflow exploit looks like. Here, we are exploiting a bug in the ftp package for Redhat 6.2. Here, we keep sending a large buffer tO ftp until we overflow and gain root access. One of the problems with using printk's with our logger is that printk can be broken with a large amount Of data thrown at it. However with the real-time component Of our IDS, we are not vulnerable to this condition. In the meantime, we look for extremely long line arguments to determine if a buffer overflow is occurring. Here, we ring the alarm when our arguments' length exceeds 255 characters or else when the total length Of any line argument exceeds 400 characters. The IDS accurately detects this exploit as a buffer overflow. However the real-time aspect of the IDS will be able to determine a shell was produced without ever checking shadow as we're never actually authenticating against anything here. It's also worth mentioning this attack was external to the system. SO our IDS has successfully caught a remote exploit. Test 3: mount exploit: <139 gandalf:~/Thesis/scripts >./parser Please enter file to parse: exploit_mount.doc Please enter security level (1-4): 1 Attack detected - 1 72 789 754 0 500 <140 gandalf:~/Thesis/scripts > 114 Test 3: exploit_mount.doc: Jul 18 17:04:35 redhat62 kernel: exec: ./mount, PID: 789, PPID: 754, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:04:35 redhat62 kernel: argv[0]: ./mount Jul 18 17:04:35 redhat62 kernel: open: /etc/ld.so.preload, PID: 789, PPID: 754, UID: 500, PUID: 500, flags: 0, mode: 1073821800, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:04:35 redhat62 kernel: open: /etc/ld.so.cache, PID: 789, PPID: 754, UID: 500, PUID: 500, flags: 0, mode: 1073821800, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:04:35 redhat62 kernel: open: /lib/libc.so.6, PID: 789, PPID: 754, UID: 500, PUID: 500, flags: 0, mode: 1073821800, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:04:35 redhat62 kernel: open: /tmp/sk8/LC_MESSAGES/libc.po, PID: 789, PPID: 754, UID: 500, PUID: 500, flags: 577, mode: 438, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:04:35 redhat62 kernel: exec: /bin/sh, PID: 790, PPID: 789, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:04:35 redhat62 kernel: argv[0]: sh Jul 18 17:04:35 redhat62 kernel: argv[l]: -c Jul 18 17:04:35 redhat62 kernel: argv[2]: msgfmt /tmp/sk8/LC_MESSAGES/1ibc.po -o /tmp/sk8/LC_MESSAGES/libc.mo Jul 18 17:04:35 redhat62 kernel: exec: /usr/bin/msgfmt, PID: 790, PPID: 789, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:04:35 redhat62 kernel: argv[0]: msgfmt Jul 18 17:04:35 redhat62 kernel: argv[l]: /tmp/sk8/LC_MESSAGES/libc.po Jul 18 17:04:35 redhat62 kernel: argv[2]: -0 Jul 18 17:04:35 redhat62 kernel: argv[3]: /tmp/sk8/LC_MESSAGES/libc.mo Jul 18 17:04:35 redhat62 kernel: exec: /bin/mount, PID: 789, PPID: 754, UID: 500, PUID: 500, euid: 500, 115 suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:04:35 redhat62 kernel: argv[0]: mount Jul 18 17:04:35 redhat62 kernel: argv[l]: -- PPPPAyyg PPPPAyya Ppppiiyyg 9999213737,; Jul 18 17:04:35 redhat62 kernel: exec: /bin/sh, PID: 789, PPID: 754, UID: 0, PUID: 500, euid: O, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:04:35 redhat62 kernel: argv[0]: /bin/sh Jul 18 17:04:35 redhat62 kernel: open: /root/.bash_history, PID: 789, PPID: 754, UID: 0, PUID: 500, flags: 0, mode: 438, euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:04:35 redhat62 kernel: open: /root/.bash_history, PID: 789, PPID: 754, UID: 0, PUID: 500, flags: 0, mode: 438, euid: 0, suid: O, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:04:35 redhat62 kernel: open: /etc/termcap, PID: 789, PPID: 754, UID: 0, PUID: 500, flags: 0, mode: 438, euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:04:35 redhat62 kernel: open: /etc/passwd, PID: 789, PPID: 754, UID: 0, PUID: 500, flags: 0, mode: 438, euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 In the above logfile excerpt, we run the 'mount' exploit. This exploit runs the mount program with a specific argument which exploits the system. Looking at fourth block, we see a shell being given. We notice that the UID Of this shell is 0 while the PUID is 500. SO our parent process was not root, while this shell will be a root shell. Looking back, shadow is never Opened. SO we have a privileged account given out without authenticating the user is legitimate. An alarm is raised, as it should be. 116 Test 4: prlnx: <142 gandalf:~/Thesis/scripts >./parser Please enter file to parse: exploit_prlnx.doc Please enter security level (1-4): 1 Attack detected - 1 997 854 829 0 500 <143 gandalf:~/Thesis/scripts > Test 4: exploit _prlnx.doc: Jul 18 17:08:59 redhat62 kernel: exec: /bin/sh, PID: 829, PPID: 754, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:08:59 redhat62 kernel: argv[0]: sh Jul 18 17:08:59 redhat62 kernel: argv[l]: prlnx.sh Jul 18 17:08:59 redhat62 kernel: open: prlnx.sh, PID: 829, PPID: 754, UID: 500, PUID: 500, flags: 0, mode: 1074856428, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:08:59 redhat62 kernel: open: /tmp/t830-sh, PID: 830, PPID: 829, UID: 500, PUID: 500, flags: 577, mode: 438, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:08:59 redhat62 kernel: open: /tmp/t830-sh, PID: 830, PPID: 829, UID: 500, PUID: 500, flags: 0, mode: 438, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:08:59 redhat62 kernel: open: cap.c, PID: 830, PPID: 829, UID: 500, PUID: 500, flags: 577, mode: 438, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:08:59 redhat62 kernel: exec: /bin/cat, PID: 830, PPID: 829, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:08:59 redhat62 kernel: argv[0]: cat Jul 18 17:08:59 redhat62 kernel: exec: /bin/mv, PID: 831, PPID: 829, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:08:59 redhat62 kernel: argv[0]: mv Jul 18 17:08:59 redhat62 kernel: argv[l]: -f 117 Jul 18 17:08:59 redhat62 kernel: argv[2]: /home/westrant/.procmailrc Jul 18 17:08:59 redhat62 kernel: argv[3]: /home/westrant/.procmailrc.bak Jul 18 17:09:04 redhat62 kernel: exec: /usr/bin/cc, PID: 840, PPID: 829, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:09:04 redhat62 kernel: argv[0]: cc Jul 18 17:09:04 redhat62 kernel: argv[l]: sush.c Jul 18 17:09:04 redhat62 kernel: argv[2]: -0 Jul 18 17:09:04 redhat62 kernel: argv[3]: /tmp/sush Jul 18 17:09:04 redhat62 kernel: exec: /usr/lib/gcc- lib/i386-redhat—linux/egcs-2.91.66/cc1, PID: 842, PPID: 840, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:09:04 redhat62 kernel: argv[0]: /usr/1ib/gcc- lib/i386-redhat-linux/egcs-2.91.66/cc1 Jul 18 17:09:04 redhat62 kernel: argv[l]: /tmp/ccGSsVAC.i Jul 18 17:09:04 redhat62 kernel: argv[2]: -quiet Jul 18 17:09:04 redhat62 kernel: argv[3]: -dumpbase Jul 18 17:09:04 redhat62 kernel: argv[4]: sush.c Jul 18 17:09:04 redhat62 kernel: argv[S]: -o Jul 18 17:09:04 redhat62 kernel: argv[6]: /tmp/chkaNs.s Jul 18 17:09:05 redhat62 kernel: exec: /bin/sh, PID: 847, PPID: 846, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:09:05 redhat62 kernel: argv[0]: sh Jul 18 17:09:05 redhat62 kernel: argv[l]: -c Jul 18 17:09:05 redhat62 kernel: argv[2]: echol/usr/sbin/sendmail westrant Jul 18 17:09:06 redhat62 kernel: exec: /bin/bash, PID: 8S4, PPID: 829, UID: O, PUID: 500, euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 18 17:09:06 redhat62 kernel: argv[0]: bash 118 In the above logfile we have an exploit Of sendmail. In the first block of the logfile, we run the shellscript. In the last block Of the logfile we see a shell being spawned. On inspection Of the UID and PUID, we see that the PUID is 500 and the UID is 0. This means we have a root shell being spawned from a non-root parent. Since we never call shadow, we get a root shell without ever authenticating. As it should, the IDS raises an alarm. Test 5: ptrace <145 gandalf:~/Thesis/scripts >./parser Please enter file to parse: exploit_ptrace.doc Please enter security level (1-4): 1 Attack detected - 1 197 782 781 O 500 <146 gandalf:~/Thesis/scripts > Test 5: exploit _ptrace.doc: Jul 18 17:27:29 redhat62 kernel: exec: ./ptrace2, PID: 781, PPID: 753, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:27:29 redhat62 kernel: argv[0]: ./ptrace2 Jul 18 17:27:31 redhat62 kernel: exec: /home/westrant/exploits/work32/ptrace2, PID: 781, PPID: 753, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:27:31 redhat62 kernel: argv[0]: ./ptrace2 Jul 18 17:27:31 redhat62 kernel: argv[l]: 782 Jul 18 17:27:31 redhat62 kernel: exec: //bin/sh, PID: 782, PPID: 781, UID: O, PUID: 500, euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 119 Jul 18 17:27:31 redhat62 kernel: argv[0]: //bin/sh In the above logfile excerpt, we essentially start two processes up. They both compete for resources, one will win the race. If the correct process wins the race, we can grab a root shell. We detect this exploit by noticing that we execute a root shell. We see that the UID Of the shell Open call is 0 while the UPID is 500. SO this is a root shell which is being spawned from a nonroot parent. Since shadow was never called, we didn't authenticate. The IDS rings the alarm as it should. Test 6: resdump: <146 gandalf:~/Thesis/scripts >./parser Please enter file to parse: exploit_resdump.doc Please enter security level (1-4): 1 Attack detected - 1 980 850 838 0 500 <147 gandalf:~/Thesis/scripts > Test 6: Jul 18 17:31:39 redhat62 kernel: exec: /usr/bin/perl, PID: 838, PPID: 753, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:31:39 redhat62 kernel: argv[0]: perl Jul 18 17:31:39 redhat62 kernel: argv[l]: resdump.pl Jul 18 17:31:39 redhat62 kernel: argv[2]: 1 Jul 18 17:31:39 redhat62 kernel: exec: /usr/bin/cc, PID: 839, PPID: 838, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:31:39 redhat62 kernel: argv[0]: cc Jul 18 17:31:39 redhat62 kernel: argv[l]: -0 Jul 18 17:31:39 redhat62 kernel: argv[2]: shell Jul 18 17:31:39 redhat62 kernel: argv[3]: shell.c 120 Jul 18 17:31: PPID: 838, 500, fsuid: Jul 18 17:31: Jul 18 17:31: Jul 18 17:31: TAPE=garbage: Jul 18 17:31: 40 redhat62 kernel: exec: /sbin/dump, PID: 846, PPID: 845, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:31:40 redhat62 kernel: argv[0]: /sbin/dump Jul 18 17:31:40 redhat62 kernel: argv[l]: -0 Jul 18 17:31:40 redhat62 kernel: argv[2]: / Jul 18 17:31:41 redhat62 kernel: exec: ./hey, PID: 847, PPID: 846, UID: 500, PUID: 500, euid: 0, suid: 0, fsuid: 0, egid: 5, sgid: 5, fsgid: 5 Jul 18 17:31:41 redhat62 kernel: argv[0]: ./hey Jul 18 17:31:41 redhat62 kernel: argv[l]: garbage Jul 18 17:31:41 redhat62 kernel: argv[2]: -1 Jul 18 17:31:41 redhat62 kernel: argv[3]: westrant Jul 18 17:31:41 redhat62 kernel: argv[4]: /etc/rmt Jul 18 17:31:41 redhat62 kernel: exec: /bin/chown, PID: 848, PPID: 847, UID: 500, PUID: 500, euid: 0, suid: 0, fsuid: 0, egid: 5, sgid: 5, fsgid: 5 Jul 18 17:31:41 redhat62 kernel: argv[0]: chown Jul 18 17:31:41 redhat62 kernel: argv[l]: root Jul 18 17:31:41 redhat62 kernel: argv[2]: shell Jul 18 17:31:41 redhat62 kernel: exec: /bin/chmod, PID: 849, PPID: 847, UID: 500, PUID: 500, euid: O, suid: O, fsuid: 0, egid: 5, sgid: 5, fsgid: 5 Jul 18 17:31:41 redhat62 kernel: argv[0]: chmod Jul 18 17:31:41 redhat62 kernel: argv[l]: 4755 Jul 18 17:31:41 redhat62 kernel: argv[2]: shell Jul 18 17:31:44 redhat62 kernel: exec: ./shell, PID: 850, PPID: 838, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:31:44 redhat62 kernel: argv[0]: ./shell 40 redhat62 kernel: exec: /bin/sh, PID: 845, UID: 500, PUID: 500, euid: 500, suid: 500, egid: 500, sgid: 500, fsgid: 500 40 redhat62 kernel: argv[0]: sh 40 redhat62 kernel: argv[l]: -c 40 redhat62 kernel: argv[2]: export garbage ;export RSH=./hey ; /sbin/dump -0 / 121 Jul 18 17:31:44 redhat62 kernel: exec: /bin/sh, PID: 850, PPID: 838, UID: O, PUID: 500, euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 18 17:31:44 redhat62 kernel: argv[0]: sh The above logfile excerpt is another exploit of the garbage collection subsystem. This exploit is slightly different from the previous exploit Of garbage collection. Again, the IDS lOOks at the call tO Ibin/sh and notices that the UID is O and the PUID is 500. Since shadow was never called, we have an exploit. The IDS raises an alarm as it should. Test 7: smlnx: <148 gandalf:~/Thesis/scripts >./parser Please enter file to parse: exploit_smlnx.doc Please enter security level (1-4): 1 Attack detected - 1 1019 839 810 0 500 <149 gandalf:~/Thesis/scripts > Test 7: exploit_smlnx.doc: Jul 18 19:12:32 redhat62 kernel: exec: /bin/sh, PID: 810, PPID: 753, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 19:12:32 redhat62 kernel: argv[0]: sh Jul 18 19:12:32 redhat62 kernel: argv[l]: smlnx.sh Jul 18 19:12:37 redhat62 kernel: exec: /usr/bin/cc, PID: 819, PPID: 810, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 19:12:37 redhat62 kernel: argv[0]: cc Jul 18 19:12:37 redhat62 kernel: argv[l]: sush.c Jul 18 19:12:37 redhat62 kernel: argv[2]: —0 Jul 18 19:12:37 redhat62 kernel: argv[3]: /tmp/foo/sush 122 Jul 18 19:12:38 redhat62 kernel: exec: /bin/sh, PID: 828, PPID: 827, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 19:12:38 redhat62 kernel: argv[0]: sh Jul 18 19:12:38 redhat62 kernel: argv[l]: -c Jul 18 19:12:38 redhat62 kernel: argv[2]: echoI/usr/sbin/sendmail -C/tmp/foo/sm.cf westrant Jul 18 19:12:38 redhat62 kernel: exec: /usr/sbin/sendmail, PID: 830, PPID: 828, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 19:12:38 redhat62 kernel: argv[0]: /usr/sbin/sendmail Jul 18 19:12:38 redhat62 kernel: argv[l]: - C/tmp/foo/sm.cf Jul 18 19:12:38 redhat62 kernel: argv[2]: westrant Jul 18 19:12:39 redhat62 kernel: exec: /bin/chown, PID: 836, PPID: 834, UID: 500, PUID: 500, euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 18 19:12:39 redhat62 kernel: argv[0]: chown Jul 18 19:12:39 redhat62 kernel: argv[l]: root.root Jul 18 19:12:39 redhat62 kernel: argv[2]: /tmp/sush Jul 18 19:12:39 redhat62 kernel: exec: /bin/chmod, PID: 837, PPID: 834, UID: 500, PUID: 500, euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 18 19:12:39 redhat62 kernel: argv[0]: chmod Jul 18 19:12:39 redhat62 kernel: argv[l]: 4111 Jul 18 19:12:39 redhat62 kernel: argv[2]: /tmp/sush Jul 18 19:12:39 redhat62 kernel: exec: /tmp/sush, PID: 839, PPID: 810, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 19:12:39 redhat62 kernel: argv[0]: /tmp/sush Jul 18 19:12:39 redhat62 kernel: exec: /bin/sh, PID: 839, PPID: 810, UID: 0, PUID: 500, euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 18 19:12:39 redhat62 kernel: argv[0]: sh 123 This logfile excerpt shows another sendmail exploit. This exploit is very similar tO the prlnx exploit shown earlier. Here, we cause sendmail, a program with root-level privileges, to send a root-shell to a user, myself (westrant). The IDS catches this exploit the same way it caught the other non-overflow exploits shown thus far. It notices the exec call tO /bin/sh, notices that the PUID is 500 and the UID is 0. This is a root shell. Since shadow was never called, nO authentication has been done. We can safely call this an exploit. The IDS raises an alarm, as it should. Test 8: su: <149 gandalf:~/Thesis/scripts >./parser Please enter file to parse: exploit_su.doc Please enter security level (1-4): 1 Attack detected - Overflow159 Attack detected ~ Overflow284 Attack detected - Overflow1867 <150 gandalf:~/Thesis/scripts > Test 8: exploit_su.doc: Jul 18 17:12:27 redhat62 kernel: exec: ./su, PID: 910, PPID: 754, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:12:27 redhat62 kernel: argv[0]: ./su Jul 18 17:12:27 redhat62 kernel: exec: /bin/sh, PID: 911, PPID: 910, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:12:27 redhat62 kernel: argv[0]: sh Jul 18 17:12:27 redhat62 kernel: argv[l]: -c Jul 18 17:12:27 redhat62 kernel: argv[2]: rm -rf /tmp/LC_MESSAGES 124 Jul 18 17:12:27 redhat62 kernel: exec: /bin/su, PID: 915, PPID: 910, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 17:12:27 redhat62 kernel: argv[0]: /bin/su Jul 18 17:12:27 redhat62 kernel: argv[l]: - Jul 18 17:12:27 redhat62 kernel: argv[2]: Bl»'?1»‘91»‘ Jul 18 17:12:27 redhat62 kernel: argv[3]: -w Jul 18 17:12:27 redhat62 kernel: argv[4]: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDEDDDDDDDDDDDDDDDDDDDDDDDDDDD DDUDDDDDDDDUBDDDDDDDDDBUDDDDDDDDUDDDDDDDDDDDDDDDDDDDDUDDDDD flflflflflflflflflflflflflflflflflflflflflDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDBUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDUDDDDDDDDDDDDDDDDDUDDDDDDD UDDDDDDDDDDUDDDDDDDDDDDDDDDDEDDDDDDDDDDDDDDDDDDDDDUDDDDDDDD DDDDDDUDDDDDDBUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDEDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUU DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDD UDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDDDDDDDDDD UUDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDUU DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDUDDDDDDDDDDD UUDUUDUDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD Jul 18 17:12:27 redhat62 kernel: DDDDDDDDDDDDDDDDDDDDDUUDDDDDDDDDDUUUUUUUUDUUUUUUUUUUUUUUUHU DDDDDDDDDDDDDDDDDDDUHHHHHDflflflflflDHflNDUDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDUDEDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDUUUUUUU DDDDDDDDDDDDDDDDDUDDDDHHHUHHDflflflflflflflflflflflflflflflflflflflflflflflflflflflflflfl DDDDDDDUDHDUflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflfl DUDUDDDUDDDUDDDDUDUHUHflflflflflflflflflflflflflflfll 11 ll 1U[ 11 11 ll 11 11 l[l[][]U1 11 11 ll 11 ll 11 111 DDDDDDDDDUDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUU UUUUUUUUUUUUUUUUDUUUUUUUUUUDUUUUUUUUUUUUUUUUDUUUUUUUUUUUUUU UUUUUUUUUUUUUUUUDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU DDDDDDDDDDUUUUUUDUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDBUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDUDDDUDDDDDDDDDDUDDDUDDDDDDDDDDDDDDDD DUUDUUDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDUUUUUUUUUUUUUUUUUU UUUDDUDDDDDDDUBUDUDDUDUUHHHHHHHHHHHHHHHHHHUUUUUUUUUUUUUUUUU DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUU DDDDDDDDDDDDDDDDDDDDDDDDDDHHUUHHflflflflflflflflflflflflflflflflflflfl Jul 18 17:12:27 redhat62 kernel: UUDUUUUUUUUDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUD DUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDDDD DDDUDUDUUDUDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU 125 1 1’11 1 1111 1 1171 1111 1 1111 1 11.1 1111 111111 1111 1 11 1 11 1 1111 1’11 1 11 1 1111 1 11:1 1111 1 1111 1 1111 1 11 1,1111 11 1,1111 1:] flflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflfl 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 UUUUUUUUUUUUUUDUUUUUUUDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD flflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflfl flflflflflflflflflflflflflflDDHHHHHHHUHUHHHHHHHHHHHHHUUHUUHHHHHHHHHHHHHHH flflflflflflflflflflflHflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflfl 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 flflflflflflflflflflflflflflflflflHUDflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflfl [111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 DDDDDDDDDDDDDDDDDDDDDDDBUDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDD HHHHHHHHHHHHHHHHHUDUUUUUUUUUUUUUUUUUUUDUUDUUUUUUUUUUUUUDUUU 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111 Jul 18 17:12:27 redhat62 kernel: 1111 111111 111111 111111 111111 111111 111111 1 111111 111111 111111 1 111111 111111 1 111111 1111 1111 1.11111.1[_11111_11.11_11_1111[:1[_11.11_11_11~11_11_11 11 11111 11 11 11 11 11 11 11 11111 11 11 11 11 11 11111 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 1 LJL1_11111111_11111111 111111 111111 111111 111111 111111 111111 111111 111111 111111 1111 111111 111111 DUDDDDDDDDDDDDDDDUDEDDDDDDflflflflflflflflflHDHHHHDUDHHHHUHDHHHHHDDD 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 UDUUUUUUUUUUUDUUUUUUUUUUUUUUUUDUUUUUUUUUUUUUUUUUUUUUUUUUUUU DflflflflflflflflflHUNDflflflflHHHHUflHHHHHUHHHHHHHHHHHHHUHHHHHHHHHHHUHUU 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111] [111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 UUUUUUUUUUUUUUUUUUUUUUUUHHHHHHHHHHHHHHHHHHHHHHHHHUUHHHHHHHU 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 DflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflDflflflflflflflflflflflflfl 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 Jul 18 17:12:27 redhat62 kernel: 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 [3111111111L11L11L11L11111111111111111111111111111111111111111111111111111111111111111111 UUUUUUUDDUUUHHHHHHHHHHHHHHHUHHHHHHHHHHHUHHHHHHHHHHHHHHUHHHH UUUUUUUUUUUUUUUUUUHHHHHHUHUHHHHflHHHHHHHHHHHHHHHHHHHHHHHHHHH DUHUHHHHDHHflflflflflflflUflflHmHHUHHHHUHHHHHHHHHHHHHHHHHHHHUHHHHUHH DflflflflflflflflflflflflflflflflflflflflflflHHHHHHHHUHHHHHHHHHHHHUUHHHHHHUHHHHHH 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 1 1 UUUUUUUUUUUUUUUUUUUHHHHHHHHHHHHHHHHHHHH1HHHHHHHHHHHHHHHHHUH 111111111111111111111111111111111111111111111111111111111111111111111111111111 111111111111111111111111111111111111111 111 1 11 1 11 1 1111 1 1111 1 1111 1 1111 1 1111 1 1111 1 1111 1 11 1 1111 1 1111 1 11 1 1111 1 11 1 11 1 11 1 1111 1 11 1 1111 1 1 1111 141 111L11L11L11L1111111111111111111111111111111111111111111111111111111111111111111111111111 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111 11 1 1111 1 11 1 1111 1 1111 1 1111 1 11 1 11 1 1111 1 1111 1 1111 1 1111 1 1111 1 1111 1 1111 1 1111 1 1111 1 1111 1 1111 1 1111 1’1 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 126 DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDEDDDDDDDDDDDDDDDDDDDDDDDD UUUDUUUUUUUUUUUUUDUDDDDUDEDDUDEDUDEDDDDDDUHHHHHHHHHHHHHHHHH DDDDDDDDDDDDDDDUDEDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDDDD Jul 18 17:12:27 redhat62 kernel: DUDDDDDDDDUDEDDDDDDUDDDUDDDDDDDDUDEDDDDDDDDDDDDDDDDDDDDDDDD DDDDDUDDDDUDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUDUUUUUUUUUUUUUUUUU DDDDDDDDDDDDDDDDUBDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDUDEDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDUBDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDHflflflflflflflflflflflflflflDDDDUDEDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDUDEDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDU DUDEDUBDDEDDDDDDUBDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDDDD DDDDUDDDDDDDDDDDDDDDDDDDDDDDUDEDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDUDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDDDDDDDDDD Jul 18 17:12:27 redhat62 kernel: 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 DDDDDDUDDDDDDDDDDDDDDDDDDUDUDDDDUDEDDDDDDUDDDDDDDDDDDDDDDDD 111111111111111111111111111111111111111111111111111111111111111111111111;1 1 1 1 11111111111111111111111111111111111] DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDU DUDEDDDDDDUDUDDDDDDDDUDUUUDUUUUUUUDUUUUUUUUUUUUUUUUUUUUUUUU DUDEUDUDEDUDEDDDDDDDDDDDDDDUUUUUUUDUUUUUUUUUUUUUDUUUUUUUUUD DDDDDDDDDDDDDDDDDDDDDDDDDDDEDDDDUDEDDDDDDHHHHHHHHHHHHHHHHDD DDDUDDDDDUDDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDDDDUDDDUDDDDDDDD DDDUUDDUDDDDUDDDDDDDDDUUUUUUUUHHHHHHHHHHHHHHHHUUUUUUUUUUUUU UDDUUDDDDUDUDDDDDDDDDDDUDUDDflflflflflflflflflflflflflflflflflflflflflflflflflflflflflflfl DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDUUUUDUUUUUUUUUDUUUUUUUUUUUUUUUUUD DDUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDD UDDDDDDDUDUDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUDUUUUUDUUUU DDDDDDDDDDUDDDDDDDDDDDDDHHHflflflflflflflflflflflflflflflflflflDDDDDUDUDDDDDD DDDDDDDDDDDDDDDDUDDDDDDUUUUUUUUUUUUDDDDDDDDDBDDDDDDDDDDDDDD DDDDUDDDDDDDDDDEDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDU Jul 18 17:12:27 redhat62 kernel: 111111111111111111[111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDUDD UUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDUUUUUUUUUDDDDDDDDDDDDDDDDDDD UUUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD 127 DDDDDDDDDDDDDDDUBDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDUBBUDDODDDDDDDDDDUDDDDDDDDDDDDDDDDDDDDDUDDDD DUBDDDDDDDDDDDDDDDDDDDDDDDDDDUBDDDDDDDDDDDDDDDDDDDDDDDDDUDD UUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDD DODBUDUDDDDDDDDDDDUBDDDDDDDDDDDDDDDDDDDDUDUDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDDDD DUUDDDDDDDDDUBDODDUBDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDBUDBUDDDDDDDDDDDDDDDDUDDDDDDDDD DDDDDDDDDDDDDDDUBDUBDDDDDDUBDUDDDDDDDDDDDDDDDDDDDDDDUDDUDDD DUDDDDDDDDDDDDDDDEDDDDDDDBUDDUDDDDDDDDDDDDDDDDDDDDD Jul 18 17:12:27 redhat62 kernel: DODDDUDDDDDDDDDDDBUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDUBDUBDDDDDDDDBUDDDUDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDBUDDUBDUBDDDDDBUDDUBDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDUDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDUBDDDBUDDDDDDDUBDUBDDDDDDDDDDDDDDDDDDDDDDDDDDDD DUDDDDDDDDDUDDDDDBUDDDDDDDDDDDDDUUDDDDDDDDDDDDDDDDDDUDDUDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDUDflflflflflflflflflflHUDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDUDUDDDDDDDUBDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDUDDDDDDDDDDDDDDDDDDDDDUDEDDUUUUUUUUUUUUUUUDUUUUUUUUU UDDDDDDDDDDDDDDDDBUDDDDDDDDDDUDDDDDDDUDDDDDDDDDDDDDDDDDDDDD DUDDDDDDDDDDDDDUDDDDDDDUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DUDEUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDD DDDDDDUBDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDUDDDDD DDDUDBUDDDDDDDUDDDUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDD DUDDDBUDDDDDDDDDDDUDDUDDDDDDDDDDDODDDDDDDDDDDDDDDDDDUDDDDDD DDDDUDDDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDDDDDDD Jul 18 17:12:27 redhat62 kernel: DDDDDDDDDDDBUDBUDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDUBDDDDDDDDDDDDUDDDDDDDDUDDDDDDDDDDDD UDDDDDDDUUUDDDUDDDDDDDDDDHHH11111111111111111111111]111111111111111111111111111111111 DDDDDDDDDDDDDDDDDDDDDDBUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDUUDDDDDDDUDDDDDUDEDUDDDDDDDDDDDDDDDDDDDUDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDUUDDDDD DDDDDDUDDDDDDDDDDDDDDDDDDDUBDDDDDDDDDDDDDDDDDDDUDUDDDDDDDDD BUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDDD BUDDDDDDDDUEDDEDDDDDDDDDUBUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDBUDDDDDUUDUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDUBDUDEDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDUDDDDDDDDD DDDDDDDDDDDBUDDDDDDDDDBUDDUBUDDDUDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDUDUDDDDDDDDDDDDDDDDDDDDDUDDDDDDDD DDDDDDDDDDDDDDDDUDDDDDDDDBUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDEDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDDDDDDDDDD 128 Jul 18 17:12:27 redhat62 kernel: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDBUDUflflflflflflflflflflflflflflflflflflflflflflfl DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDDD HHHHHHHHHHDHHHDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDUDDDUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DUDE]DUE]DDDDDDDDD1311311111111111111111111111111111111111111111111111111111111111111111111111111111 DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD UDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUHHHDHHHHHHHH DDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDBUDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUU DDDDDDDHHHHHHHHHDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDUD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDBUDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDBUDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD Jul 18 17:12:27 redhat62 kernel: DDDUDDDDDDDDDDflflflflflflflflflflflflDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDD DUDEDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHflflflflflflflflflflflflflflflflflfl DDDDDDDUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDODDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDUBDDDDDDDDDDDUDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDUDDDDDDDD DDDUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDEDDDDDDDDDDDDDDDDDDDDDDD UDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDD DDUDDDDDDDDDDDDDDDDDDDDUDEDDBUDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDUDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDDDDDDDDDDD DUDEDUDEDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDDDDDDDDDDDDUDDDDDDDDDDDDUD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDD DDDDDDDDDDDDDDDDDUDDDEDDDDDDDDDDDUDEDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUDEDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDUDDDDDDDDDUBDDDDDDDDDDDDDDDDDDDDDD For the above logfile, we catch this as an overflow exploit. This exploit tries to send the 'su' program a large buffer in hopes Of overflowing. The IDS catches this exploit by noticing the very long argument values. 129 Test 9: <151 gandalf:~/Thesis/scripts >./parser Please enter file to parse: Please enter security level Attack detected - 2 4153 Attack detected - 2 4174 <152 gandalf:~/Thesis/scripts > Test 9: exploit_xperl.doc: Jul 18 19:15:00 redhat62 kernel: UID: 500, PPID: 500, Jul 18 19:15:01 redhat62 kernel: 851, PID: 500, fsgid: Jul 18 Jul 18 Jul 18 Jul 18 894, suid: 500 Jul Jul Jul Jul 18 18 18 18 753, fsuid: Jul 18 19:15:00 redhat62 kernel: Jul 18 19:15:00 redhat62 kernel: suid: 500 19:15: 19:15: 19:15: 19:15: PPID: 500, 19: 19: 19: 19: 15: 15: 15: 15: 500, PPID: 847, 500, 01 01 01 03 875, fsuid: 03 03 03 O3 redhat62 redhat62 redhat62 redhat62 UID: 500, redhat62 redhat62 redhat62 redhat62 /usr/bin/suidperl Jul Jul Jul Jul Jul 18 18 18 18 18 19: 19: 19: 19: 19: 15: 15: 15: 15: 15: 03 O3 04 O4 04 redhat62 redhat62 redhat62 redhat62 redhat62 egid: fsuid: exec: /bin/sh, PID: 847, PUID: 500, euid: 500, suid: 500, sgid: 500, fsgid: 500 argv[0]: sh argv[l]: xperl.sh exec: /usr/bin/make, UID: 500, PUID: 500, euid: 500, egid: 500, sgid: 500, kernel: argv[0]: make kernel: argv[l]: bighole kernel: argv[2]: sush kernel: exec: /bin/nice, PID: 500, PUID: 500, euid: 500, egid: 500, sgid: 500, fsgid: kernel: argv[0]: nice kernel: argv[l]: -n kernel: argv[2]: +20 kernel: argv[3]: kernel: argv[4]: ./none kernel: kernel: ~1bighole kernel: kernel: 130 exploit_xperl.doc (1-4): 1 Jul 18 19:15:10 redhat62 kernel: open: ./flare, PID: 1179, PPID: 1141, UID: 500, PUID: 500, flags: 0, mode: 438, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 19:15:13 redhat62 kernel: exec: /bin/mail, PID: 1278, PPID: 1179, UID: O, PUID: 0, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 19:15:13 redhat62 kernel: argv[0]: /bin/mail Jul 18 19:15:13 redhat62 kernel: argv[l]: root Jul 18 19:15:18 redhat62 kernel: exec: /bin/bash, PID: 1505, PPID: 1278, UID: 0, PUID: 0, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 19:15:18 redhat62 kernel: argv[0]: /bin/bash Jul 18 19:15:18 redhat62 kernel: argv[l]: -c Jul 18 19:15:18 redhat62 kernel: argv[2]: bighole Jul 18 19:15:18 redhat62 kernel: exec: /bin/bash, PID: 1505, PPID: 1278, UID: 0, PUID: 0, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 18 19:15:18 redhat62 kernel: argv[0]: /bin/bash Jul 18 19:15:18 redhat62 kernel: argv[l]: -c Jul 18 19:15:18 redhat62 kernel: argv[2]: bighole Jul 18 19:15:19 redhat62 kernel: exec: ./sush, PID: 1612, PPID: 847, UID: 500, PUID: 500, euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: soo, fsgid: 500 Jul 18 19:15:19 redhat62 kernel: argv[0]: ./sush Jul 18 19:15:19 redhat62 kernel: exec: /bin/sh, PID: 1618, PPID: 1612, UID: 0, PUID: 0, euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 18 19:15:19 redhat62 kernel: argv[0]: sh Jul 18 19:15:19 redhat62 kernel: argv[l]: -c Jul 18 19:15:19 redhat62 kernel: argv[2]: /bin/bash 131 The logfile above shows a new sort Of exploit. This exploit makes use Of a bug in suidperl. We see that the IDS picks up two attacks, both Of type 2. If you lOOk at the last logfile block, we see a call to /bin/bash with U11) Of 0 and PUID Of 0. While this on the surface is fine, the IDS checks to make sure that the PUID really is 0. Notice that the PPID for this Open call to bash is 1612. If we look at the next to last block, we see an exec call tO ./sush has PID 1612. We also see that PID has a UID Of 500. If the PPID Of something is 1612 and the UID of this item is also 0, then the UID of PID 1612 must be 0. We see that the UID of PID 1612 is in fact 500. Note that we discovered two attacks. The second attack can be traced to the third from last block. Here, we see a call to /bin/bash with a UID and PUID Of 0. We again check to make sure the PUID is really 0. Checking the PPID, we find PPID = 1278. Checking PID 1278, we find the UID and PUID are both 0 (this is the 5th block from the bottom). We also notice that the PPID is 1179 for PID 1278. When we check PID 1179 (6th block from bottom), we see that the UID and PUID are both 500. SO in that chain, we managed tO go from UID Of 500 to UID of 0 without ever checking shadow. To make things even more suspicious, the PUID is inaccurate from the Open call tO ./flare (6th block from bottom) to the exec call tO fbin/mail (5th block from bottom). As it should, the IDS detects two exploits and raises two individual alarms. Even though both alarms are related tO the same exploit, we see that two shells were granted. To keep tabs on the OS, it's a good idea to report all individual shells granted as we are doing. 132 BZ - Parser Test For File-Based Exploits This section Offers various tests of how the IDS works with respect to detecting file-based intrusions. By file-based intrusions, I mean any exploit / intrusion which Operates by modifying critical system files. The common theme for most Of these tests is editing Of the shadow file. As mentioned before, while the parser itself guards against attacks made on the ‘shadow’ file itself and ignores most other file-based attacks, it is trivial to modify the parser tO catch attacks on any other file you wish to protect. The Linux kernel does not require any further modifications to catch other types of file-based exploits. I’m going tO divide this part into three sections based on which security level we are checking. As you recall from the source code overview and high-level logic overview, the file-exploit piece Of the parsing code Offers four levels Of security. Since the last level is essentially no protection, I have not Offered any tests Of this level. Suffice tO say it doesn’t flag any legitimate behavior as malicious. 133 82a — Security Level 1: Table 3 - File test - Security Level 1 Expected alarm (y/n) Result 0711) Test name no N (f1) run passwd and fail. (normal user) no N (12) run passwd and succeed. (normal user) no N (13) run passwd and succeed. (root user) no N (f4) run passwd and succeed. (normal user su'ed) no N (f5) run passwd on other user and succeed. (root) no N (f6) run passwd on other user and succeed. (su) yes Y (f7) directly edit shadow as root. (<<) yes Y (f8) directly edit shadow as su. (<<) yes Y (19) pico shadow as su. yes Y (fl 0) picO shadow as root. yes Y (fl 1) emacs shadow as su. yes Y (le) emacs shadow as root. yes Y (fl 3) touch shadow as su. yes Y (f14) touch shadow as root. no N (fl 5) picO shadow as normal user. (fail) no N (f16) emacs shadow as normal user. (fail) nO N (11 7) touch shadow as normal user. (fail) Yes Y (118) Cron tests. Yes Y (fl 9) xterm tests. (all_elements2.doc) Yes Y (120) su tests. (test_su.doc) Yes Y (121) extensive cron tests. (all_elementsdoc) Table 3: The above table shows which file-based tests were tried against the IDS. Here, I show both an expected result and an actual result. Note that we don’t want to raise an alarm against some Of the tests above. Note also that the IDS catches everything it’s expected to and doesn’t catch anything it’s not expected to catch. Test 1 and 2 run: <149 arctic:~/Thesis/scripts >./parser Please enter file to parse: test_1-2.doc Please enter security level (1-4): 1 <150 arctic:~/Thesis/scripts > 134 Test 1: Run passwd and fail. (normal user): Jul 13 00:56:56 localhost kernel: sys_access: Filename: /usr/bin/passwd, mode: 1, UID: 500, GID: 500 PID: 1403, PPID: 1401, UID: 500, PUID: 0 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 00:56:56 localhost kernel: sys_access: Filename: /usr/bin/passwd, mode: 1, UID: 500, GID: 500 PID: 1403, PPID: 1401, UID: 500, PUID: 0 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 00:56:56 localhost kernel: exec: /usr/bin/passwd, PID: 1440, PPID: 1403, UID: 500, PUID: 500 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 00:56:56 localhost kernel: argv[0]: passwd Jul 13 00:56:57 localhost kernel: open: /etc/shadow, PID: 1440, PPID: 1403, UID: 500, PUID: 500 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 13 00:57:00 localhost passwd(pam_unix)[1440]: authentication failure; logname=westrant uid=500 euid=0 tty= ruser= rhost= user=westrant Jul 13 00:57:00 localhost kernel: open: /etc/passwd, PID: 1440, PPID: 1403, UID: 500, PUID: 500 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: O, egid: 500, sgid: 500, fsgid: 500 Jul 13 00:57:00 localhost kernel: open: /etc/shadow, PID: 1440, PPID: 1403, UID: 500, PUID: 500 flags: 0, mode: 438 euid: 0, suid: O, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 In the above trace, a normal user tries to run passwd and doesn't authenticate. If you look at the 4th system call (Open: /etc/shadow), you'll notice that the flags value is 0. Since the last 2 bits Of flags are 00, shadow was not Opened for a write. Directly below this, we see that user westrant failed to authenticate. The parser doesn't use this information. The last call is an Open to shadow. Again, notice that the flags variable is 0. Since we didn't write anything to shadow, we will not set Off an alarm. As a note, it is acceptable for a standard (non-root) user to attempt tO view shadow. The file system 135 itself will not allow a user to view /etc/shadow unless they are already an administrative user, meaning they have already broken into our system. Test 2: Run passwd and succeed. (normal user): Jul 13 00:57:42 localhost kernel: exec: /usr/bin/passwd, PID: 1494, PPID: 1403, UID: 500, PUID: 500 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 00:57:42 localhost kernel: argv[0]: passwd Jul 13 00:57:43 localhost kernel: open: /etc/shadow, PID: 1494, PPID: 1403, UID: 500, PUID: 500 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 13 00:57:46 localhost kernel: open: /etc/passwd, PID: 1494, PPID: 1403, UID: 500, PUID: 500 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 13 00:57:46 localhost kernel: open: /etc/shadow, PID: 1494, PPID: 1403, UID: 500, PUID: 500 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 13 00:57:46 localhost kernel: open: /etc/passwd, PID: 1494, PPID: 1403, UID: 500, PUID: 500 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 13 00:57:46 localhost kernel: open: /etc/shadow, PID: 1494, PPID: 1403, UID: 500, PUID: 500 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 13 00:57:52 localhost kernel: open: /etc/shadow, PID: 1494, PPID: 1403, UID: 500, PUID: 500 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 13 00:57:52 localhost kernel: open: /etc/passwd, PID: 1494, PPID: 1403, UID: 500, PUID: 500 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 13 00:57:52 localhost kernel: open: /etc/passwd, PID: 1494, PPID: 1403, UID: 500, PUID: 500 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, 136 fsgid: 500 Jul 13 00:57:52 localhost kernel: open: /etc/shadow, PID: 1494, PPID: 1403, UID: 500, PUID: 500 flags: 0, mode: 438 euid: 0, suid: O, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 13 00:57:52 localhost kernel: open: /etc/nshadow, PID: 1494, PPID: 1403, UID: 500, PUID: 500 flags: 577, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 13 00:57:52 localhost kernel: open: /etc/shadow, PID: 1494, PPID: 1403, UID: 500, PUID: 500 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 500, sgid: 500, fsgid: 500 Jul 13 00:57:52 localhost kernel: chown: Filename: /etc/nshadow, UID: 0, GID: 0 Jul 13 00:57:52 localhost kernel: chmod: Filename: /etc/nshadow, mode: 33024 In the above trace, a normal (non-root) user successfully changes their password. If you lOOk at all Of the Opens to shadow, you'll notice that all of them have a flags value Of 0. This implies that none of the shadow Opens were writes. I would like to note the nshadow call. The script looks for an Open to nshadow which is prefaced with a call to passwd. The Open call to nshadow and the exec Of passwd both must have the same PID. All Of these are fine for the above logfile excerpt. Test 3 and 4 run: <153 arctic:~/Thesis/scripts >./parser Please enter file to parse: test_3-4.doc Please enter security level (1-4): 1 <154 arctic:~/Thesis/scripts > Test 3: Run passwd and succeed. (root user): 137 Jul 13 02:13:48 localhost kernel: sys_access: Filename: /usr/bin/passwd, mode: 1, UID: 0, GID: 0 PID: 1047, PPID: 1044, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:13:48 localhost kernel: sys_access: Filename: /usr/bin/passwd, mode: 1, UID: 0, GID: 0 PID: 1047, PPID: 1044, UID: 0, PUID: 0 euid: O, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:13:48 localhost kernel: exec: /usr/bin/passwd, PID: 1090, PPID: 1047, UID: O, PUID: O euid: O, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:13:48 localhost kernel: argv[0]: passwd Jul 13 02:13:48 localhost kernel: open: /etc/passwd, PID: 1090, PPID: 1047, UID: 0, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:13:48 localhost kernel: open: /etc/shadow, PID: 1090, PPID: 1047, UID: O, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:13:48 localhost kernel: open: /etc/passwd, PID: 1090, PPID: 1047, UID: 0, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:13:48 localhost kernel: open: /etc/shadow, PID: 1090, PPID: 1047, UID: 0, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:13:52 localhost kernel: open: /etc/shadow, PID: 1090, PPID: 1047, UID: 0, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: O, egid: O, sgid: 0, fsgid: 0 Jul 13 02:13:52 localhost kernel: open: /etc/passwd, PID: 1090, PPID: 1047, UID: 0, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:13:52 localhost kernel: open: /etc/passwd, PID: 1090, PPID: 1047, UID: O, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:13:52 localhost kernel: open: /etc/shadow, PID: 1090, PPID: 1047, UID: 0, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:13:52 localhost kernel: open: /etc/nshadow, PID: 1090, PPID: 1047, UID: 0, PUID: 0 flags: 577, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:13:52 localhost kernel: open: /etc/shadow, PID: 1090, PPID: 1047, UID: 0, PUID: 0 flags: 0, mode: 438 euid: O, suid: O, fsuid: 0, egid: O, sgid: 0, fsgid: 0 Jul 13 02:13:52 localhost kernel: chown: Filename: 138 /etc/nshadow, UID: 0, GID: 0 Jul 13 02:13:52 localhost kernel: chmod: Filename: /etc/nshadow, mode: 33024 In the above logfile, root successfully changes their own password. Again note that the flags value for all Open calls tO shadow are 0, implying we're not writing directly to shadow. The nshadow with flags of 577 shows we successfully updated shadow via a write to nshadow. Since passwd was run and passwd has the same PID as the Open / write to nshadow, we allow the Operation and don't ring the alarm. Test 4: Run passwd and succeed. (normal user su'ed): Jul 13 02:14:06 localhost kernel: sys_access: Filename: /usr/bin/passwd, mode: 1, UID: 0, GID: 0 PID: 1096, PPID: 1092, UID: 0, PUID: 500 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:14:06 localhost kernel: sys_access: Filename: /usr/bin/passwd, mode: 1, UID: 0, GID: 0 PID: 1096, PPID: 1092, UID: 0, PUID: 500 euid: O, suid: 0, fsuid: O, egid: 0, sgid: O, fsgid: 0 Jul 13 02:14:06 localhost kernel: exec: /usr/bin/passwd, PID: 1130, PPID: 1096, UID: 0, PUID: 0 euid: O, suid: 0, fsuid: 0, egid: 0, sgid: O, fsgid: 0 Jul 13 02:14:06 localhost kernel: argv[0]: passwd Jul 13 02:14:06 localhost kernel: open: /etc/passwd, PID: 1130, PPID: 1096, UID: 0, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:14:06 localhost kernel: open: /etc/shadow, PID: 1130, PPID: 1096, UID: O, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:14:06 localhost kernel: open: /etc/passwd, PID: 1130, PPID: 1096, UID: 0, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:14:06 localhost kernel: open: /etc/shadow, PID: 1130, PPID: 1096, UID: O, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 139 Jul 13 02:14:09 localhost kernel: open: /etc/shadow, PID: 1130, PPID: 1096, UID: 0, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:14:09 localhost kernel: open: /etc/passwd, PID: 1130, PPID: 1096, UID: 0, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:14:09 localhost kernel: open: /etc/passwd, PID: 1130, PPID: 1096, UID: O, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: O, sgid: 0, fsgid: 0 Jul 13 02:14:09 localhost kernel: open: /etc/shadow, PID: 1130, PPID: 1096, UID: 0, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:14:09 localhost kernel: open: /etc/nshadow, PID: 1130, PPID: 1096, UID: 0, PUID: 0 flags: 577, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:14:09 localhost kernel: open: /etc/shadow, PID: 1130, PPID: 1096, UID: 0, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:14:09 localhost kernel: chown: Filename: /etc/nshadow, UID: 0, GID: 0 Jul 13 02:14:09 localhost kernel: chmod: Filename: /etc/nshadow, mode: 33024 In the above trace, a normal user successfully runs SU, then runs passwd to change root's password. This trace is the same as the previous 3, so little commentary will be Offered. Again, note how no alarm was raised, even though another instance Of passwd was encountered by the script. Had this new PID not been recorded, an alarm would've been raised for the above /etc/nshadow write. Test 5 and 6 run: <133 arctic:~/Thesis/scripts >./parser Please enter file to parse: test_5—6.doc Please enter security level (1-4): 1 <134 arctic:~/Thesis/scripts > 140 Test 5: Run passwd on other user and succeed (root): Jul 13 02:56:31 localhost kernel: sys_access: Filename: /usr/bin/passwd, mode: 1, UID: 0, GID: 0 PID: 1072, PPID: 1070, UID: O, PUID: 0 euid: 0, suid: 0, fsuid: O, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:56:31 localhost kernel: sys_access: Filename: /usr/bin/passwd, mode: 1, UID: 0, GID: 0 PID: 1072, PPID: 1070, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:56:31 localhost kernel: exec: /usr/bin/passwd, PID: 1115, PPID: 1072, UID: O, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:56:31 localhost kernel: Jul 13 02:56:31 localhost kernel: Jul 13 02:56:31 localhost kernel: 1115, PPID: 1072, UID: 0, PUID: euid: 0, suid: 0, fsuid: 0, egid: Jul 13 02:56:31 localhost kernel: 1115, PPID: 1072, UID: 0, PUID: euid: 0, suid: 0, fsuid: 0, egid: Jul 13 02:56:31 localhost kernel: 1115, PPID: 1072, UID: 0, PUID: euid: 0, suid: 0, fsuid: 0, egid: Jul 13 02:56:43 localhost kernel: 1115, PPID: 1072, UID: 0, PUID: euid: 0, suid: 0, fsuid: 0, egid: Jul 13 02:56:43 localhost kernel: 1115, PPID: 1072, UID: 0, PUID: euid: 0, suid: 0, fsuid: 0, egid: Jul 13 02:56:43 localhost kernel: 1115, PPID: 1072, UID: O, PUID: euid: 0, suid: 0, fsuid: 0, egid: Jul 13 02:56:43 localhost kernel: 1115, PPID: 1072, UID: 0, PUID: euid: 0, suid: 0, fsuid: 0, egid: Jul 13 02:56:43 localhost kernel: 1115, PPID: 1072, UID: 0, PUID: 438 euid: 0, suid: 0, fsuid: O, 0 Jul 13 02:56:43 localhost kernel: 1115, PPID: 1072, UID: 0, PUID: euid: 0, suid: 0, fsuid: 0, egid: 141 argv[0]: passwd argv[l]: westrant PID: 438 open: /etc/shadow, 0 flags: 0, mode: 0, sgid: 0, fsgid: 0 open: /etc/passwd, 0 flags: 0, mode: 0, sgid: 0, fsgid: 0 open: /etc/shadow, 0 flags: 0, mode: 0, sgid: 0, fsgid: 0 PID: 438 PID: 438 PID: 438 /etc/shadow, 0 flags: 0, mode: 0, sgid: 0, fsgid: 0 open: /etc/passwd, 0 flags: 0, mode: 0, sgid: 0, fsgid: 0 open: /etc/passwd, 0 flags: 0, mode: 0, sgid: 0, fsgid: 0 open: /etc/shadow, 0 flags: 0, mode: 0, sgid: 0, fsgid: 0 open: /etc/nshadow, PID: 0 flags: 577, mode: egid: 0, sgid: O, fsgid: open: PID: 438 PID: 438 PID: 438 PID: 438 /etc/shadow, 0, mode: fsgid: 0 open: 0 flags: 0, sgid: 0, Jul 13 02:56:43 localhost kernel: /etc/nshadow, UID: 0, GID: 0 Jul 13 02:56:43 localhost kernel: /etc/nshadow, mode: 33024 chown: Filename: chmod: Filename: In the above script, root logs in and runs passwd with westrant as the user. The 3rd line above shows the command run. Again here, nshadow is the only thing Opened for write, and passwd has the same PID as nshadow. NO alarm is rung. Test 6: Run passwd on other user and succeed (su): Jul 13 02:57:30 localhost kernel: PID: 1189, PPID: 1160, UID: 0, 0, fsuid: 0, egid: O, sgid: 0, Jul 13 02:57:30 localhost kernel: Jul 13 02:57:30 localhost kernel: Jul 13 02:57:31 localhost kernel: 1189, PPID: 1160, UID: 0, PUID: euid: 0, suid: 0, fsuid: 0, egid: Jul 13 02:57:31 localhost kernel: 1189, PPID: 1160, UID: O, PUID: euid: 0, suid: 0, fsuid: 0, egid: Jul 13 02:57:31 localhost kernel: 1189, PPID: 1160, UID: 0, PUID: euid: O, suid: 0, fsuid: 0, egid: Jul 13 02:57:39 localhost kernel: 1189, PPID: 1160, UID: 0, PUID: euid: O, suid: 0, fsuid: O, egid: Jul 13 02:57:39 localhost kernel: 1189, PPID: 1160, UID: 0, PUID: euid: 0, suid: 0, fsuid: 0, egid: Jul 13 02:57:39 localhost kernel: 1189, PPID: 1160, UID: 0, PUID: euid: 0, suid: 0, fsuid: 0, egid: Jul 13 02:57:39 localhost kernel: 1189, PPID: 1160, UID: O, PUID: euid: 0, suid: O, fsuid: 0, egid: Jul 13 02:57:39 localhost kernel: 142 exec: /usr/bin/passwd, PUID: 0 euid: 0, suid: fsgid: 0 argv[0]: passwd argv[l]: westrant open: /etc/shadow, PID: 0 flags: 0, mode: 438 O, sgid: 0, fsgid: 0 open: /etc/passwd, PID: 0 flags: 0, mode: 438 0, sgid: 0, fsgid: 0 open: /etc/shadow, PID: 0 flags: 0, mode: 438 0, sgid: O, fsgid: 0 open: /etc/shadow, PID: 0 flags: 0, mode: 438 0, sgid: 0, fsgid: 0 open: /etc/passwd, PID: 0 flags: 0, mode: 438 0, sgid: 0, fsgid: 0 open: /etc/passwd, PID: 0 flags: 0, mode: 438 0, sgid: 0, fsgid: 0 open: /etc/shadow, PID: 0 flags: 0, mode: 438 O, sgid: O, fsgid: 0 open: /etc/nshadow, PID: 1189, PPID: 1160, UID: 0, PUID: 0 flags: 577, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:57:39 localhost kernel: open: /etc/shadow, PID: 1189, PPID: 1160, UID: 0, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:57:39 localhost kernel: chown: Filename: /etc/nshadow, UID: 0, GID: 0 Jul 13 02:57:39 localhost kernel: chmod: Filename: /etc/nshadow, mode: 33024 In the above log excerpt, a normal user logs in, successfully runs SU, and runs passwd on the user account westrant. From the first line Of the script, we can see the passwd command. Again, the only command where a write is done is with the nshadow. Since the PID for the Open and write on nshadow is the same as the PID on passwd, no ahnnknmng Moving onto some tests where the alarm is rung for various reasons. Test 7 and 8 run: <143 gandalf:~/Thesis/scripts >./parser Please enter file to parse: test_7-8.doc Please enter security level (1-4): 1 ALARM!!! level of 1 selected shadow changed without the use of passwd file: shadow, pid: 1194 ALARM!!! level of 1 selected shadow changed without the use of passwd file: shadow, pid: 1290 <144 gandalf:~/Thesis/scripts > As it should, the script caught both examples Of editing shadow directly without 143 the use Of passwd. Test 7: Directly edit shadow as root (< <): Jul 13 02:57:57 localhost kernel: open: /dev/tty, PID: 1194, PPID: 1192, UID: 0, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: O, fsgid: 0 Jul 13 02:57:57 localhost kernel: open: /dev/tty, PID: 1194, PPID: 1192, UID: 0, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:57:57 localhost kernel: open: /dev/pts/0, PID: 1194, PPID: 1192, UID: 0, PUID: 0 flags: 32770, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:57:57 localhost kernel: open: /dev/tty, PID: 1194, PPID: 1192, UID: 0, PUID: 0 flags: 32769, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 03:10:29 localhost kernel: open: shadow, PID: 1194, PPID: 1192, UID: 0, PUID: 0 flags: 33857, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 In the above script, I logged in as root and gave the command: echo "bobrulez" >> /etc/shadow. SO the logfile should show that passwd was never run and shadow was modified. Above, we see that the flags for shadow have 01 as the last two bits. The PID Of the shadow edit is linked directly to the TTY session, so we can be assured this is not a script. However since this is level 1, all we care about is that something changed shadow without using passwd. Test 8: Directly edit shadow as su (< <): Jul 13 03:09:56 localhost kernel: open: /dev/tty, PID: 1248, PPID: 1245, UID: O, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 144 Jul 13 03:09:56 localhost kernel: open: /dev/tty, PID: 1248, PPID: 1245, UID: 0, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 03:09:57 localhost kernel: open: /dev/pts/1, PID: 1248, PPID: 1245, UID: O, PUID: 0 flags: 32770, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 03:09:57 localhost kernel: open: /dev/tty, PID: 1248, PPID: 1245, UID: 0, PUID: 0 flags: 32769, mode: 0 euid: 0, suid: 0, fsuid: O, egid: 0, sgid: O, fsgid: 0 Jul 13 03:10:33 localhost kernel: exec: /bin/su, PID: 1286, PPID: 1248, UID: 500, PUID: 500 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 03:10:33 localhost kernel: argv[0]: su Jul 13 03:10:36 localhost kernel: open: /root/.bash_history, PID: 1290, PPID: 1286, UID: 0, PUID: 500 flags: 32768, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 03:10:46 localhost kernel: open: shadow, PID: 1290, PPID: 1286, UID: 0, PUID: 500 flags: 33857, mode: 438 euid: 0, suid: 0, fsuid: O, egid: 0, sgid: 0, fsgid: 0 The above script shows a normal user logging into pts/l, successfully running SU, and editing shadow with the command: echo "bobrulezZ" >> /etc/shadow We know that the SU Operation was successful by seeing the Open to /.bash_history. Note how PID's and PPID's are working above, in particular note how the PPID of the Open shadow call points tO the SU instruction, not the original TTY session. What I'm doing is watching for a successful SU. Once I see that the user has successfully run SU, I allow an extension Of PID's. This comes into play later for determining whether or not shadow was edited by a script or a user. 145 Tests 9 - l4: <148 gandalf:~/Thesis/scripts >./parser Please enter file to parse: test_9-14.doc Please enter security level (1-4): 1 ALARM!!! level of 1 selected shadow changed without the use of passwd file: shadow, pid: 1604 ALARM!!! level of 1 selected shadow changed without the use of passwd file: /etc/shadow, pid: 1607 ALARM!!! level of 1 selected shadow changed without the use of passwd file: shadow, pid: 1610 ALARM!!! level of 1 selected shadow changed without the use of passwd file: shadow, pid: 1691 ALARM!!! level of 1 selected shadow changed without the use of passwd file: /etc/shadow, pid: 1694 ALARM!!! level of 1 selected shadow changed without the use of passwd file: shadow, pid: 1697 <149 gandalf:~/Thesis/scripts > Test 9: Pico shadow as root: ALARM!!! level of 1 selected shadow changed without the use of passwd file: shadow, pid: 1604 Jul 13 08:57:33 localhost kernel: open: /dev/tty, 0 flags: egid: UID: 0. PPID: 0, 1558, 0 euid: 1556, suid: 0. fsuid: Jul 13 08:57:33 localhost kernel: open: /dev/tty, PUID: 0. 146 0. 1558, PPID: 1556, UID: O, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: O, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:57:33 localhost kernel: open: /dev/pts/0, PID: 1558, PPID: 1556, UID: 0, PUID: 0 flags: 32770, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:57:33 localhost kernel: open: /dev/tty, PID: 1558, PPID: 1556, UID: 0, PUID: 0 flags: 32769, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:58:55 localhost kernel: exec: /usr/bin/pico, PID: 1604, PPID: 1558, UID: O, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: O, sgid: 0, fsgid: 0 Jul 13 08:58:55 localhost kernel: argv[0]: pico Jul 13 08:58:55 localhost kernel: argv[l]: shadow Jul 13 08:58:56 localhost kernel: sys_access: Filename: shadow, mode: 4, UID: 0, GID: 0 PID: 1604, PPID: 1558, UID: 0, PUID: O euid: O, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:58:56 localhost kernel: open: shadow, PID: 1604, PPID: 1558, UID: 0, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:58:58 localhost kernel: open: shadow, PID: 1604, PPID: 1558, UID: O, PUID: 0 flags: 65, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Test 10: Emacs shadow as root: ALARM!!! level of 1 selected shadow changed without the use of passwd file: /etc/shadow, pid: 1607 Jul 13 08:57:33 localhost kernel: open: /dev/tty, PID: 1558, PPID: 1556, UID: O, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:57:33 localhost kernel: open: /dev/tty, PID: 1558, PPID: 1556, UID: 0, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:57:33 localhost kernel: open: /dev/pts/O, PID: 1558, PPID: 1556, UID: O, PUID: 0 flags: 32770, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:57:33 localhost kernel: open: /dev/tty, PID: 1558, PPID: 1556, UID: 0, PUID: 0 flags: 32769, mode: 147 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:59:05 localhost kernel: exec: /usr/bin/emacs, PID: 1607, PPID: 1558, UID: 0, PUID: 0 euid: O, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:59:05 localhost kernel: argv[0]: emacs Jul 13 08:59:05 localhost kernel: argv[l]: shadow Jul 13 08:59:15 localhost kernel: open: /etc/shadow, PID: 1607, PPID: 1558, UID: O, PUID: 0 flags: 33345, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Test 1 l .' Touch shadow as root: ALARM!!! level of 1 selected shadow changed without the use of passwd file: shadow, pid: 1610 Jul 13 08:57:33 localhost kernel: open: /dev/tty, PID: 1558, PPID: 1556, UID: 0, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:57:33 localhost kernel: open: /dev/tty, PID: 1558, PPID: 1556, UID: O, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: O, fsgid: 0 Jul 13 08:57:33 localhost kernel: open: /dev/pts/0, PID: 1558, PPID: 1556, UID: 0, PUID: 0 flags: 32770, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:57:33 localhost kernel: open: /dev/tty, PID: 1558, PPID: 1556, UID: O, PUID: 0 flags: 32769, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:59:28 localhost kernel: exec: /bin/touch, PID: 1610, PPID: 1558, UID: 0, PUID: 0 euid: O, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:59:28 localhost kernel: argv[0]: touch Jul 13 08:59:28 localhost kernel: argv[l]: shadow Jul 13 08:59:28 localhost kernel: open: shadow, PID: 1610, PPID: 1558, UID: 0, PUID: 0 flags: 35137, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 148 Test 12: Pico shadow as su: ALARM!!! level of 1 selected shadow changed without the use of passwd file: shadow, pid: 1691 Jul 13 08:59:56 localhost kernel: open: /dev/tty, PID: 1622, PPID: 1619, UID: 0, PUID: 0 flags: 33026, mode: 0 euid: O, suid: 0, fsuid: 0, egid: O, sgid: 0, fsgid: 0 Jul 13 08:59:56 localhost kernel: open: /dev/tty, PID: 1622, PPID: 1619, UID: O, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:59:56 localhost kernel: open: /dev/pts/1, PID: 1622, PPID: 1619, UID: O, PUID: 0 flags: 32770, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:59:56 localhost kernel: open: /dev/tty, PID: 1622, PPID: 1619, UID: O, PUID: 0 flags: 32769, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:59:57 localhost kernel: sys_access: Filename: /bin/su, mode: 1, UID: 500, GID: 500 PID: 1622, PPID: 1619, UID: 500, PUID: O euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 08:59:57 localhost kernel: sys_access: Filename: /bin/su, mode: 1, UID: 500, GID: 500 PID: 1622, PPID: 1619, UID: 500, PUID: 0 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 08:59:57 localhost kernel: exec: /bin/su, PID: 1658, PPID: 1622, UID: 500, PUID: 500 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 08:59:57 localhost kernel: argv[0]: su Jul 13 09:00:14 localhost kernel: exec: /usr/bin/pico, PID: 1691, PPID: 1662, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 09:00:14 localhost kernel: argv[0]: pico Jul 13 09:00:14 localhost kernel: argv[1]: shadow Jul 13 09:00:14 localhost kernel: open: shadow, PID: 1691, PPID: 1662, UID: O, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 09:00:15 localhost kernel: open: shadow, PID: 1691, 149 PPID: 1662, UID: O, PUID: 0 flags: 65, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 lhst13: lbnacsshadbuzassu: ALARM!!! level of 1 selected shadow changed without the use of passwd file: /etc/shadow, pid: 1694 Jul 13 08:59:56 localhost kernel: open: /dev/tty, PID: 1622, PPID: 1619, UID: 0, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: O, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:59:56 localhost kernel: open: /dev/tty, PID: 1622, PPID: 1619, UID: 0, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:59:56 localhost kernel: open: /dev/pts/1, PID: 1622, PPID: 1619, UID: 0, PUID: 0 flags: 32770, mode: 0 euid: O, suid: 0, fsuid: 0, egid: O, sgid: 0, fsgid: 0 Jul 13 08:59:56 localhost kernel: open: /dev/tty, PID: 1622, PPID: 1619, UID: 0, PUID: 0 flags: 32769, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 08:59:57 localhost kernel: sys_access: Filename: /bin/su, mode: 1, UID: 500, GID: 500 PID: 1622, PPID: 1619, UID: 500, PUID: 0 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 08:59:57 localhost kernel: sys_access: Filename: /bin/su, mode: 1, UID: 500, GID: 500 PID: 1622, PPID: 1619, UID: 500, PUID: 0 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 08:59:57 localhost kernel: exec: /bin/su, PID: 1658, PPID: 1622, UID: 500, PUID: 500 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 08:59:57 localhost kernel: argv[0]: su Jul 13 09:00:22 localhost kernel: exec: /usr/bin/emacs, PID: 1694, PPID: 1662, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 09:00:22 localhost kernel: argv[0]: emacs Jul 13 09:00:22 localhost kernel: argv[1]: shadow Jul 13 09:00:33 localhost kernel: open: /etc/shadow, PID: 1694, PPID: 1662, UID: O, PUID: 0 flags: 33345, mode: 150 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 09:00:33 localhost kernel: chmod: Filename: /etc/shadow, mode: 256 Test 14: Touch shadow as su: ALARM!!! level of 1 selected shadow changed without the use of passwd file: shadow, pid: 1697 Jul 13 08:59: 1622, PPID: 0 euid: 0, Jul 13 08:59 1622, PPID: O euid: 0, Jul 13 08:59 1622, PPID: 0 euid: 0, Jul 13 08:59: 1622, PPID: O euid: 0, 1619, suid: 0, UID: 0, PUID: 0 fsuid: 0, egid: 0, 1619, suid: 0, UID: O, PUID: O fsuid: 0, egid: 0, flags: 1619, suid: 0, UID: 0, PUID: 0 fsuid: 0, egid: 0, flags: 1619, suid: 0, UID: 0, PUID: O fsuid: 0, egid: 0, flags: Jul 13 08:59:57 localhost kernel: sys_access: /bin/su, mode: 1, UID: 500, GID: 500 PID: 1622, PPID: 1619, UID: 500, PUID: 0 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 08:59:57 localhost kernel: sys_access: Filename: /bin/su, mode: 1, UID: 500, GID: 500 PID: 1622, PPID: 1619, UID: 500, PUID: 0 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 08:59:57 localhost kernel: exec: /bin/su, PID: 1658, PPID: 1622, UID: 500, PUID: 500 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 08:59:57 localhost kernel: Jul 13 09:00:42 localhost kernel: 56 localhost kernel: open: /dev/tty, flags: 33026, sgid: :56 localhost kernel: open: /dev/tty, 33026, sgid: :56 localhost kernel: open: /dev/pts/1, 32770, sgid: 0, 56 localhost kernel: open: /dev/tty, 32769, sgid: sys_access: PID: mode: 0, fsgid: 0 PID: mode: 0, fsgid: 0 PID: mode: fsgid: 0 PID: mode: 0, fsgid: 0 Filename: argv[0]: su Filename: /bin/touch, mode: 1, UID: 0, GID: 0 PID: 1662, PPID: 1658, UID: 0, PUID: 500 euid: O, suid: O, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 09:00:42 localhost kernel: /bin/touch, mode: 1, UID: 0, GID: 0 151 sys_access : Filename: PID: 1662, PPID: 1658, UID: O, PUID: 500 euid: 0, suid: O, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 09:00:42 localhost kernel: exec: /bin/touch, PID: 1697, PPID: 1662, UID: 0, PUID: 0 euid: O, suid: 0, fsuid: 0, egid: O, sgid: 0, fsgid: 0 Jul 13 09:00:42 localhost kernel: argv[0]: touch Jul 13 09:00:42 localhost kernel: argv[1]: shadow Jul 13 09:00:42 localhost kernel: open: shadow, PID: 1697, PPID: 1662, UID: O, PUID: 0 flags: 35137, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Test 15 -17: <163 gandalf:~/Thesis/scripts >./parser Please enter file to parse: test_15—17.doc Please enter security level (1-4): 1 <164 gandalf:~/Thesis/scripts > Test 15: Pico shadow as normal user (Fail): Jul 13 09:19:48 localhost kernel: open: /dev/tty, PID: 1704, PPID: 1702, UID: O, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 09:19:48 localhost kernel: open: /dev/tty, PID: 1704, PPID: 1702, UID: 0, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: O, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 09:19:48 localhost kernel: open: /dev/pts/0, PID: 1704, PPID: 1702, UID: O, PUID: 0 flags: 32770, mode: 0 euid: 0, suid: O, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 09:19:48 localhost kernel: open: /dev/tty, PID: 1704, PPID: 1702, UID: 0, PUID: 0 flags: 32769, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 09:23:56 localhost kernel: sys_access: Filename: /usr/bin/pico, mode: 1, UID: 500, GID: 500 PID: 1704, PPID: 1702, UID: 500, PUID: 0 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 09:23:56 localhost kernel: sys_access: Filename: 152 /usr/bin/pico, mode: 1, UID: 500, GID: 500 PID: 1704, PPID: 1702, UID: 500, PUID: 0 euid: 500, euid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 09:23:56 localhost kernel: exec: /usr/bin/pico, PID: 1744, PPID: 1704, UID: 500, PUID: 500 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 09:23:56 localhost kernel: argv[0]: pico Jul 13 09:23:56 localhost kernel: argv[1]: shadow Jul 13 09:23:56 localhost kernel: sys_access: Filename: shadow, mode: 4, UID: 500, GID: 500 PID: 1744, PPID: 1704, UID: 500, PUID: 500 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Note the absence of the actual Open call to shadow. The file system prevents any user with UID != 0 from Opening shadow. Test 16: Emacs shadow as normal user (fail): Jul 13 09:19:48 localhost kernel: open: /dev/tty, PID: 1704, PPID: 1702, UID: 0, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 09:19:48 localhost kernel: open: /dev/tty, PID: 1704, PPID: 1702, UID: 0, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 09:19:48 localhost kernel: open: /dev/pts/0, PID: 1704, PPID: 1702, UID: 0, PUID: 0 flags: 32770, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 09:19:48 localhost kernel: open: /dev/tty, PID: 1704, PPID: 1702, UID: 0, PUID: 0 flags: 32769, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 09:24:05 localhost kernel: sys_access: Filename: /usr/bin/emacs, mode: 1, UID: 500, GID: 500 PID: 1704, PPID: 1702, UID: 500, PUID: 0 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 09:24:05 localhost kernel: sys_access: Filename: /usr/bin/emacs, mode: 1, UID: 500, GID: 500 PID: 1704, PPID: 1702, UID: 500, PUID: O euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 153 Jul 13 09:24:05 localhost kernel: exec: /usr/bin/emacs, PID: 1747, PPID: 1704, UID: 500, PUID: 500 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 09:24:05 localhost kernel: argv[0]: emacs Jul 13 09:24:05 localhost kernel: argv[1]: shadow Jul 13 09:24:08 localhost kernel: open: /etc/shadow, PID: 1747, PPID: 1704, UID: 500, PUID: 500 flags: 32768, mode: 0 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 09:24:14 localhost kernel: sys_access: Filename: /etc/shadow, mode: 2, UID: 500, GID: 500 PID: 1747, PPID: 1704, UID: 500, PUID: 500 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 09:24:17 localhost kernel: open: /etc, PID: 1747, PPID: 1704, UID: 500, PUID: 500 flags: 100352, mode: 0 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 09:24:17 localhost kernel: open: /etc/shadow, PID: 1747, PPID: 1704, UID: 500, PUID: 500 flags: 32768, mode: 0 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 09:24:17 localhost kernel: sys_access: Filename: /etc/shadow~, mode: 2, UID: 500, GID: 500 PID: 1747, PPID: 1704, UID: 500, PUID: 500 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 09:24:18 localhost kernel: open: /etc/shadow, PID: 1747, PPID: 1704, UID: 500, PUID: 500 flags: 32768, mode: 0 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 09:24:18 localhost kernel: open: /etc/shadow, PID: 1747, PPID: 1704, UID: 500, PUID: 500 flags: 32768, mode: 0 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 In the above logfile, note how all Of the Opens to shadow all have 00 in the last two bits. This ensures us that shadow was only Opened for a read. Besides, with a UID Of 500 Opening shadow, we can be assured the file will not be displayed. 154 Test 17: Touch shadow as normal user (fail): Jul 13 09:19:48 localhost kernel: open: /dev/tty, PID: 1704, PPID: 1702, UID: O, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: O, sgid: 0, fsgid: 0 Jul 13 09:19:48 localhost kernel: open: /dev/tty, PID: 1704, PPID: 1702, UID: 0, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 09:19:48 localhost kernel: open: /dev/pts/0, PID: 1704, PPID: 1702, UID: 0, PUID: 0 flags: 32770, mode: . 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 | Jul 13 09:19:48 localhost kernel: open: /dev/tty, PID: 1704, PPID: 1702, UID: 0, PUID: 0 flags: 32769, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 09:24:29 localhost kernel: sys_access: Filename: /bin/touch, mode: 1, UID: 500, GID: 500 PID: 1704, PPID: 1702, UID: 500, PUID: 0 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 09:24:29 localhost kernel: sys_access: Filename: /bin/touch, mode: 1, UID: 500, GID: 500 PID: 1704, PPID:1702, UID: 500, PUID: 0 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 09:24:29 localhost kernel: exec: /bin/touch, PID: 1749, PPID: 1704, UID: 500, PUID: 500 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 09:24:29 localhost kernel: argv[0]: touch Jul 13 09:24:29 localhost kernel: argv[1]: shadow Jul 13 09:24:29 localhost kernel: open: shadow, PID: 1749, PPID: 1704, UID: 500, PUID: 500 flags: 35137, mode: 438 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 In the above script, it almost looks as if UID 500 successfully Opened shadow (flags: last two bits: 01). However the file system has denied access. For a normal user tO access letc/shadow, they would either have to break the file system itself or else gain root access. 155 Test 18: various cronjobs <132 gandalf:~/Thesis/scripts >./parser Please enter file to parse: newrun2.doc Please enter security level (1-4): 1 ALARM!!! level of 1 selected shadow changed without the use of passwd file: /etc/shadow, pid: 1719 ALARM!!! level of 1 selected shadow changed without the use of passwd file: /etc/shadow, pid: 1721 ALARM!!! level of 1 selected shadow changed without the use of passwd file: /etc/shadow, pid: 1722 <133 gandalf:~/Thesis/scripts >ls // First alarm: Jul 11 23:50:50 localhost kernel: exec: /etc/cron.daily/shadow1, PID: 1719, PPID: 1430, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 11 23:50:50 localhost kernel: argv[0]: /etc/cron.daily/shadow1 Jul 11 23:50:51 localhost kernel: open: /etc/cron.daily/shadow1, PID: 1719, PPID: 1430, UID: 0, PUID: 0 flags: 32768, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 11 23:50:51 localhost kernel: open: /etc/shadow, PID: 1719, PPID: 1430, UID: 0, PUID: 0 flags: 33857, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 // Second alarm: Jul 11 23:50:51 localhost kernel: sys_access: Filename: /bin/touch, mode: 1, UID: 0, GID: 0 PID: 1719, PPID: 1430, UID: O, PUID: O euid: O, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 156 Jul 11 23:50:51 localhost kernel: sys_access: Filename: /bin/touch, mode: 1, UID: 0, GID: 0 PID: 1719, PPID: 1430, UID: 0, PUID: 0 euid: 0, suid: O, fsuid: O, egid: 0, sgid: 0, fsgid: 0 Jul 11 23:50:51 localhost kernel: exec: /bin/touch, PID: 1721, PPID: 1719, UID: O, PUID: 0 euid: O, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 11 23:50:51 localhost kernel: argv[0]: touch Jul 11 23:50:51 localhost kernel: argv[1]: /etc/shadow Jul 11 23:50:51 localhost kernel: open: /etc/shadow, PID: 1721, PPID: 1719, UID: O, PUID: 0 flags: 35137, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: O ”Thhdahnn: Jul 11 23:50:51 localhost kernel: open: /etc/cron.daily/filenew, PID: 1719, PPID: 1430, UID: 0, PUID: 0 flags: 33857, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 11 23:50:52 localhost kernel: open: /etc/rc.d/filenew2, PID: 1719, PPID: 1430, UID: O, PUID: 0 flags: 33857, mode: 438 euid: O, suid: 0, fsuid: 0, egid: O, sgid: 0, fsgid: 0 Jul 11 23:50:52 localhost kernel: exec: ./root/shadow1, PID: 1722, PPID: 1719, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 11 23:50:52 localhost kernel: argv[0]: ./root/shadow1 Jul 11 23:50:52 localhost kernel: open: ./root/shadow1, PID: 1722, PPID: 1719, UID: 0, PUID: 0 flags: 32768, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 11 23:50:52 localhost kernel: open: /etc/shadow, PID: 1722, PPID: 1719, UID: O, PUID: 0 flags: 33857, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 The following two cronjobs produced the above trace: This is: /etc/cron.daily/shadowl: #!/bin/bash echo "crapl" >> /etc/shadow touch /etc/shadow echo "junk12" >> /etc/cron.daily/filenew 157 echo "junk14" >> /etc/rc.d/filenew2 cd /root ./shadow1 /etc/shadow exit 0 This is: /root/shadow1: #!/bin/bash echo "crap2" >> /etc/shadow exit 0 Our script detects three improper writes to shadow. Since this is a cronjob, none Of the writes to shadow are attached to a TTY session. The first alarm is raised when we echo "crap" into /etc/shadow. The second alarm is raised when we touch /etc/shadow. The third alarm is raised when we echo "crap2" into shadow from our second cron job. We don't detect any Of the writes tO files within /etc/cron.* or /etc/rc*. We also don't care where the cronjob runs from. At level 1, all we care about is that something other than root was able to write to shadow. Test 19: <166 gandalf:~/Thesis/scripts >./parser Please enter file to parse: all_element82.doc Please enter security level (1—4): 1 ALARM!!! level of 1 selected shadow changed without the use of passwd file: shadow, pid: 1950 ALARM!!! level of 1 selected shadow changed without the use of passwd 158 file: shadow, pid: 1952 ALARM!!! level of 1 selected shadow changed without the use of passwd file: shadow, pid: 2072 //Alarm for PID 1950: Jul 13 20:35:22 localhost kernel: sys_access: Filename: /usr/X11R6/bin/xterm, mode: 1, UID: 0, GID: 0 PID: 1864, PPID: 1862, UID: 0, PUID: 0 euid: O, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 20:35:22 localhost kernel: sys_access: Filename: /usr/X11R6/bin/xterm, mode: 1, UID: 0, GID: 0 PID: 1864, PPID: 1862, UID: O, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 20:35:22 localhost kernel: exec: /usr/X11R6/bin/xterm, PID: 1918, PPID: 1864, UID: 0, PUID: O euid: 0, suid: 0, fsuid: O, egid: 0, sgid: 0, fsgid: 0 Jul 13 20:35:22 localhost kernel: argv[0]: xterm Jul 13 20:35:24 localhost kernel: open: /dev/pts/1, PID: 1920, PPID: 1918, UID: 0, PUID: 0 flags: 2, mode: - 1073743496 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 20:35:24 localhost kernel: open: /etc/group, PID: 1920, PPID: 1918, UID: 0, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 20:35:52 localhost kernel: exec: /bin/touch, PID: 1950, PPID: 1920, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 20:35:52 localhost kernel: argv[0]: touch Jul 13 20:35:52 localhost kernel: argv[1]: shadow Jul 13 20:35:52 localhost kernel: open: shadow, PID: 1950, PPID: 1920, UID: 0, PUID: 0 flags: 35137, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 //Alarm for PID 1952: Jul 13 20:36:08 localhost kernel: sys_access: Filename: /usr/bin/pico, mode: 1, UID: 0, GID: 0 PID: 1920, PPID: 1918, UID: 0, PUID: 0 euid: O, suid: O, fsuid: 0, 159 egid: 0, sgid: 0, fsgid: 0 Jul 13 20:36:08 localhost kernel: sys_access: Filename: /usr/bin/pico, mode: 1, UID: 0, GID: 0 PID: 1920, PPID: 1918, UID: 0, PUID: 0 euid: 0, suid: O, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 20:36:08 localhost kernel: exec: /usr/bin/pico, PID: 1952, PPID: 1920, UID: 0, PUID: O euid: O, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 20:36:08 localhost kernel: argv[0]: pico Jul 13 20:36:08 localhost kernel: argv[l]: shadow Jul 13 20:36:08 localhost kernel: sys_access: Filename: shadow, mode: 4, UID: O, GID: O PID: 1952, PPID: 1920, UID: O, PUID: 0 euid: O, suid: O, fsuid: 0, egid: O, sgid: 0, fsgid: 0 Jul 13 20:36:08 localhost kernel: open: shadow, PID: 1952, PPID: 1920, UID: 0, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 20:36:12 localhost kernel: open: shadow, PID: 1952, PPID: 1920, UID: 0, PUID: 0 flags: 65, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 //Alarm for pid: 2072 Jul 13 20:36:40 localhost kernel: exec: /usr/X11R6/bin/xterm, PID: 2038, PPID: 2007, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: O, sgid: 0, fsgid: 0 Jul 13 20:36:40 localhost kernel: argv[0]: xterm Jul 13 20:36:40 localhost kernel: open: /dev/pts/3, PID: 2040, PPID: 2038, UID: 0, PUID: 0 flags: 2, mode: - 1073743528 euid: O, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 20:36:54 localhost kernel: exec: /usr/bin/pico, PID: 2072, PPID: 2040, UID: O, PUID: O euid: O, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 20:36:54 localhost kernel: argv[0]: pico Jul 13 20:36:54 localhost kernel: argv[1]: shadow Jul 13 20:36:54 localhost kernel: sys_access: Filename: shadow, mode: 4, UID: 0, GID: 0 PID: 2072, PPID: 2040, UID: 0, PUID: O euid: 0, suid: O, fsuid: 0, egid: 0, sgid: O, fsgid: 0 Jul 13 20:36:54 localhost kernel: open: shadow, PID: 2072, 160 PPID: 2040, UID: O, PUID: 0 flags: 0, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 20:37:01 localhost kernel: open: shadow, PID: 2072, PPID: 2040, UID: O, PUID: 0 flags: 65, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 For pid = 1950: What happened here is I logged in as root, ran Xterm, then touched shadow. I wanted to ensure that the scripts allowed a user to run xterm and still be able to edit shadow for level 2 and 3. However I also wanted to make sure that level I caught this edit as root had not run passwd to edit shadow. For pid = 1952: I took the same session as above (still xtermed) and ran pico on shadow. Again, I wanted to make sure that the level 1 would catch this, but level 2 and 3 wouldn't. From the script excerpt, you can see it was caught. for pid = 2072: I took the same session as above (still xtermed) and ran xterm again. Then I ran picO on shadow. I wanted tO ensure that we could cascade the xterrns (make sure that permissions propagate as we nest different levels Of Xterm). From the script, it did indeed detect this. Test 20: <165 gandalf:~/Thesis/scripts >./parser Please enter file to parse: test_su.doc 161 Please enter security level (1-4): 1 ALARM!!! level of 1 selected shadow changed without the use of passwd file: shadow, pid: 1194 ALARM!!! level of 1 selected shadow changed without the use of passwd file: shadow, pid: 1290 <166 gandalf:~/Thesis/scripts > For this system Of tests, I wanted to see if the scripts would allow a normal user to run SU, then edit shadow. For level 1, it should deny this behavior, yet for levels 2 and 3 it should allow it. //pid 1 194: Jul 13 02:57:57 localhost kernel: open: /dev/tty, PID: 1194, PPID: 1192, UID: 0, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:57:57 localhost kernel: open: /dev/tty, PID: 1194, PPID: 1192, UID: 0, PUID: 0 flags: 33026, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:57:57 localhost kernel: open: /dev/pts/0, PID: 1194, PPID: 1192, UID: 0, PUID: 0 flags: 32770, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 02:57:57 localhost kernel: open: /dev/tty, PID: 1194, PPID: 1192, UID: 0, PUID: 0 flags: 32769, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 13 03:10:29 localhost kernel: open: shadow, PID: 1194, PPID: 1192, UID: 0, PUID: 0 flags: 33857, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 // pid 1290: Jul 13 03:10:33 localhost kernel: sys_access: Filename: /bin/su, mode: 1, UID: 500, GID: 500 PID: 1248, PPID: 1245, UID: 500, PUID: O euid: 500, suid: 500, 162 fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 03:10:33 localhost kernel: sys_access: Filename: /bin/su, mode: 1, UID: 500, GID: 500 PID: 1248, PPID: 1245, UID: 500, PUID: 0 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 03:10:33 localhost kernel: exec: /bin/su, PID: 1286, PPID: 1248, UID: 500, PUID: 500 euid: 500, suid: 500, fsuid: 500, egid: 500, sgid: 500, fsgid: 500 Jul 13 03:10:33 localhost kernel: argv[0]: su Jul 13 03:10:46 localhost kernel: open: shadow, PID: 1290, PPID: 1286, UID: O, PUID: 500 flags: 33857, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 For pid 1194: Here, I simply logged in and typed: echo "bobrulez4" >> shadow The scripts running at level I caught this. For pid 1290: Here, I logged in as a normal user, ran SU, then edited shadow. I wanted to ensure that the scripts could catch (for level 1) a normal user editing shadow after they ran su. Note here how the PUID is 500 (for the Open call tO SU). This is fine because the user successfully authenticated into SU. Test 21 - extensive cron tests (all_elements.doc) <177 gandalf:~/Thesis/scripts >./parser Please enter file to parse: all_elements.doc Please enter security level (1-4): 1 ALARM!!! level of 1 selected shadow changed without the use of passwd file: /etc/shadow, pid: 1300 ALARM!!! 163 level of 1 selected shadow changed without the file: /etc/shadow, pid: ALARM!!! level of 1 selected shadow changed without the file: /etc/shadow, pid: ALARM!!! level of 1 selected shadow changed without the file: /etc/shadow, pid: use of passwd 1302 use of passwd 1303 use of passwd 1304 <178 gandalf:~/Thesis/scripts > //PH)1300: Jul 9 23:47:31 localhost kernel: sys_access: Filename: /etc/cron.dai1y/shadow1, mode: 1, UID: 0, GID: 0 PID: 1009, PPID: 929, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 9 23:47:32 localhost kernel: exec: /etc/cron.daily/shadow1, PID: 1300, PPID: 1009, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 9 23:47:32 localhost kernel: argv[0]: /etc/cron.daily/shadow1 Jul 9 23:47:33 localhost kernel: open: /etc/shadow, PID: 1300, PPID: 1009, UID: 0, PUID: 0 flags: 33857, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: O // PID 1302: Jul 9 23:47:33 localhost kernel: sys_access: Filename: /bin/touch, mode: 1, UID: 0, GID: 0 PID: 1300, PPID: 1009, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: O, fsgid: 0 Jul 9 23:47:34 localhost kernel: sys_access: Filename: /bin/touch, mode: 1, UID: 0, GID: 0 PID: 1300, PPID: 1009, UID: 0, PUID: O euid: O, suid: 0, fsuid: 0, egid: O, sgid: O, fsgid: 0 Jul 9 23:47:34 localhost kernel: exec: /bin/touch, PID: 1302, PPID: 1300, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: O, fsgid: 0 Jul 9 23:47:34 localhost kernel: argv[0]: touch Jul 9 23:47:34 localhost kernel: argv[1]: /etc/shadow Jul 9 23:47:34 localhost kernel: open: /etc/shadow, PID: 164 1302, PPID: 1300, UID: 0, PUID: 0 flags: 35137, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 // PID 1303: Jul 9 23:47:34 localhost kernel: exec: ./root/shadow1, PID: 1303, PPID: 1300, UID: O, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 9 23:47:34 localhost kernel: argv[0]: ./root/shadow1 Jul 9 23:47:36 localhost kernel: open: ./root/shadow1, PID: 1303, PPID: 1300, UID: 0, PUID: 0 flags: 32768, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 9 23:47:36 localhost kernel: open: /etc/shadow, PID: 1303, PPID: 1300, UID: 0, PUID: 0 flags: 33857, mode: 438 euid: 0, suid: O, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 // PID 1304: Jul 9 23:47:36 localhost kernel: sys_access: Filename: /bin/touch, mode: 1, UID: 0, GID: 0 PID: 1303, PPID: 1300, UID: O, PUID: O euid: O, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 9 23:47:36 localhost kernel: sys_access: Filename: /bin/touch, mode: 1, UID: 0, GID: 0 PID: 1303, PPID: 1300, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: O, fsgid: 0 Jul 9 23:47:36 localhost kernel: exec: /bin/touch, PID: 1304, PPID: 1303, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 9 23:47:36 localhost kernel: argv[0]: touch Jul 9 23:47:36 localhost kernel: argv[l]: /etc/shadow Jul 9 23:47:37 localhost kernel: open: /etc/shadow, PID: 1304, PPID: 1303, UID: 0, PUID: 0 flags: 35137, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: O 165 BZb — Security Level 2: Table 4 - File Test - Security Level 2 Alarm Expected /n) Result (y/n) Test Run no N (f1) run passwd and fail. (normal user) nO N (12) run passwd and succeed. (normal user) nO N (B) run passwd and succeed. (root user) (f4) run passwd and succeed. (normal user no N su'ed) (f5) run passwd on other user and succeed no N (root) no N (f6) run passwd on other user and succeed (su) nO N (17) directly edit shadow as root (<<) no N (18) directly edit shadow as su (<<) no N (19) pico shadow as su no N (f10) pico shadow as root no N (fl 1) emacs shadow as su no N (fl 2) emacs shadow as root no N (fl 3) touch shadow as su no N (f1 4) touch shadow as root no N (fl 5) pico shadow as normal user (Fail) no N (fl 6) emacs shadow as normal user (fail) no N (fl 7) touch shadow as normal user (fail) Yes Y (fl 8) Cron tests (newrun2.doc) NO N (f19) xterm tests (all_elements2.doc) NO N (120) su tests (test_su.doc) Yes Y (121) extensive cron tests (all_elements.doc) Table 4: In the above table, we test the file protection portion Of our IDS with a security level Of 2. Again, note the correlation between the expected result and the actual result. don't run passwd first. We, however, want to block any cronjobs from editing shadow For tests Of level 2, we want to allow root / su to edit shadow directly, even if they whatsoever (regardless Of where the scripts run from). 166 Tests 1 - 2: <160 gandalf:~/Thesis/scripts >./parser Please enter file to parse: test_1-2.doc Please enter security level (1-4): 2 <161 gandalf:~/Thesis/scripts > Tests 3 - 4: <162 gandalf:~/Thesis/scripts >./parser Please enter file to parse: test_3-4.doc Please enter security level (1-4): 2 <163 gandalf:~/Thesis/scripts > Tests 5 - l7: <137 gandalf:~l'l’hesis/scripts >./parser Please enter file tO parse: test_5-17.doc Please enter security level (1-4): 2 <138 gandalf:~l'l’hesis/scripts > As it should, the script recorded that shadow was not edited improperly. As with the series Of tests for level 1 security, the logfiles are exactly the same. Please check the level 1 tests for excerpts from logfiles. Essentially because all Of the tests 1-17 involve a user who is logged intO either console, an SSH session, or telnet to edit a file directly, no alarm should go out. A TTY session is hooked to each instance Of editing. 167 Test 18: <170 gandalf:~/Thesis/scripts >./parser Please enter file to parse: newrun2.doc Please enter security level (1-4): 2 ALARM!!! Level of 2 selected something without a TTY changed shadow file: /etc/shadow, pid: 1719 ALARM!!! Level of 2 selected something without a TTY changed shadow file: /etc/shadow, pid: 1721 ALARM!!! Level of 2 selected something without a TTY changed shadow file: /etc/shadow, pid: 1722 <171 gandalf:~/Thesis/scripts > Test 19: <173 gandalf:~/Thesis/scripts >./parser Please enter file to parse: all_element82.doc Please enter security level (1-4): 2 <174 gandalf:~/Thesis/scripts >./parser Test 20: <174 gandalf:~/Thesis/scripts >./parser Please enter file to parse: test_su.doc Please enter security level (1-4): 2 <175 gandalf:~/Thesis/scripts > Test 21: <176 gandalf:~/Thesis/scripts >./parser Please enter file to parse: all_elements.doc 168 Please enter security level (1-4): 2 ALARM!!! Level of 2 selected something without a TTY changed shadow file: /etc/shadow, pid: 1300 ALARM!!! Level of 2 selected something without a TTY changed shadow file: /etc/shadow, pid: 1302 ALARM!!! Level of 2 selected something without a TTY changed shadow file: /etc/shadow, pid: 1303 ALARM!!! Level of 2 selected something without a TTY changed shadow file: /etc/shadow, pid: 1304 <177 gandalf:~/Thesis/scripts > 169 82c - Security Level 3: Table 5 - File Test - Security Level 3 Alarm Expected (y/n) Result (y/n) Test Name no N (fl) run passwd and fail. (normal user) no N (12) run passwd and succeed. (normal user) nO N (13) run passwd and succeed. (root user) nO N (f4) run passwd and succeed. (normal user su'ed) no N (f5) run passwd on other user and succeed. (root) no N (16) run passwd on other user and succeed. (su) no N (f7) directly edit shadow as root. (<<) no N (18) directly edit shadow as su. (<<) no N (19) pico shadow as su. no N (fl 0) pico shadow as root. no N (fl 1) emacs shadow as su. no N (f12) emacs shadow as root. no N (fl 3) touch shadow as su. no N (114) touch shadow as root. no N (f1 5) pico shadow as normal user. (fail) nO N (f1 6) emacs shadow as normal user. (fail) no N (f1 7) touch shadow as normal user. (fail) Yes Y (fl 8) Cron tests. (newrun2.doc) NO N (f19) xterm tests. (all_elements2.doc) NO N (120) su tests. (test_su.doc) Yes Y (121) extensive cron tests. (all_elements.doc) Table 5: We are testing the file protection portion Of our IDS again, except here we test with a security level Of 3, which allows the least restrictive criterion to be applied. Test 1 - 2: <132 gandalf:~/Thesis/scripts >./parser Please enter file to parse: test_1-2.doc Please enter security level (1-4): 3 <133 gandalf:~/Thesis/scripts > 170 Test 3 - 4: <133 gandalf:~/Thesis/scripts >./parser Please enter file to parse: test_3-4.doc Please enter security level (1-4): 3 <134 gandalf:~/Thesis/scripts > Test 5 -17: <136 gandalf:~/Thesis/scripts >./parser Please enter file to parse: test_5-17.doc Please enter security level (1-4): 3 <137 gandalf:~/Thesis/scripts > Test 18: <140 gandalf:~/Thesis/scripts >./parser Please enter file to parse: newrun2.doc Please enter security level (1-4): 3 ALARM!!! Level of 3 selected A cronjob wrote to /etc/rc* or /etc/cron.* file: /etc/cron.daily/filenew, pid: 1719 ALARM!!! Level of 3 selected A cronjob wrote to /etc/rc* or /etc/cron.* file: /etc/rc.d/filenew2, pid: 1719 ALARM!!! Level of 3 selected something whose parent is not cron changed shadow file: /etc/shadow, pid: 1722 <141 gandalf:~/Thesis/scripts > Log Jul 11 23:50:50 localhost kernel: sys_access: Filename: /etc/cron.daily/shadow1, mode: 1, UID: 0, GID: 0 PID: 1430, PPID: 1425, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 171 Jul 11 23:50:50 localhost kernel: exec: /etC/Cron.dai1y/shadowl, PID: 1719, PPID: 1430, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 11 23:50:50 localhost kernel: argv[0]: /etc/cron.daily/shadow1 Jul 11 23:50:51 localhost kernel: open: /etc/cron.daily/shadow1, PID: 1719, PPID: 1430, UID: 0, PUID: 0 flags: 32768, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 11 23:50:51 localhost kernel: open: /etc/shadow, PID: 1719, PPID: 1430, UID: 0, PUID: 0 flags: 33857, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 11 23:50:51 localhost kernel: sys_access: Filename: /bin/touch, mode: 1, UID: 0, GID: 0 PID: 1719, PPID: 1430, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: O, egid: 0, sgid: 0, fsgid: 0 Jul 11 23:50:51 localhost kernel: sys_access: Filename: /bin/touch, mode: 1, UID: 0, GID: 0 PID: 1719, PPID: 1430, UID: O, PUID: 0 euid: 0, suid: O, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 11 23:50:51 localhost kernel: exec: /bin/touch, PID: 1721, PPID: 1719, UID: 0, PUID: O euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 11 23:50:51 localhost kernel: argv[0]: touch Jul 11 23:50:51 localhost kernel: argv[1]: /etc/shadow Jul 11 23:50:51 localhost kernel: open: /etc/shadow, PID: 1721, PPID: 1719, UID: 0, PUID: 0 flags: 35137, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 11 23:50:51 localhost kernel: open: /etc/cron.daily/filenew, PID: 1719, PPID: 1430, UID: 0, PUID: 0 flags: 33857, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 11 23:50:52 localhost kernel: open: /etc/rc.d/filenew2, PID: 1719, PPID: 1430, UID: 0, PUID: 0 flags: 33857, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 11 23:50:52 localhost kernel: exec: ./root/shadow1, PID: 1722, PPID: 1719, UID: 0, PUID: 0 euid: O, suid: 0, fsuid: 0, egid: O, sgid: 0, fsgid: 0 Jul 11 23:50:52 localhost kernel: argv[0]: ./root/shadow1 172 Jul 11 23:50:52 localhost kernel: open: ./root/shadow1, PID: 1722, PPID: 1719, UID: 0, PUID: 0 flags: 32768, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 11 23:50:52 localhost kernel: open: /etc/shadow, PID: 1722, PPID: 1719, UID: 0, PUID: 0 flags: 33857, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Test 19: <141 gandalf Please enter Please enter <142 gandalf Test 20: <142 gandalf: Please enter Please enter <143 gandalf Test 21: <143 gandalf Please enter Please enter ALARM!!! :~/Thesis/scripts >./parser file to parse: all_element82.doc security level (1—4): 3 :~/Thesis/scripts > ~/Thesis/scripts >./parser file to parse: test_su.doc security level (1-4): 3 :~/Thesis/scripts > :~/Thesis/scripts >./parser file to parse: all_elements.doc security level (1-4): 3 Level of 3 selected A cronjob wrote to /etc/rc* or /etc/cron.* file: /etc/cron.daily/filenew, ALARM!!! pid: 1300 Level of 3 selected A cronjob wrote to /etc/rc* or /etc/cron.* file: ALARM!!! /etc/rc.d/filenew2, pid: 1300 Level of 3 selected something whose parent is not cron changed shadow file: /etc/shadow, pid: 1303 173 ALARM!!! Level of 3 selected something whose parent is not cron changed shadow file: /etc/shadow, pid: 1304 <144 gandalf:~/Thesis/scripts > logfiles: Jul 9 23:47:31 localhost kernel: sys_access: Filename: /etc/cron.daily/shadow1, mode: 1, UID: 0, GID: 0 PID: 1009, PPID: 929, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 9 23:47:32 localhost kernel: exec: /etc/cron.daily/shadow1, PID: 1300, PPID: 1009, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: O, egid: O, sgid: 0, fsgid: 0 Jul 9 23:47:32 localhost kernel: argv[0]: /etc/cron.daily/shadow1 Jul 9 23:47:33 localhost kernel: open: /etc/shadow, PID: 1300, PPID: 1009, UID: 0, PUID: 0 flags: 33857, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 9 23:47:33 localhost kernel: sys_access: Filename: /bin/touch, mode: 1, UID: 0, GID: 0 PID: 1300, PPID: 1009, UID: O, PUID: 0 euid: 0, suid: O, fsuid: 0, egid: 0, sgid: O, fsgid: 0 Jul 9 23:47:34 localhost kernel: sys_access: Filename: /bin/touch, mode: 1, UID: O, GID: 0 PID: 1300, PPID: 1009, UID: 0, PUID: 0 euid: O, suid: O, fsuid: 0, egid: O, sgid: 0, fsgid: 0 Jul 9 23:47:34 localhost kernel: exec: /bin/touch, PID: 1302, PPID: 1300, UID: 0, PUID: 0 euid: O, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 9 23:47:34 localhost kernel: argv[0]: touch Jul 9 23:47:34 localhost kernel: argv[1]: /etc/shadow Jul 9 23:47:34 localhost kernel: open: /etc/shadow, PID: 1302, PPID: 1300, UID: 0, PUID: 0 flags: 35137, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 9 23:47:34 localhost kernel: open: /etc/cron.daily/filenew, PID: 1300, PPID: 1009, UID: 0, PUID: 0 flags: 33857, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 174 Jul 9 23:47:34 localhost kernel: open: /etc/rc.d/filenew2, PID: 1300, PPID: 1009, UID: O, PUID: 0 flags: 33857, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 9 23:47:34 localhost kernel: exec: ./root/shadow1, PID: 1303, PPID: 1300, UID: 0, PUID: 0 euid: O, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 9 23:47:34 localhost kernel: argv[0]: ./root/shadow1 Jul 9 23:47:36 localhost kernel: open: ./root/shadow1, PID: 1303, PPID: 1300, UID: 0, PUID: 0 flags: 32768, mode: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 9 23:47:36 localhost kernel: open: /etc/shadow, PID: 1303, PPID: 1300, UID: 0, PUID: 0 flags: 33857, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 9 23:47:36 localhost kernel: sys_access: Filename: /bin/touch, mode: 1, UID: 0, GID: 0 PID: 1303, PPID: 1300, UID: O, PUID: O euid: O, suid: 0, fsuid: O, egid: 0, sgid: 0, fsgid: 0 Jul 9 23:47:36 localhost kernel: sys_access: Filename: /bin/touch, mode: 1, UID: 0, GID: 0 PID: 1303, PPID: 1300, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 9 23:47:36 localhost kernel: exec: /bin/touch, PID: 1304, PPID: 1303, UID: 0, PUID: 0 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: 0 Jul 9 23:47:36 localhost kernel: argv[0]: touch Jul 9 23:47:36 localhost kernel: argv[1]: /etc/shadow Jul 9 23:47:37 localhost kernel: open: /etc/shadow, PID: 1304, PPID: 1303, UID: O, PUID: 0 flags: 35137, mode: 438 euid: 0, suid: 0, fsuid: 0, egid: 0, sgid: 0, fsgid: O 175 Bibliography “Linux Intrusion Detection System (LIDS)”, http://www.lids.org/index.html 42 “Security-Enhanced Linux”, http://www.nsa.gov/selinux 43 “The Twenty Most Critical Internet Security Vulnerabilities—the Expert’s Consensus”, http://www.sans.org/top20/ 6 Allen, J., Christie, A., Fithen, W., McHugh, J., Pickel, J., and Stoner, E. 2000. “State of the practice of intrusion detection technologies." Technical Report CMU/SEI-99TR -028 10 Chiueh, T., Hsu, F "RAD: A Compile-time Solution to Bufler Overflow A ttacks. " International Conference on Distributed Computing Systems (ICDCS), Phoenix, Arizona, USA, April 2001 42 Hofrneyr, S.A., S. Forrest, and A. Sorrrayaji. “Intrusion detection using sequences of system calls.” Journal of Computer Security, 6:151--l80, 1998. 1 Hsu, F., " The Principle. Attack Patterns, and Defense Methods of Buffer Overflow Attacks,” RPE report, October 2000 42 Kim, G.H and E. H. Spafford. "The design and implerrrentation Of tripwire: a file system integrity checker.” Technical Report CSD-TR-93-07l, Purdue University, Dept. of Cmputer Sciences, Purdue University, West Lafayette, IN 47907-1398, 1993 3 KO, C., Pink, 6., and Levitt, K., “Automated Detection of Vulnerabilities in Privileged Programs by Execution Monitoring. ” Proceedings of the [OM Annual Computer Security Applications Conference, pages 134-144, Orlando, FL, 1994. 41 Kumar, S., Spafford, E., “A Pattern Matching Model for Misuse Intrusion Detection” Proceedings of the 17th National Computer Security Conference, Pages 11-21, 1994 41 Lawless, T., “On Intrusion Resiliency”, http://packetstormsecurity.nl/papers/IDS/OlR.pdf 44 Lindqvist, U. and P. A Porras, “eXpert-BSM: A Host-based Intrusion Detection Solution for Sun Solaris,” Proceedings of the 17th Annual Computer Security Applications Conference (A CSAC 2001). IEEE Computer Society, New Orleans, Louisiana. December 10-14, 2001. Pages 240-251. 1 Lindqvist, U. and RA. Porras. “Detecting computer and network misuse through the Production-Based Expert System Toolset (PBEST).” Proceedings of the I 999 Symposium on Security and Privacy, Oakland, California, May 1999. IEEE Computer Society. pp. 146161 17 Lippmann, R., et al., "The 1999 DARPA Off-Line Intrusion Detection Evaluation", Computer Networks 34(4) 579-595, 2000. 6 Porras, P. A. and P.G. Neurnann. “EMERALD: Event Monitoring Enabling Responses Anomalous Live Disturbances.” Proceedings of the Nineteenth National Computer Security Conference, pages 353-365, Baltimore, Maryland, 22-25 October 1997. NIST/NCSC 38 Vandenwauver, M., Claessens, J., Moreau, W., Vaduva, C., and Maier, R. (1999). “Why Enterprises Need More than Firewalls and Intrusion Detection Systems.” Proceedings of the Eighth IEEE International 2 Yaghmour, K., and M. R. Dagenais, “Measuring and Characterizing 15 176 ll111111111111111111111