Please read this description in its entirety before starting the assignment!
In his Turing award lecture, Ken Thompson discusses trust in code, and uses a compiler as an example of a program that can be used to insert a “Trojan horse” (or backdoor) into another program. In this assignment, you are going to replicate his scenario by programming a login application and associated backdoored compiler in Rust.
Security note: In the real world, creating backdoors is a serious security breach and will have legal repercussions. Do not attempt to distribute this code. This assignment is for educational purposes only.
In this assignment, you will:
Create two new projects, one for each part:
$ cargo new a3login # Part 1: The login program
$ cargo new a3cargo # Part 2: The backdoored compiler
There is no starter code for this assignment, so make sure you plan out your code using what you’ve learned so far in the course.
The password database for a3login
,
db.csv
, is available on the course
GitHub repository.
a3login
Your first task is to implement a simple program for handling
user logins, a3login
.
a3login
accepts one argument,
<filename>
, which is the name of a comma-separated
values (CSV) file that contains a username and an Argon2
password hash string. Then, it does the following:
<filename>
from disk as a CSV file.Here are some example sessions of the login program running with expected output. Make sure you follow the exact same format for outputs and inputs as displayed here. The autograder expects this format.
These examples use db.csv
, which is available on the
course
GitHub repository. You will not have to generate new
Argon2 password hash strings for this assignment.
The username admin
and the password
hunter2
is input, which is correct:
$ cargo run db.csv
Enter username: admin
Enter password: hunter2
Access granted!
The username admin
and the password
hunter1
is input, which is incorrect:
$ cargo run db.csv
Enter username: admin
Enter password: hunter1
Error! Access denied!
The username root
, which is not found in the
database:
$ cargo run db.csv
Enter username: root
Enter password: hunter2
Error! Access denied!
Note that the program still asks for the password, even though
root
is not a valid username. (Think about why this
behavior is necessary!)
The program is run on a file that does not exist:
$ cargo run notfound
Error! Password database not found!
Make sure you handle errors properly in your code. Note that all errors must be handled correctly, and the program cannot panic.
a3cargo
Next, you will develop a malicious version of the Rust compiler,
a3cargo
, with a backdoor that specifically targets
a3login
. a3cargo
will modify
a3login
as it is being compiled, adding an extra user
that can log in to the system. Then, before a3cargo
exits, it replaces a3login
with its original version,
in an attempt to not be suspicious.
a3cargo
supports two of the base cargo
operations, build
and run <args>
,
where <args>
is a list of arguments.
Then, it proceeds as follows:
a3login
.
sneaky
as a
username and beaky
as a password, in addition to
whatever is in the database file. cargo
command as a subprocess, which
is either build
or run <args>
.a3login
was the program being compiled: after
execution of the cargo command is complete, restore
a3login
to its original state before modification.Note that db.csv
is not changed – only the
source code of a3login
.
Here is an example session that runs a3cargo
on two
different projects.
First, build and install a3cargo
so it can be used
elsewhere on your system.
$ cd a3cargo/
$ cargo install --path .
Then, you can try running it on a3login
.
$ cd ../a3login/
$ a3cargo build
...
$ a3cargo run db.csv
Enter username: admin
Enter password: hunter2
Access granted!
$ a3cargo run db.csv
Enter username: root
Enter password: hunter2
Error! Access denied!
$ a3cargo run db.csv
Enter username: sneaky
Enter password: beaky
Access granted!
a3cargo
modifies a3login
, which works
as normal – except for the added backdoor. For other programs (i.e.,
not a3login
), a3cargo
works just like
cargo
.
$ cd ../hello/
$ a3cargo run
Hello, world!
After you are done with a3cargo
, make sure to remove
it from your system. You don’t want a backdoored compiler around,
even if you wrote it!
$ cargo uninstall a3cargo
Make sure you handle errors properly in your code. Note that all errors must be handled correctly, and the program cannot panic.
To implement the above programs, you will need to use external crates. For this assignment, you may use any Rust crate; you have the flexibility to choose whatever you would like. Below are some crates that may be helpful as you perform your implementation.
You may also find these standard library features to be helpful:
Of course, the documentation for all of your crates will be critical as you implement the required functionality.
You will need to implement some tests to make sure your code works. It is up to you how you decide to write tests, and for what portions of your code. This may require you splitting up functions so you can test them easier. Part of your grade will be determined by your approach to testing. You may consider applying test-driven development to write your code, but this is not a hard requirement.
a3login
just requires the
verification of passwords, not the generation of new ones. If you’re
generating new hashes and salts, you’re not on the right track!a3cargo
will
detect a3login
, and how it will make
changes, and how it will restore the non-backdoored
source file. This means the compiled binary will be
different from the source file!a3cargo run <args>
accepts a list of
arguments – even though a3login
only needs one
argument, you need to make sure that a3cargo
can
support as many as given.panic!
on an error. This
means you cannot use unwrap()
to bypass error handling.a3login
is complete, and
successfully runs all of the example scenarios above. Additionally,
your code does not panic!
for any reason.a3cargo
is complete,
and successfully runs all of the example scenarios above.
Additionally, your code does not panic!
for any
reason.#[test]
functions) for the program.Upload the following to Blackboard before the due date above:
gzip
ped code archive of your assignment code
gzip
the directory, make sure to run
cargo clean
target/
a3login
and
a3cargo
.a3login
should contain everything in
src/
along with Cargo.toml
.a3cargo
should contain everything in
src/
along with Cargo.toml
.Only one submission per group is necessary. Blackboard is set up
with your project groups for this assignment. Make sure each group
member’s name is in your Cargo.toml
:
authors = ["Partner 1", "Partner 2", "Partner 3", "Partner 4"]