CSC 150 Chapter 13: Selected Security Topics and Case Studies
information resources:
An Invitation to Computer Science Third Edition,
G. Michael Schneider and Judith L. Gersting,
Thompson Course Technology, 2007.
Computer Networking: A Top-Down Approach Featuring the
Internet, James Kurose and Keith Ross, Addison-Wesley, 2000.
Reflections on Trusting Trust,
Ken Thompson and Dennis Ritchie,
Communications of the ACM, August 1984
[ previous | schedule | next ]
Network Security: Cryptography
Cryptography: designing ciphers
Cipher: system for transforming plain text into secret code and back through use of an algorithm and key
Symmetric cryptography
a.k.a secret key
Traditional methods fall into this category, which include:
Example: DES (Data Encryption Standard)
Asymmetric cryptography
a.k.a public key
most such methods are variation of public key cryptography
Authentication
Guaranteeing that an entity really is who it claims to be.
passwords are simple example of authentication for purposes of gaining
system access
digital signature is a type of authentication which uses cryptography
Example procedure (there are other methods):
1. sender applies its private DS to M
2. sender transmits DS(M)
3. receiver applies sender's public ES to get ES(DS(M))
= M
If the message had come from a different sender, last step would fail.
Such signatures are legally recognized.
Application
Public key cryptography is very computationally expensive.
A typical application will use public key cryptography for the exchange of DES keys, followed by data communication using DES
These technologies are utilized in:
Network Security: Viruses and Worms
Viruses, Worms and Trojan Horses
Following are 4 case studies:
The “I Love You” virus of May 2000.
McAfee calls it a “worm with virus qualities”. It is a VBScript virus which arrives attached to an email message with this format:
Subject "ILOVEYOU"
Message "kindly check the attached LOVELETTER coming from me."
Attachment "LOVE-LETTER-FOR-YOU.TXT.vbs"
Opening the attachment will cause it to run. Here is a summary
of what it does:
1. It makes a few copies of itself in Windows system folders.
2. It also modifies the Windows system registry in order to run the
virus at system startup.
3. It then searches all drives connected to the system and :
a. replaces JPEG files with copies of itself
and it adds the extension .VBS to the original filename.
b. replaces files having certain other file name extensions
with copies of itself and changes the extension to .VBS.
c. makes MP3 files hidden without destroying them,
and makes copies of itself with the same filenames only adding extension
.VBS to the original filename.
4. It then sends copies of itself to everyone in the system’s Microsoft
Outlook’s address book. This is how it propagates.
5. Tries to download and install a password stealing program called
WIN-BUGSFIX.EXE, This program will email captured passwords to an address
in the Philippines.
Here are two classic Internet Worm cases. The first occurred in 1988 and the second in 2003. The 1988 Morris Internet Worm was the first great Internet worm. It epitomizes worm behavior and exploitation through buffer overflow. The 2003 Slammer Internet worm is more recent but no more interesting. It demonstrates that, sadly, we still haven't learned our lessons and Internet services are still susceptible to buffer overflow attacks. The Morris worm will be covered in greater detail.
Morris' Internet Worm of November 1988.
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. There is an especially comprehensive account at http://www.snowplow.org/tom/worm/worm.html
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.
I will describe how the worm attacked one hole in particular.
One mode of attack was through a bug in BSD Unix fingerd
Server (fingerd) follows this sequence:
1. Waits for user name from client.
2. When user name received, stores it into a 512-byte buffer (array)
3. runs its finger program to get user info
4. sends user info back to the client
5. closes connection
Here’s what Morris’ worm did:
1. issued a finger command directed to a targeted remote machine.
2. This established a client-server connection.
3. Instead of sending user name, it sent a 536- byte long string especially
crafted to overflow the server’s 512-byte buffer.
4. The string was crafted so the overflow replaced the code to run finger
(server step 3) with the code to run sh, the command interpreter.
5. Thus, when the server got to its step 3, it started up a command interpreter.
6. Because the client-server connection was still active, the command interpreter
expected to get its input from that connection instead of from a keyboard.
7. The client (worm) issued the necessary commands to transmit the worm files
to the server (targeted) machine then run the worm on that machine. Self-propagation!
Postscript: the possibility of "buffer overflow" attack remains to this day...just read on.
The Slammer Internet Worm of January 2003
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
As far as I've been able to determine, the author and source of Slammer have never been identified.
Ken Thompson's C compiler Trojan Horse
Ken Thompson and Dennis Ritchie developed the Unix operating system at Bell Labs. They were later given an ACM Turing Award for this accomplishment. Ken Thompson presented this lecture at the award ceremony. In it, he describes how he planted a Trojan Horse into an early version of the C compiler (which he helped develop in conjunction with Unix). The lecture is published as "Reflections on Trusting Trust" by Dennis Ritchie and Ken Thompson, Communications of the ACM, August 1984.
Three concepts are required.
1. Compiler is written in the same language that it compiles.
2. learning compiler.
3. self-reproducing code.
1. Compiler is written in the same language that it compiles.
C compiler is written in C. Classic chicken-and-egg, right?
Kinda.
2. Learning compiler
This is described in general by steps 4 and 5 above. The example
given in the lecture, along with code, is this: the compiler recognizes
‘\n’ as the newline character but does not recognize ‘\t’ as tab character.
Teach it to do so. The example source code is in the C compiler.
I will take some poetic license with C syntax to make the code more understandable.
// Version X. recognizes ‘\\’ (backslash) and ‘\n’ (newline)
char c;
c = next( ); // get next character from program being compiled
if ( c == ‘\’) { // first character of ‘\n’ or
‘\\’
c = next( );
if (c == ‘\’) // it is ‘\\’ which
compiles into backslash
return (‘\\’);
if (c == ‘n’) // it is ‘\n’ which
compiles into newline
return (‘\n’);
}
// Version X+1. Teach to recognize ‘\t’ (tab) ASCII code 9
char c;
c = next( );
if ( c == ‘\’) {
c = next( );
if (c == ‘\’) // it is ‘\\’ which
compiles into backslash
return (‘\\’);
if (c == ‘n’) // it is ‘\n’ which
compiles into newline
return (‘\n’);
if (c == ‘t’) // it is ‘\t’ which
compiles into ASCII 9
return (9);
}
// Version X+2. Recognizes ‘\\’, ‘\n’ and ‘\t’
char c;
c = next( ); // get next character from program being compiled
if ( c == ‘\’) { // first character of ‘\n’ or
‘\\’ or ‘\t’
c = next( );
if (c == ‘\’) // it is ‘\\’ which
compiles into backslash
return (‘\\’);
if (c == ‘n’) // it is ‘\n’ which
compiles into newline
return (‘\n’);
if (c == ‘t’) // it is ‘\t’ which
compiles into tab
return (‘\t’);
}
The remarkable thing is this: once the compiler is taught, in
Version X+1, that ‘\t’ compiles into ASCII code 9, we can remove
that fact from the compiler in Version X+2 yet the compiler will forever
after know that ‘\t’ compiles into 9!
3. Self-reproducing code
This is a program whose output, when run, is an exact copy of its own
source code! Trust me that this can be done, The lecture includes
an example.
How are these 3 concepts applied to plant this untraceable Trojan Horse?
Again, I will take some poetic license with C syntax to make the code more understandable.
1. Suppose the compiler includes a function which compiles one line of code. Its definition would look something like this:
void compile(String lineOfCode) {
. . .
}
2. Bug the C compiler to recognize a specific line of code and replace it with something else.
void compile(String lineOfCode) {
if (lineOfCode == “pattern”) {
compile(“bug”);
return;
}
. . .
}
where “pattern” represents a specific line of source code from the Unix login command, and “bug” represents source code of the Trojan Horse, which allows Thompson to login as anyone. The match can only occur when compiling the Unix operating system. This is not too hard to do, but cannot be left in the compiler because it will be discovered. We have to go further.
3. Incorporate a second similar bug into the C compiler, shown here as the second IF statement.
void compile(String lineOfCode) {
if (lineOfCode == “pattern”) {
compile(“bug”);
return;
}
if (lineOfCode == “pattern2”) {
compile(“bug2”);
return;
}
. . .
}
where “pattern” and “bug” are the same as before. “pattern2” is a line of code that exists only in the C compiler (thus this match only kicks in when compiling the compiler). “bug2” is a self-reproducing program which will insert both Trojan Horses into the compiled code.
4. The initial C compiler machine code is clean; use it to compile the “dirty” source version from #3. Afterward, both the source code and the machine code of the C compiler are “dirty”.
5. Edit the C compiler source code to remove the two IF statements. The source code is once again clean, as in #1.
6. Compile the newly-cleansed C compiler source code using the dirty C compiler. The dirty C compiler will still match the “pattern2” code because we did not remove it. When this match occurs, the dirty compiler will compile “bug2”, which again inserts both Trojan Horses into the compiler machine code! The machine code of the compiler is forever bugged, unless someone “reverse engineers” it and discovers the skullduggery.
Even if you don’t understand all the nuances of the steps above, understand this: the code that inserted the Trojan Horse into the C compiler is written into the compiler source code one time and then removed after compiling it. Thereafter, any time the compiler is compiled, the Trojan Horse will be propagated to the new version because the code was self-reproducing!
Thompson’s moral of the story: You can’t trust code that you did not totally create yourself.