CS 261 Homework 3

Instructions

This homework is totally optional. If you do it, it will be included in your final grade only if it improves your final grade. If you don't do it, you will not be penalized.

This homework is due Monday, December 10th, at 11:59pm.

Work on your own for this homework. You may use any source you like (including other papers or textbooks), but if you use any source not discussed in class, you must cite it.

Question 1: Do a security review of some software

For this question, you will practice doing a security evaluation of some interesting program. Pick any open-source application where security is relevant. The only requirement is that it must consist of at least 2000 lines of code. If you're at a loss for a program to audit, good choices might include network daemons, standard Unix utilities, setuid programs, clients that process data that came from the network (e.g., MP3 players, image viewers, EXIF metadata editors, etc.), or any web application. Or, you could look on Google Code project hosting or on Sourceforge for a software program to audit. Try not to pick an application that is too large or complex; a smaller, well-defined piece of software will make your life easier for this problem.

Then, do all of the following.

  1. What application did you pick? Which version? Give the URL where I can download the source. How many lines of code is it? (One simple way to count the number of lines is using the sloccount program. For C programs, another way is to run "find . -name '*.[ch]' -print | xargs wc -l" from within the source directory.) Include all of this in your write-up.

  2. Spend 1-2 hours familiarizing yourself with it: e.g., how to run it, what it does, reading documentation. Then, based upon your understanding of the program, describe the threat model and security goals for your program in your write-up.

  3. Spend 1-3 hours to understand the architecture and organization of your program. (You may have to browse source code for this, because it is often not documented.) Draw a diagram depicting the program architecture at a high level. Your diagram might show one or more important components of the program and how they interact. It should also show any untrusted external entities or data that the program interacts with, any network communication channels it uses, and any potentially sensitive or untrusted files (or other data containers) that it stores or reads on persistent storage. Your diagram does not need to be complete; do your best to identify the most interesting or security-relevant parts, stopping after 1-2 hours. Include your diagram with the write-up you turn in to this homework.

  4. Based on the diagram you drew and your examination so far, what portions of the program seem most likely to have the highest risk of security holes?

    (If you want some tips on how to build a diagram and identify security risks from it, you could check out Microsoft's introduction to threat modelling (in Powerpoint or pdf) or the STRIDE methodology.)

  5. Select one high-risk portion of the code (from your analysis in Q1.4). Ideally, you'd choose a subset of at most a few hundred lines of code of the program. Spend 1-3 hours reading the code from this portion of the program, looking to see whether the program meets its security goals. This should include an intensive read of the source code, looking for common implementation errors. You don't have to audit all the high-risk code; instead, stop after 1-3 hours, and describe what you did review.

  6. Write a summary of the results of your audit. Did you find any security holes or fishy-looking code? Could the code have been structured better for security? Describe your findings. Attach a copy of your summary to your write-up for the homework.

    (To get the idea of what a summary for Q1.6 might look like, you can refer to a report I wrote a while back, when reviewing a piece of code for fun.)

  7. If you found any security holes, notify the code maintainer as well. Attach to your write-up a copy of your bug report you sent to the code maintainer and (if available) a URL in their bug tracker where I can view the report.

Turn in the entire write-up.

Question 2: Code review

The popular zombie fan site, ThirdDeath, provides a multi-player gaming and virtual world. To allow users to customize their experience in the ThirdDeath virtual world, users can upload custom scripts to the ThirdDeath server and execute them there in a Javascript interpreter. User's scripts are written in Javascript and can interact with special APIs exposed by ThirdDeath (however, they cannot interact with browser DOM APIs or, indeed, any other APIs than the special ones exposed by ThirdDeath). ThirdDeath has recently decided to expose an API that allows users to use the in-game currency and buy stuff with it. I want you to do a code review of the code that keeps track of the amount of money each player has and allows player scripts to manage their currency. Each part of this question asks you to identify a vulnerability that could be exploited by a malicious user script.

The basic framework looks like this:

var bank = (function() {
    var balances = {};
    var tmpnum = 0;
    var transfer = function(payer, rcpt, amount) {
        ... // TBD
    }
    var setBalance = function(name, amount) {
        balances[name] = amount;
    }
    var publicApi = {
        transfer: transfer,
        getBalance: function(name) {
            return balances[name];
        },
        newTmpAccount: function() {
            var name = "tmp" + tmpnum;
            tmpnum++;
            setBalance(name, 0);
            return name;
        }
    }
    return {
        setBalance: setBalance,
        public: publicApi
    }
})();
Alice is a user of ThirdDeath. When Alice paid to create her account with username alice, the ThirdDeath server gave her an initial balance of 100 units by invoking
    bank.setBalance("alice", 100);
Whenever she feels like it, Alice can supply a Javascript user script that defines a top-level function called aliceMain(). The ThirdDeath server will invoke her function, like this:
    aliceMain(bank.public, "alice");

Let's look at how to implement the transfer() function, which was marked TBD above. Each of the following implementations has a vulnerability of some sort that can be exploited by Alice (if she is malicious). All of them can be exploited by Alice on her own, even in the absence of any other user. Describe the vulnerability, then show an example of an implementation of aliceMain() that exploits this vulnerability.

  1. ThirdDeath delegates the implementation of transfer() to an intern, who implements it as follows:
        var transfer = function(payer, rcpt, amount) {
            amount = Number(amount);
            payer = String(payer);
            rcpt = String(rcpt);
            if (!((payer in balances) && (rcpt in balances)))
                return; // Illegal username
            var payer_orig_balance = balances[payer];
            var rcpt_orig_balance = balances[rcpt];
            if (amount < 0)
                return; // Illegal to use negative amounts.
            if (payer_orig_balance < amount)
                return; // Not enough money in payer's account
            balances[payer] = payer_orig_balance - amount;
            balances[rcpt] = rcpt_orig_balance + amount;
        }
    
    Unfortunately, there is a serious problem in this code: a malicious Alice can create money from thin air. Explain how, and show the code of a malicious aliceMain() that exploits this vulnerability.
  2. Before the above is deployed, a more senior programmer refactors the code to the following more concise version:
        var transfer = function(payer, rcpt, amount) {
            payer = String(payer);
            rcpt = String(rcpt);
            if (!((payer in balances) && (rcpt in balances)))
                return; // Illegal username
            if (amount < 0)
                return; // Illegal to use negative amounts.
            if (balances[payer] < amount)
                return; // Not enough money in payer's account
            balances[payer] -= amount;
            balances[rcpt] += amount;
        }
    
    Fortuitously, this closes the vulnerability from Q2.1, but unfortunately, it opens a different attack where Alice can give herself effectively unlimited amounts of money. What is it?

    Hint: read up on the special valueOf() and toString() methods in Javascript, and when they are called. How can you use this to exploit the above code?

  3. Here's a different implementation:
        var transfer = function(payer, rcpt, amount) {
            amount = Number(amount);
            payer = String(payer);
            if (balances[payer]===undefined || balances[rcpt]===undefined)
                return; // Illegal username
            if (amount < 0)
                return; // Illegal to use negative amounts.
            if (balances[payer] < amount)
                return; // Not enough money in payer's account
            balances[rcpt] += amount;
            balances[payer] -= amount;
        }
    
    What's the attack on this one?

Reassurance: You shouldn't need to know anything special about Javascript, beyond that it is a dynamically-typed object-oriented language and (as noted above) about how valueOf() and toString() works. Beyond learning about how valueOf() and toString() work in Javascript, you don't need to know anything fancy about Javascript syntax or semantics to do this problem.

Tips: A convenient way to experiment with Javascript is to use the Squarefree shell in your browser (documentation). If you want to download the complete implementation of the ThirdDeath code, here it is: bank1.js, bank2.js, bank3.js.