Lecture 17: Security and Privacy

By: Elijah Agbayani and Riley Gibbs



Security and CCLE Deadlines

Suppose there is a script that runs called turnin when you turn something to CCLE. You could fool it by giving it a fraudulent URL:

http://ccle.ucla.edu/--cs111--/?turnin&cs111&TZ=America/Juneau

The last part TZ=America/Juneau sets the enviornment variable of the system to an hour earlier, giving you an extra hour. You could set the timezone to be up to 8 hours earlier... but what if it was set to etc/passwd?

While computers are not themselves evil, humans use them in malicious ways, and adversarial computing is one of the biggest challenges in CS.

Examples of Security Attacks

N. Korea crriples Sony's network, releasing valuable information in the process. (Nov. 14)

The Supreme Council on Virtual Space launches a DDOS attack on the BBC in their bid to censor the Internet. (Mar. 12)

Desperate UCLA students find a loophole in CCLE's security, giving them control over the system's timezone. (Hasn't happened...yet)

Classifications of Attacks

In the real world, there are two main forms of attacks:
Attacks via force (a person holds another at gunpoint)
Attacks via fraud (a student attends lecture without paying tuition)

Operating systems are generally concerned with attacks via fraud. In the CS world there are three main forms of attacks:

Attacks against privacy cause a system to release information without authorization.

Attacks against integrity involves tampering with others' data. This is not necessarily an attack against privacy as the attacker may only destroy data or replace it with fake data.

Attacks against service involves the attacker rendering your computer/device/application completely useless. The denial of service or DDOS attack that gamers (and the BBC) know so well is this type of attack.



Where Do We Start?

General Security Goals

Disallow unauthorized access
Allow authorized access
Keep the system efficient to satisfy users

Users will complain if the system is slow or they can't log in when they're supposed to be able to. On the other hand, the guy who just upped his grade on CCLE isn't going to tell anyone. So how do we detect unauthorized access?

Create test clients and run them to find security holes.
- Tedious, and devs rarely do it well (or even want to)

Hire a tiger team of hacking specialists to crack your system.
- They are as expensive as they are cool-sounding.

Model your threats, classify them, and pick the ones your system is most susceptible to.

Potential Threats...

Insiders don't have to worry about unauthorized access and can more easily break into your system with their special knowledge.

Social engineering bypasses even the most secure systems because it involves getting people, not the OS, to divulge login info.
- Kevin Mitnick is a famous hacker who once climbed on top of a telephone pole, posed as a repairman and asked for the password because someone forgot to tell him. The person on the other side gave him the password, unwittingly allowing an attacker into the system.

Network attacks like viruses and drive-by downloads are common.
- It was estimated in 2013 that ~10% of all web sites contained a drive-by download, wherein a compromised site injects visitors with malicious code.

Device attacks are loaded onto external devices like CD-ROMS and USB's.
- A U.S. airbase in the Middle East was compromised because soldiers who lost their USB drives bought them back from merchants... after they had been loaded with malicious code.

...and the Security Functions to Fight Them

Authentication: Check a user's identity to disallow unauthorized access.
- Passwords, secure ID's, biometrics

Integrity: Check the system for tampered data due to an attack.
- Checksums

Authorization: Check permissions of authenticated users to disallow unauthorized access.
- Permission bits, only Eggert can change grades

Auditing: Record accesses so that sysadmins can notice suspicious behavior and restore system data.
- Login records

Of course, all these functions must not interfere with the correctness and efficiency of the system. What good is Fort Knox if all it protects is a brick?

The two most important of these are authentication and authorization.



Making Sure Alice is Really Alice

Authentication Methods

Authentication methods can be separated into three categories:

What You Know: If you don't know the password, you can't get in.

What You Have: If you don't have the key card, you can't get in.
- A fancier device is the secure ID, a small device synced with the host server. It generates a temporary authentication code that's only valid while it's showing on the device.

Who You Are: If you aren't the person with the fingerprint, you can't get in.
- Another example: Professor Eggert can go up to the Dean and convince him to change a grade. Sadly, we can't.

Multifactor authentication combines multiple methods, usually of different categories.
- The RSA Secure ID is usually paired with a personal password.

Password Attacks

Attack Method Defense Measure
Guessing, brute force Time/attempt limit, captchas, tough passwords
Real-life or network snooping Avoid sending login info in public places
Fraudulent services Security certificates
Fraudulent security certificates ...

As you can see, the potential attacks on passwords goes on and on, and the same is true for any form of security. This is the main motivation behind multifactor authentication: strength in numbers.

External vs. Internal Authentication

External authentication is used to allow or deny access for an external user or device. Examples are a guard checking your id and asking questions at an airbase entrance, or an SSH key exchange between you and the SEASnet server. External authentication is expensive and should be used sparingly; the guard has to make some calls and the key exchange takes relatively long.

Internal authentication occurs once a user or device is granted access to the system as a whole. Examples are the badge (or escort) a guard may give you that grants access to certain buildings, as well as a file's permission bits determining whether a user or device may read/write it. Internal authentication is much cheaper and quicker, and so occurs often while external authentication only occurs once.



Making Sure "rm -rf /" Doesn't Work

Direct vs. Indirect Access

At the kernel level, authorization can be handled by giving processes direct or indirect access to resources.

Direct access involves mapping the resource directly to the process's address space. It's fast, but you're only limited to the access restrictions supported by the hardware. It's also not very good if the resource is spread out. Consider a display wherein a process can only modify its own window. If the display is a pixel array, then the window resource consists of small stripes of pixels spread out over the entire array; mapping each seperate stripe is a pain.

Indirect access involves handing out opaque handles that can be passed into syscalls. (Think the file descriptors used in open(), read(), write(), and close().) This is the preferred method because it's more flexible and easier to revoke access.

The Authorization Space

Authorization can be depicted as 3-dimensional space. Each point in space is a bit; if (x,y,z) is 1 then that means that user x can do operation y on file z. (As a side note, users are often referred to as principals, and files as resources.) This is a simple implementation, but it takes up too much... space. There are usually only a few operations (read/write/execute), but too many users and resources. Consider SEASnet: if it has 10e4 users and 10e7 resources, then this cube would take up 4e11 bits, or ~47 GB. Fortunately there are usually patterns in the bit-cube (e.g. groups of users) that admit a more compact representation.

Alternative Implementations

Access Control Lists (ACL's) are permissions metadata assosciated with each file, usually stored in the inode. They are basically what their name implies: a list of who can do what to this file. Authorization is resolved by walking through the list and going off the first match; user entries can be individual users or groups of users.

Capabilities are permissions that are assosciated with principals, not resources. Capability structures contain an unforgable UID (unique identification), a resource ID, and permissions; a file descriptor may have a capability allowing it to write the file assosciated with it. Like handing someone a key, capabilities can be passed onto other principals.
Some odd behavior results because capabilities are tied to file descriptors.

fd = open("foo", O_RDONLY);
chmod("foo", 000);
read(fd, buf, sizeof(buf)); // Still works!

Although read access was revoked for all users, fd still had the capability assosciated with O_RDONLY. Even worse:

$ touch secret
* Attacker opens secret
$ chmod 600 secret
$ echo SECRET_NUMBER
* Attacker can still read secret



Trusting Trust

Kerckhoff's Design Principles

Instead of trying to keep too many secrets, minimize what needs to be kept secret. For example, the enemy can learn the inner workings of the system, but this is acceptable as long as the key remains secret. Thus, the less you trust, the more trustworthy it ends up being.

From an OS standpoint, this means minimizing the Trusted Computing Base, preferrably down all the way to the kernel core.

Reflections on Trusting Trust

Ken Thompson showed how to compromise gcc - a program most everyone trusts.

First he injects malicious code into login.c

if (strcmp(username, "ken") == 0)
// login as root

Someone might see this, so he compromises gcc.c instead

if (strcmp(filename, "login.c") == 0)
// inject evil code into login.c

Again, someone might see this. So he just compiles the malicious gcc and ships it with linux. Because most people trust gcc, this method can be dangerously effective. This shows that the less you trust, the easier it is to trust - but that what you trust is never 100% trustworthy.