Again and again, when considering system security, people tell me, “I already patch my system.” I try to explain to them, as I will here, why they’re still vulnerable, even if they patch and read BugTraq regularly. To this end, I’ll visit the following topics:
- Levels of Cracker-dom
- The Way of the Script Kiddie (Methods)
- Common (Failed) Attempts to Halt the Kiddie
- The Lifecycle of the Modern Security Vulnerability
- Really Stopping the Kiddie!
Levels of Cracker-dom
We can think of system crackers (“hackers”) of falling into three tiers of ability – I’ll use a strange, but hopefully effective, analogy with photographers:
Tier I – The Professional
This person really knows what he’s doing. He finds vulnerabilities in existing programs and writes his own exploit code from scratch. He’s very knowledgeable and often rather experienced and may even be doing this for a living. This guy is like the photographer who builds his camera from scratch, or at least makes his own repairs. While this type of cracker is very rare, consider him very dangerous. He’ll be very stealthy when he cracks your system – if you even notice him, you probably spent a lot of time on your Intrusion Detection Systems.
Tier II – Mid-level, Knowledgeable Types
This person probably works as a UNIX programmer or system administrator by day. He often uses pre-written, higher-level tools, like nmap and netcat. In some cases, he’ll use others’ exploit code, but he’s not reliant on others to provide one-shot easy- to-use scripted cracks. He’ll often code his own vulnerability scanners, by combining tools with his own C, Perl or shell code. When he does get root on a new system, he knows what he’s doing and covers his tracks fairly well. He’s like the photographer who knows enough to carefully select his own filters and lenses, take a well- constructed shot and then develop his own film when he gets home. This cracker is somewhat more common than the Pro, but usually picks his targets selectively and isn’t interested in your system.
Tier III – L33t Script Kiddie d00d3z
This is your average system cracker. He’s not especially knowledgeable. He downloads his exploit scripts from Web sites and often barely understands what he’s doing. Once he does root your system, he may not even know basic UNIX commands – some will even try DOS commands at the root prompt! This guy is the weekend photographer who uses the disposable one-button auto-everything camera and tends to remove film before he’s rewound it. These crackers are dangerous, if only because there are so many of them – if one of them has a 1/10% chance of successfully compromising your system, but 100 of them are trying, there’s a 1 in 10 shot you’re getting cracked. This type of cracker is incredibly common on the Internet and, as I hope to show you below, is the bulk of the problem.
Hardening your system is effective against all three classes of cracker, but we’re going to discuss the Kiddie here, as he represents the simplest, yet most common, case that can be easily stopped.
The Way of the Script Kiddie
The script kiddie uses two basic types of exploit: remote exploits and local exploits. He can run a remote exploit against your system from some other host on the Internet, while he can only run a local exploit from an account on your system itself. Remote exploits are far, far less common, but rather dangerous. We’ll consider this type first.
Our script kiddie scans cracker/security web sites, ftp sites and irc channels regularly for new remote exploits. Few exist and even fewer actually work, but he’ll tend to find one or two that do work. Next, he’ll download and run a scanner that can look for vulnerable boxes that he can attack with these scripts/programs.
This is key: the script kiddie is indiscriminate. His exploit only works against a small percentage of machines on the Internet, so he’s got to scan a large portion of it to find vulnerable hosts. The last time that I cleaned up a hacked machine, I found that the cracker had been scanning the IP range 24.1.0.0 – 24.8.255.255 for Solaris hosts with a vulnerable sadmind available – this range includes the entirety of a major home user ISP! I learned about my cracked machine not from IDS, but from cable modem users who he had scanned!
The kiddie can scan a large IP range in hours. He’ll usually log off and let his scanner run, coming back for the listing of vulnerable machines later. When he comes back, he’ll methodically break into each one with his exploit, set up shop, and decide what to do with his new box. Before we talk about what he does next, let’s consider the class of local exploits.
Our kiddie also uses local exploits which require1 a shell account on a vulnerable system. To get accounts that he can use for this, our kiddie will generally set up a sniffer on a system that he’s already compromised. The sniffer, or “protocol analyzer,” will grab thousands of name/password pairs from each telnet/ftp/pop/imap session to or from the compromised system. Each of these pairs represents an account he can now steal – these accounts will be not only on the compromised system, but also on lots of remote systems!
Using one of these stolen name/password pairs, the kiddie will now log in to one of our systems. At this point, he’ll try to figure out what version of the O/S (Linux, FreeBSD, Solaris…) that we’re running, so he can download local exploits. He’ll usually download these by running an ftp client on our system to grab exploits from his favorite site. He’ll even use our system to compile any C exploits that he downloads.
Each exploit is against a particular vulnerable local program that runs with root privilege. This program might be a Set-UID root program like dump or at, or a local system daemon, like gpm. On Red Hat 6.0, he might use userrooter.sh to exploit the Set-UID root program userhelper. Once he’s found an exploit for such a program, he’ll run his exploit to turn his ordinary user privilege into root privilege. This method, where he gets an unprivileged account and then leverages this to get root, is called “escalation of privilege.”
What does our script kiddie do once he does get root, through either method? He sets up shop! He’ll create additional accounts, plant back doors so he can get back in and Trojan existing programs. He’ll often install a rootkit, replacing common programs, like ps, ls, and top, with versions that will hide his activities. He may even patch your system, to stop other crackers from using the same hole he used! In any case, he might inhabit your system quietly, running a sniffer or an IRC bot from your box, or he may make a total nuisance of himself, using your system as a launchpad to scan or attack other systems. In either case, you’d probably prefer if he never got root in the first place!
Common (Failed) Attempts to Halt the Kiddie
How do we halt the script kiddie? One common approach is to simply “not have any vulnerabilities!” Strike 1! This fails, because every publicly available operating system, even the venerable OpenBSD, seems to have bugs that lead to security vulnerabilities. Well then, you say, what if we turn off every vital service? Strike 2! In this case, our machine becomes quite useless and the kernel may still be vulnerable! OK, OK, you say, I’m a good admin! I patch! Most (good) sysadmins take this approach, whereby they patch the hell out of their machines, as rapidly as the patches come out. But this too fails. Strike 3! Patching, unfortunately, fails to protect you in many cases because it doesn’t account for both undiscovered bugs and discovered, but unfixed, bugs. Actually, even if you read BugTraq and fix bugs before official patches are released, you still have non- trivially long windows of vulnerability. We’ll consider this last bit in greater depth now, as we discuss the lifecycle of the modern security vulnerability.
The Lifecycle of the Modern Security Vulnerability
I. Bug Discovery
If we think about the security vulnerabilities that crackers exploit, whether locally or remotely, we realize that they’re caused by one thing: a “bug” in either the design or the implementation of a system program. The lifecycle of this vulnerability starts when someone discovers this bug, through whatever method. They may be reading code or reverse-engineering the program, but they might as well be reading Internet RFCs describing a given protocol. In any case, the problem becomes a real possibility at the moment someone discovers this bug. It becomes a little worse if and when this person shares that knowledge with another.
II. Vulnerability Discovery
Now at some point, possibly seconds later, someone realizes that this “bug” actually leaves a security hole in the program. If this program has privilege, the vulnerability may be exploitable to gain that privilege. Again, the discoverer doesn’t necessarily share this knowledge with anyone!
III. Exploit Coding
Somewhat later, someone, often the original finder, codes an exploit against the security hole. This exploit will abuse the hole to make the program do, generally, one of the following:
- Run arbitrary commands.
- Dump a section of memory containing passwords or other privileged information to a file.
- Write well-crafted data to the end of a specific file.
At this point, the vulnerability has become our problem. The exploit writer now has the capability to break into our machine – and we usually don’t even know about the vulnerability. This is not good.
IV. Exploit Sharing
The exploit coder may share his exploit at this point. He can distribute it privately, among friends and acquaintances. Our problem just got worse, as there are now more people that can break into our machine and we may still not even know about the vulnerability.
V. Public Release!
Finally, one of the exploit owners may choose to release the exploit publicly, on BugTraq or other security mailing lists and possibly on security web sites. Our problem just got worse, in that now every script kiddie has access to a working exploit. Remember, there are tons of them and they’re scanning the net indiscriminately, so we could be a target. But, our situation can finally be improved, in that someone might fix the vulnerability now! Remember, there’s no guarantee that the vulnerability/exploit will ever reach this stage! Many exploits are circulated quite privately among cracker groups and thus don’t become well-known for some time, if ever.
VI. Source Code Patch
Once the vulnerability is well-known, someone can code a patch. Often, the patch will be released on BugTraq and/or the vendor web site. This can happen very quickly in the Open Source community, but still often takes 1 hour to 4 days. Further, these source-code level patches are applied only by some sysadmins, who have the time and expertise to patch in this manner. Most admins wait for a vendor- supplied patch or update package.
Finally, realize that even for this first group, there has already been a sizable window of opportunity, in which their system could have been cracked. To see this, consider all the time between step III and steps IV, V and VI! In all this time, some number of crackers has had a working method of cracking our machine, usually before we’ve even heard about it!
VII. Vendor Patch
Now some number of days, weeks or months later, the vendor will release a patch. At this point our troubles, with this particular vulnerability, are usually over! Remember, though, there has been a sizable window of opportunity between initial coding of the exploit and the vendor patch. In these days, weeks or months, your machine has been rather vulnerable. Given the indiscriminate nature of the script kiddie, there’s a very real chance that you could get hit!
Let’s recapitulate the dangers here: first, many exploits are privately used, but not publicly announced for some time. Second, there’s a delay between availability of exploit code and a source code patch. Third, vendors take quite a while to release that patch/update, leaving a large window of vulnerability in which you can be attacked. Fourth, there are a boatload of script kiddies out there, which means that while the exploit is publicly available, there’s a number of people firing it indiscriminately against many random machines on the Internet. The only real way that we can stop the script kiddie is to actually take some proactive action.
Really Stopping the Kiddie!
Now that you realize that you’ve got to do something proactive to stop the script kiddie, let’s consider what you can do. First, if you’re on a Linux system, run Bastille Linux (shameless plug!). Bastille can harden a system for you very effectively with a minimum of hassle – it’ll also teach you a fair deal in the process! You can also harden a system by hand, though it’s likely to be less comprehensive than a Bastille run, unless you’re using a very well- written checklist. If you do this all by hand, keep in mind these minimum important steps:
- Firewall the box – if possible, do this both on the box and on your border router to the Internet.
- Patch, patch, patch and patch some more. Automate this process, if possible, to warn you of new patches as soon as they’re released. Please remember that the window of vulnerability is large enough without a sysadmin waiting two-four weeks to apply patches…
- Perform a Set-UID root audit of the system, to clear up as many (local) paths to root as possible. I show how to do this and perform one for Red Hat 6.x in my previous SecurityPortal.com art icle.
- Deactivate all unnecessary network services/daemons, minimizing the possibility of remote exploits!
- Tighten the configurations of all remaining network services/daemons to better constrain remote exploits.
- Harden the core O/S itself, through PAM settings, boot security settings and so on…
- Educate the sysadmin and end users!
As I said, Bastille does this stuff very well. Here’s a real-world example of how hardening a box can be so much more effective than only patching: Red Hat 6.0 shipped with a BIND named daemon that was vulnerable to a remote root exploit. This vulnerability was unknown at the time, so no patch existed for a little while. If you had run Bastille, it had minimized the risk from any BIND exploit, known or unknown, by setting BIND to run as a non-root user in a “chroot” prison. When the exploit came out, people who hadn’t hardened BIND were vulnerable to a remote root grab. Thousands of machines, at least, were rooted before patches were released and applied. If you had hardened ahead of time, by running Bastille or otherwise, the root grab failed. This example is just one of several – there were a few ways to root a Red Hat 6.0 box, all of which could be minimized by judicious hardening.
1 Actually, there are also hybrid exploits, where he gets an unprivileged shell on the system from some network daemon, without ever logging in but these are a hybrid type. Our script kiddie generally doesn’t use this stuff, though he may if he’s bright or has a good text file instructing him.
Jay Beale is the Lead Developer of the Bastille Linux Project (http://www.bastille- linux.org). He is the author of several articles on Unix/Linux security, along with the upcoming book Securing Linux the Bastille Way, to be published by Addison Wesley. At his day job, Jay is a security admin working on Solaris and Linux boxes. You can learn more about his articles, talks and favorite security links via http://www.bastille- linux.org/jay.
SecurityPortal is the world’s foremost on-line resource and services provider for companies and individuals concerned about protecting their information systems and networks.
http://www.SecurityPortal.com
The Focal Point for Security on the Net ™