C SC 340 Lecture 12: Security
[ previous
| schedule
| next ]
major resources: "Reflections on Trusting Trust",
Ken Thompson, Communications of the ACM, 1984
"The Internet Worm Incident", Eugene Spafford, Technical Report CSD-TR-933, Purdue University, 1991.
Distinguishing Protection from Security
- Protection: mechanism for controlling access to system resources by processes.
This includes a means of specifying controls and a means of enforcing the controls.
This is an internal problem.
- Security: assuring the integrity of system resources and data.
Protection is the enforcement aspect of security.
Security must also consider the external environment in which the system operates.
Security
Security insures the integrity of system resources and data.
Security violation categories, broadly defined
- confidentiality violations, unauthorized reading of data
- integrity violations, unauthorized modification of data
- availability violations, unauthorized destruction of data
- service theft, unauthorized use of resources (the first 3 fall under this umbrella)
- service denial, violations that deny others authorized use of resources
Security features are needed at many levels
Come up with examples. Consider physical security of the system, human vulnerability, security
in the OS itself, security of the network leading into the system.
List of security threats
The textbook introduces quite a few threats from within and without:
- trojan horses, trusted program that performs untrustworthy function (downloaded program that bears spyware), or untrustworthy program
disguised as trusted program (e.g. fake login).
- trap doors, programmed to open security hole for specific user based on ID
- logic bombs, programmed to open security hole under specified circumstances such as date or employment status
- buffer and stack overflow, programmed to exploit system stack mechanism to take over CPU
- viruses, self-replicating program that "hitches a ride" into the system from outside. Benign until activated.
- worms, self-replicating program that activates itself and usually ties up system resources
- port scanners, software that tests for vulnerable Internet ports and attacks them when found
- denial of service attacks, where attacker either gains control and monopolizes system resources, or
denies access to system resources by monopolizing network resources through flurry of requests.
What a rogue's gallery! Let's work our way through a few of them.
The threats are not all independent of each other.
- The Thompson/Ritchie article below describes
a combined trojan horse / trap door.
- Worms and viruses are overlapping categories, depending on how you define those terms.
- Worms can take
over a system through buffer and stack overflow, as described below in the discussion of the 1988 Morris Internet worm.
- The 2003 Slammer worm also uses buffer and stack overflow, demonstrating that 15 years after Morris
we still were not (and still are not) getting it right.
- We'll go through a generic and possibly specific example showing how buffer overflow can lead
to stack overflow, which can lead to hostile system takeover. This requires understanding
how stack frames are constructed and used.
Discussion of Thompson paper "Reflections on Trusting Trust"
This is Ken Thompson's Turing Award Lecture, printed in August 1984 issue of Communications of the ACM.
He and Dennis Ritchie received the award to honor their development of the UNIX operating system at
AT&T Bell Labs.
I recently did a Google search on the title of this paper and got nearly 2000 hits.
It is
available online from several sources.
Summary: Thompson bugged the C compiler (written in C), so that whenever
Unix source code (written in C) was compiled, a trap door giving him special
access was inserted into Unix binary. The trap door logic and the code that
inserts it were placed into the compiler source using the technique of self-replicating
code. After compiling the compiler source, the compiler binary contains the
self-replicating code. It can then be removed from the compiler source code
yet will be propagated every time the compiler source is subsequently compiled.
Detectable only through reverse engineering of compiler binary code.
Discussion outline
We will follow this outline, only if we have time to read/discuss this paper.
- Stage I question
- What is a self-replicating program?
- Stage II questions
- How is it possible for a compiler to be written in the same language that it compiles?
- What does the code in Figure 2.1 do?
- What does the code in Figure 2.2 do?
- What does the code in Figure 2.3 do?
- What has the C compiler learned after Figure 2.3 is executed?
- Stage III comments and questions
- Comment: Figure 3.1 represents the function in the C compiler that compiles a line of source code (represented by parameter s, declared in old-style C). Alterations to the function
are shown in Figures 3.2 and 3.3.
- What program is being targeted in Figure 3.2 (e.g. what program, when compiled, will contain the pattern)?
- If you were to plant this bug, what would you replace the word "pattern"
with, in Figure 3.2?
- If you were to plant this bug, what would you replace the word "bug"
with, in Figure 3.2?
- Comment: The first if statement in Figure 3.3 is the same as the if statement
in Figure 3.2.
- What program is being targeted in Figure 3.3's second if statement (e.g. what program, when compiled, will contain the pattern 2)?
- If you were to plant this bug, what would you replace the word "pattern
2" with, in Figure 3.3?
- If you were to plant this bug, what would you replace the word "bug
2" with, in Figure 3.3?
- How long do the if statements of Figure 3.3 remain in the C
compiler source code?
- How long do the if statements of Figure 3.3 remain in the C
compiler binary code?
- Other questions
- What is the moral of the story?
- Why is this technique called a "Trojan Horse"?
Morris' Internet Worm of November 1988.
On November 2, 1988, Robert Morris, Jr., a graduate student in Computer
Science at Cornell, wrote an experimental self-propagating program called
a worm and injected it into the Internet.
It spread very rapidly. Due to a bug in the worm, it also spawned
many new processes on each infected system, slowing system response to
a crawl. The Internet bogged down, and many system administrators
simply disconnected.
Researchers at U.C. Berkeley and other institutions “reverse engineered”
the worm’s code and developed a fix within a few hours. The damage,
however, was already widespread.
Morris was convicted of violating the computer Fraud and Abuse Act,
and sentenced to three years of probation, 400 hours of community service,
and a fine of $10,000. Ironically, his father was chief scientist at the National Computer Security Center at
the time of the worm attack.
Significance: first wake-up call for Internet users that security
measures need to be taken.
The worm attacked several “holes” in BSD Unix, which was developed at U.C.
Berkeley and distributed free to educational institutions. Most machines
connected to the Internet at that time ran BSD Unix.
Up to three methods of attack were attempted in this sequence: rsh
(a facility for invoking a command shell from a remote machine), fingerd
(described below), and sendmail (email server).
The fingerd attack
Here is a detailed description of the fingerd attack. We will cover it only if time allows.
One mode of attack was through a bug in BSD Unix fingerd
-
finger is a Unix command to request public information about a
user
-
e.g. finger pete for info about user pete on local system
-
e.g. finger pete@csc.smsu.edu for info about user pete
on remote system
-
the second example triggers connection between local (client) and remote
(server)
- fingerd is the name of the server program that handles finger
requests from remote clients. “d” is short for daemon, a process
that awakens periodically to handle service requests.
Partial pseudo-code for the finger program, the fingerd program, and the Morris Internet Worm attack on fingerd.
finger program
- get user name from command argument
- determines whether request is for local or remote user ("user" or "user@host")
- if for local user
- does lookup for that user
- outputs results to standard output
- if for remote user
- creates a client socket
- connects through socket to remote host (server) port 79, the fingerd port
- sends user name to server through socket
- reads user information from server through socket
- outputs results to standard output
- closes connection and socket
fingerd server
- Accepts socket connection from client on port 79
- (standard input and output are redirected to socket)
- Reads user name from client through socket using system call gets(buffer),
where buffer is a 512-byte character array. The man
page for gets states: Function gets(s) reads a line from
standard input into the buffer pointed to by s until either a terminating
newline or EOF, which it replaces with '\0'. No check for buffer overrun is
performed (see BUGS below).
- Forks new process to execute finger with the local user
name.
- The child process, being a clone of the parent, has standard input and output directed to the socket.
- The child process does system call execve("/usr/ucb/finger", args, 0);
to replace its code segment with the binary code of the finger
program (described above) and run it. The variable args contains
the finger argument list (user name which is copied over
from buffer).
- The child process is now finger with a local user, and it does the lookup
then sends results to standard output (in this case directed back to client through socket).
- After forking, the parent loops back to step 1 to get next client connection
worm, pretending to be fingerd client
- Creates a client socket
- Connects through socket to remote host (server) port 79, the fingerd port
- Instead of sending user name, sends specially-crafted 536 byte string to
server through socket. This overflows the 512 byte buffer. The extra 24 bytes
overwrite other parts of the runtime stack to this affect:
- the return address for main (address to which control resumes upon completion)
is modified from X to Y, where Y is within the buffer now containing the
536 byte string.
- location Y contains machine code to call execve("/bin/sh", 0, 0);
- When the server attempts to return,
- Control passes to the worm code at location Y in the buffer.
- This executes execve("/bin/sh", 0, 0);
- This in turn overwrites the process' code segment with binary code of
the standard command shell (command interpreter).
- Since standard input and output have already been directed to the socket,
the command shell will receive its commands from the socket. The worm
is at the other end of the socket!
- The worm now has a command shell on the remote host and can send commands.
- Worm sends commands to copy the remainder of the worm program and then to
execute it. Self-propagation!
This account is digested from several web pages, including one containing the
source code for the worm! Do a google search on Morris Internet Worm and
you'll get lots of information.
The Slammer worm of January 2003
The possibility of "buffer overflow" attack remains
to this day.
My source for this account is the July 2003 Wired magazine article
"Slammed! An inside
view of the worm that crashed the Internet in 15 minutes." They caught some grief for
publishing the disassembled code of the worm but it is instructive.
Just after midnight on January 25, 2003, the Internet was overwhelmed in 15 minutes by UDP packets targeting
Microsoft's SQL Server 2000. The worm took advantage of a buffer overflow vulnerability.
Here's how the worm was constructed and operated
- The vulnerability: SQL Server offers a SQL Server Monitor service on UDP port 1434.
This service expects a request packet to begin with a one byte service number and the "04" service in question then
expects a maximum 16 byte long database name. Since names can vary in length, the server expects
it to be "null terminated" -- the name must end with a byte of 0's.
- The Buffer Overflow: Instead of a null-terminated database name, Slammer provides a long
sequence of "01" bytes (00000001 in binary) followed by a sequence of binary-encoded instructions.
By the time the server sees the null byte the packet contents have overflowed
the buffer and into the adjacent runtime stack entry.
- Taking Control: The overflow part of the packet contains
not data but instructions. The runtime stack entry into which they flow, controls what code
the computer will execute next. After the server reads the packet, it then looks to the runtime stack entry
to determine what to do next. But this has been corrupted by the overflow, which directs
the computer to execute its own instructions. The Worm now has control of the computer.
- Replication: The Worm reads the 32-bit system clock and uses that as a 32-bit IP address.
It generates a UDP packet replicating the packet it arrived in and sends it off to the host at that
IP address. It then repeatedly permutes the 32-bit IP address and with each permutation fires off
another worm packet. I do not know what, if anything, causes it to stop doing this. After a few minutes
the Internet was so congested the packets could no longer be transmitted anyway.
UDP is a prime carrier for such an attack because each packet travels the Internet on its own and
arrives at the receiving host unexpected. By contrast, the more robust TCP protocol establishes a client-server
connection prior to sending any data packets. TCP has its own vulnerabilities, but that's a different story...
As far as I've been able to determine, the author and source of Slammer have never been identified.
Cryptography
One defense against security threats is cryptography
The Texas State Library computer
security glossary contains a very specific definition of cryptography "The art of science concerning the principles, means, and methods for
rendering plain text unintelligible and for converting encrypted messages into intelligible form."
Relevant crypto topics include:
- symmetric encryption, (e.g. DES, AES, stream cipher for WEP). Both
sender and receiver have to know same key. This is a weakness since how is
key securely communicated? But it is fast.
- asymmetric encryption, (e.g. RSA). Sender and receiver each has
two keys, one public and one private. Private key not communicated, but algorithm
is slower.
- message authentication. How does receiver know message is really
from sender? How does receiver know message wasn't altered after being sent?
There are both symmetric and asymmetric solutions.
- key distribution
. There are issues for both symmetric and asymmetric crypto. Symmetric: How
do sender and receiver agree on key? One solution is communicate symmetric key
by encrypting and sending it using asymmetric method. Asymmetric: How does sender
know that key advertised as receiver's public key really belongs to receiver
and not imposter? One solution is digital certificate, where digital certificate
authority (issuer) address is included in sender's application (e.g. browser).
Check my
CSC 150 cryptography notes for more details.
[ C
SC 340 | Peter
Sanderson | Math Sciences server
| Math Sciences home page
| Otterbein ]
Last updated:
Peter Sanderson (PSanderson@otterbein.edu)