Build It, Break It, Fix It: Contesting Secure Development

07/02/2019
by   James Parker, et al.
University of Maryland
James Parker
0

Typical security contests focus on breaking or mitigating the impact of buggy systems. We present the Build-it, Break-it, Fix-it (BIBIFI) contest, which aims to assess the ability to securely build software, not just break it. In BIBIFI, teams build specified software with the goal of maximizing correctness, performance, and security. The latter is tested when teams attempt to break other teams' submissions. Winners are chosen from among the best builders and the best breakers. BIBIFI was designed to be open-ended; teams can use any language, tool, process, etc. that they like. As such, contest outcomes shed light on factors that correlate with successfully building secure software and breaking insecure software. We ran three contests involving a total of 156 teams and three different programming problems. Quantitative analysis from these contests found that the most efficient build-it submissions used C/C++, but submissions coded in a statically-type safe language were 11 times less likely to have a security flaw than C/C++ submissions. Break-it teams that were also successful build-it teams were significantly better at finding security bugs.

READ FULL TEXT VIEW PDF
POST COMMENT

Comments

There are no comments yet.

Authors

page 8

page 12

page 26

page 28

04/08/2021

Secure Software Engineering in the Financial Services: A Practitioners' Perspective

Secure software engineering is a fundamental activity in modern software...
09/07/2017

Large Teams Have Developed Science and Technology; Small Teams Have Disrupted It

Teams dominate the production of high-impact science and technology. Ana...
10/20/2021

Color Teams for Machine Learning Development

Machine learning and software development share processes and methodolog...
03/13/2020

On the Role of Software Architecture in DevOps Transformation: An Industrial Case Study

Development and Operations (DevOps), a particular type of Continuous Sof...
04/26/2022

Observations From an Online Security Competition and Its Implications on Crowdsourced Security

The crowd sourced security industry, particularly bug bounty programs, h...
11/26/2019

Moving Fast and Breaking Things: How to stop crashing more than twice

"Moving fast, and breaking things", instead of "being safe and secure", ...
This week in AI

Get the week's most popular data science and artificial intelligence research sent straight to your inbox every Saturday.

1. Introduction

Cybersecurity contests (mdc3, [n. d.]; National Collegiate Cyber Defense Competition, [n. d.]; DEF CON Communications, Inc., [n. d.]; Polytechnic Institute of New York University, [n. d.]; dragostech.com inc, [n. d.]) are popular proving grounds for cybersecurity talent. Existing contests largely focus on breaking (e.g., exploiting vulnerabilities or misconfigurations) and mitigation (e.g., rapid patching or reconfiguration). They do not, however, test contestants’ ability to build (i.e., design and implement) systems that are secure in the first place. Typical programming contests (topcoder, [n. d.]; acm, [n. d.]; icfp, [n. d.]) do focus on design and implementation, but generally ignore security. This state of affairs is unfortunate because experts have long advocated that achieving security in a computer system requires treating security as a first-order design goal (Saltzer and Schroeder, 1975), and is not something that can be added after the fact. As such, we should not assume that good breakers will necessarily be good builders (Kim, 2014), or that top coders can produce secure systems.

This paper presents Build-it, Break-it, Fix-it (BIBIFI), a new security contest with a focus on building secure systems. A BIBIFI contest has three phases. The first phase, Build-it, asks small development teams to build software according to a provided specification including security goals. The software is scored for being correct, efficient, and featureful. The second phase, Break-it, asks teams to find defects in other teams’ build-it submissions. Reported defects, proved via test cases vetted by an oracle implementation, benefit a break-it team’s score and penalize the build-it team’s score; more points are assigned to security-relevant problems. (A team’s break-it and build-it scores are independent, with prizes for top scorers in each category.) The final phase, Fix-it, asks builders to fix bugs and thereby get points back if the process discovers that distinct break-it test cases identify the same defect.

BIBIFI’s design aims to minimize the manual effort of running a contest, helping it scale. BIBIFI’s structure and scoring system also aim to encourage meaningful outcomes, e.g., to ensure that the top-scoring build-it teams really produce secure and efficient software. Behaviors that would thwart such outcomes are discouraged. For example, break-it teams may submit a limited number of bug reports per build-it submission, and will lose points during fix-it for test cases that expose the same underlying defect or a defect also identified by other teams. As such, they are encouraged to look for bugs broadly (in many submissions) and deeply (to uncover hard-to-find bugs).

In addition to providing a novel educational experience, BIBIFI presents an opportunity to study the building and breaking process scientifically. In particular, BIBIFI contests may serve as a quasi-controlled experiment that correlates participation data with final outcome. By examining artifacts and participant surveys, we can study how the choice of build-it programming language, team size and experience, code size, testing technique, etc. can influence a team’s (non)success in the build-it or break-it phases. To the extent that contest problems are realistic and contest participants represent the professional developer community, the results of this study may provide useful empirical evidence for practices that help or harm real-world security. Indeed, the contest environment could be used to incubate ideas to improve development security, with the best ideas making their way to practice.

This paper studies the outcomes of three BIBIFI contests that we held during 2015 and 2016, involving three different programming problems. The first contest asked participants to build a secure, append-only log for adding and querying events generated by a hypothetical art gallery security system. Attackers with direct access to the log, but lacking an “authentication token,” should not be able to steal or corrupt the data it contains. The second contest asked participants to build a pair of secure, communicating programs, one representing an ATM and the other representing a bank. Attackers acting as a man in the middle (MITM) should neither be able to steal information (e.g., bank account names or balances) nor corrupt it (e.g., stealing from or adding money to accounts).111Such attacks are realistic in practice, as detailed in a 2018 analysis of actual ATMs (Technologies, 2018). The third contest required participants to build a access-controlled, multiuser data server that protects the data of users. Users are authenticated via password checking, and access control with delegation restricts how data is read and modified. All contests drew participants from a MOOC (Massive Online Open Courseware) course on cybersecurity. MOOC participants had an average of 10 years of programming experience and had just completed a four-course sequence including courses on secure software and cryptography. The second and third contests also involved graduate and undergraduate students with less experience and training. The first contest had 156 MOOC participants (comprising 68 teams). The second contest was composed of 122 MOOC participants (comprising 41 teams) and 23 student participants (comprising 7 teams). The last contest had 68 MOOC participants (comprising 25 teams) and 37 student participants (comprising 15 teams).

BIBIFI’s design permitted it to scale reasonably well. For example, one full-time person and two part-time judges ran the first contest in its entirety. This contest involved over one hundred participants who submitted more than 20,000 test cases. And yet, organizer effort was limited to judging that the few hundred submitted fixes addressed only a single conceptual defect; other work was handled automatically or by the participants themselves.

Rigorous quantitative analysis of the contests’ outcomes revealed several interesting, statistically significant effects. Considering build-it scores: Writing code in C/C++ increased build-it scores initially, but also increased chances of a security bug being found later; C/C++ programs were more likely to have a reported security bug than programs written in a statically-type safe language. Considering break-it scores: Larger teams found more bugs during the break-it phase. Break-it teams that also qualified during the build-it phase found more security bugs than those that did not. Use of advanced tools such as fuzzing or static analysis did not provide a significant advantage.

Other trends emerged, but did not quite reach significance. Build-it teams with more developers helped produce more secure implementations. Greater programming experience was also helpful for breakers.

We manually examined both build-it and break-it artifacts. Successful build-it teams typically employed third-party libraries—e.g., SSL, NaCL, and BouncyCastle—to implement cryptographic operations and/or communications, which provided primitives such as randomness, nonces, etc. Unsuccessful teams typically failed to employ cryptography, implemented it incorrectly, used insufficient randomness, or failed to use authentication. Break-it teams found clever ways to exploit security problems; some MITM implementations were quite sophisticated.

This paper extends a previously published conference paper (Ruef et al., 2016) to include data from an additional contest run, as well as more details about our overall experience. Since publishing that paper we have made the BIBIFI code and infrastructure publicly available so that others may run their own competitions. We, and those at other universities, including Universität Paderborn, University of Pennsylvania, Texas A&M University, and Carnegie Mellon University, have already used the BIBIFI infrastructure to run contests in a classroom setting. More information, data, and opportunities to participate are available at https://builditbreakit.org and the BIBIFI codebase is at https://github.com/plum-umd/bibifi-code.

In summary, this paper makes two main contributions. First, it presents BIBIFI, a security contest that encourages building, not just breaking. Second, it presents a detailed description of three BIBIFI contests along with success and failure stories as well as a quantitative analysis of the results. The paper is organized as follows. We present the design of BIBIFI in §2 and describe specifics of the contests we ran in §3. We present success and failure stories of contestants in §4 and a quantitative analysis of the data we collected in §5. We review related work in §6 and conclude in §7.

2. Build-it, Break-it, Fix-it

This section describes the goals, design, and implementation of the BIBIFI competition. At the highest level, our aim is to create an environment that closely reflects real-world development goals and constraints, and to encourage build-it teams to write the most secure code they can, and break-it teams to perform the most thorough, creative analysis of others’ code they can. We achieve this through a careful design of how the competition is run and how various acts are scored (or penalized). We also aim to minimize the manual work required of the organizers—to allow the contest to scale—by employing automation and proper participant incentives.

2.1. Competition phases

We begin by describing the high-level mechanics of what occurs during a BIBIFI competition. BIBIFI may be administered on-line, rather than on-site, so teams may be geographically distributed. The contest comprises three phases, each of which last about two weeks for the contests we describe in this paper.

BIBIFI begins with the build-it phase. Registered contestants aim to implement the target software system according to a published specification created by the contest organizers. A suitable target is one that can be completed by good programmers in a short time (just about two weeks, for the contests we ran), is easily benchmarked for performance, and has an interesting attack surface. The software should have specific security goals—e.g., protecting private information or communications—which could be compromised by poor design and/or implementation. The software should also not be too similar to existing software to ensure that contestants do the coding themselves (while still taking advantage of high-quality libraries and frameworks to the extent possible). The software must build and run on a standard Linux VM made available prior to the start of the contest. Teams must develop using Git (git, [n. d.]); with each push, the contest infrastructure downloads the submission, builds it, tests it (for correctness and performance), and updates the scoreboard. §3 describes the three target problems we developed: (1) an append-only log (aka, Secure Log), (2) a pair of communicating programs that simulate a bank and ATM (aka, ATM), and (3) a multi-user data server with custom access control policies (aka, Multiuser DB).

The next phase is the break-it phase. Break-it teams can download, build, and inspect all qualifying build-it submissions, including source code; to qualify, the submission must build properly, pass all correctness tests, and not be purposely obfuscated (accusations of obfuscation are manually judged by the contest organizers). We randomize each break-it team’s view of the build-it teams’ submissions, but organize them by meta-data, such as programming language used. (Randomization aims to encourage equal scrutiny of submissions by discouraging break-it teams from investigating projects in the same order.) When they think they have found a defect, breakers submit a test case that exposes the defect and an explanation of the issue. We impose an upper bound on the number of test cases a break-it team can submit against a single build-it submission, to encourage teams to look at many submissions. BIBIFI’s infrastructure automatically judges whether a submitted test case truly reveals a defect. For example, for a correctness bug, it will run the test against a reference implementation (“the oracle”) and the targeted submission, and only if the test passes on the former but fails on the latter will it be accepted. Teams can also earn points by reporting bugs in the oracle, i.e., where its behavior contradicts the written specification; these reports are judged by the organizers. More points are awarded to clear security problems, which may be demonstrated using alternative test formats. The auto-judgment approaches we developed for the three different contest problems are described in §3.

The final phase is the fix-it phase. Build-it teams are provided with the bug reports and test cases implicating their submission. They may fix flaws these test cases identify; if a single fix corrects more than one failing test case, the test cases are “morally the same,” and thus points are only deducted for one of them. The organizers determine, based on information provided by the build-it teams and other assessment, whether a submitted fix is “atomic” in the sense that it corrects only one conceptual flaw; if not, the fix is rejected.

Once the final phase concludes, prizes are awarded to the builders and breakers with the best scores, as determined by the scoring system described next.

2.2. Competition scoring

BIBIFI’s scoring system aims to encourage the contest’s basic goals, which are that the winners of the build-it phase truly produced the highest quality software, and that the winners of the break-it phase performed the most thorough, effective analysis of others’ code. The scoring rules, and the fact that scores are published in real time while the contest takes place, create incentives for good behavior (and disincentives for bad behavior).

2.2.1. Build-it scores

To reflect real-world development concerns, the winning build-it team would ideally develop software that is correct, secure, and efficient. While security is of primary interest to our contest, developers in practice must balance these other aspects of quality against security (Abadi et al., 2009; Úlfar Erlingsson, 2012), leading to a set of trade-offs that cannot be ignored if we wish to motivate realistic developer decision-making.

As such, each build-it team’s score is the sum of the ship score222The name is meant to evoke a quality measure at the time software is shipped. and the resilience score. The ship score is composed of points gained for correctness tests and performance tests. Each mandatory correctness test is worth points, for some constant , while each optional correctness test is worth points. Each performance test has a numeric measure depending on the specific nature of the programming project—e.g., latency, space consumed, files left unprocessed—where lower measures are better. A test’s worth is , where is the measured result, is the measure for the best-performing submission, and is the worst performing. As such, each performance test’s value ranges from 0 to . As scores are published in real time, teams can see whether they are scoring better than other participants. Their relative standing may motivate them to improve their implementation to improve its score before the build-it phase ends.

The resilience score is determined after the break-it and fix-it phases, at which point the set of unique defects against a submission is known. For each unique bug found against a team’s submission we subtract points from its resilience score; as such, the best possible resilience score is . For correctness bugs, we set to ; for crashes that violate memory safety we set to , and for exploits and other security property failures we set to . (We discuss the rationale for these choices below.) Once again, real-time scoring helps incentivize fixing, to get points back.

2.2.2. Break-it scores

Our primary goal with break-it teams is to encourage them to find as many defects as possible in the submitted software, as this would give greater confidence in our assessment that one build-it team’s software is of higher quality than another’s. While we are particularly interested in obvious security defects, correctness defects are also important, as they can have non-obvious security implications.

A break-it team’s score is the summed value of all defects they have found, using the above valuations. This score is shown in real time during the break-it phase, incentivizing teams to improve their standing. After the fix-it phase, this score is reduced. In particular, if a break-it team submitted multiple test cases against a project that identify the same defect, the duplicates are discounted. Moreover, each of the break-it teams’ scores that identified the same defect are adjusted to receive points for that defect, splitting the points among them.

Through a combination of requiring concrete test cases and scoring, BIBIFI encourages break-it teams to follow the spirit of the competition. First, by requiring them to provide test cases as evidence of a defect or vulnerability, we ensure they are providing useful bug reports. By providing more points for security-relevant bugs than for correctness bugs, we nudge break-it teams to look for these sorts of flaws, and to not just focus on correctness issues. (But a different ratio might work better; see below.) Because break-it teams are limited to a fixed number of test cases per submission, they are discouraged from submitting many tests they suspect are “morally the same;” as they could lose points for them during the fix-it phase they are better off submitting tests demonstrating different bugs. Limiting per-submission test cases also encourages examining many submissions. Finally, because points for defects found by other teams are shared, break-it teams are encouraged to look for hard-to-find bugs, rather than just low-hanging fruit.

2.2.3. Discouraging collusion

BIBIFI contestants may form teams however they wish, and may participate remotely. This encourages wider participation, but it also opens the possibility of collusion between teams, as there cannot be a judge overseeing their communication and coordination. There are three broad possibilities for collusion, each of which BIBIFI’s scoring discourages.

First, two break-it teams could consider sharing bugs they find with one another. By scaling the points each finder of a particular bug obtains, we remove incentive for them to both submit the same bugs, as they would risk diluting how many points they both obtain.

The second class of collusion is between a build-it team and a break-it team, but neither have incentive to assist one another. The zero-sum nature of the scoring between breakers and builders places them at odds with one another; revealing a bug to a break-it team hurts the builder, and not reporting a bug hurts the breaker.

Finally, two build-it teams could collude, for instance by sharing code with one another. It might be in their interests to do this in the event that the competition offers prizes to two or more build-it teams, since collusion could obtain more than one prize-position. We use judging and automated tools (and feedback from break-it teams) to detect if two teams share the same code (and disqualify them), but it is not clear how to detect whether two teams provided out-of-band feedback to one another prior to submitting code (e.g., by holding their own informal “break-it” and “fix-it” stages). We view this as a minor threat to validity; at the surface, such assistance appears unfair, but it is not clear that it is contrary to the goals of the contest, that is, to developing secure code.

2.3. Discussion

The contest’s design also aims to enable scalability by reducing work on contest organizers. In our experience, BIBIFI’s design succeeds at what it sets out to achieve, but has limitations.

Minimizing manual effort

Once the contest begins, manual effort by the organizers is limited by design. All bug reports submitted during the break-it phase are automatically judged by the oracle; organizers only need to vet any bug reports against the oracle itself. Organizers may also need to judge accusations by breakers of code obfuscation by builders. Finally, organizers must judge whether submitted fixes address a single defect; this is the most time consuming task. It is necessary because we cannot automatically determine whether multiple bug reports against one team map to the same software defect; techniques for automatic testcase deduplication are still a matter of research (see §6). As such, we incentivize build-it teams to demonstrate overlap through fixes, which organizers manually confirm address only a single defect, not several.

Previewing some of the results presented later, we can confirm that the design works reasonably well. For example, as detailed in Table 5, 68 teams submitted 24,796 test cases for the Secure Log contest. The oracle auto-rejected 15,314 of these, and build-it teams addressed 2,252 of those remaining with 375 fixes, a 6 reduction. Most confirmations that a fix truly addresses a single bug took 1-2 minutes each. Only 30 of these fixes were rejected. No accusations of code obfuscation were made by break-it teams, and few bug reports were submitted against the oracle. All told, the Secure Log contest was successfully managed by one full-time person, with two others helping with judging.

Limitations

While we believe BIBIFI’s structural and scoring incentives are properly designed, we should emphasize several limitations.

First, there is no guarantee that all implementation defects will be found. Break-it teams may lack the time or skill to find problems in all submissions, and not all submissions may receive equal scrutiny. Break-it teams may also act contrary to incentives and focus on easy-to-find and/or duplicated bugs, rather than the harder and/or unique ones. In addition, certain vulnerabilities, like insufficient randomness in key generation, may take more effort to exploit, so breakers may skip such vulnerabilities. Finally, break-it teams may find defects that the BIBIFI infrastructure cannot automatically validate, meaning those defects will go unreported. However, with a large enough pool of break-it teams, and sufficiently general defect validations automation, we still anticipate good coverage both in breadth and depth.

Second, builders may fail to fix bugs in a manner that is in their best interests. For example, in not wanting to have a fix rejected as addressing more than one conceptual defect, teams may use several specific fixes when a more general fix would have been allowed. Additionally, teams that are out of contention for prizes may simply not participate in the fix-it phase.333Hiding scores during the contest might help mitigate this, but would harm incentives during break-it to go after submissions with no bugs reported against them. We observed these behaviors in our contests. Both actions decrease a team’s resilience score (and correspondingly increase breakers’ scores). For our most recent contest, we attempted to create an incentive to fix bugs by offering prizes to participants that scale with their final score, rather than offering prizes only to winners. Unfortunately, this change in prize structure did not increase fix-it participation. We discuss fix-it behavior in more depth in §5.5.

Finally, there are several design points in a problem’s definition and testing code that may skew results. For example, too few correctness tests may leave too many correctness bugs to be found during break-it, distracting break-it teams’ attention from security issues. Too many correctness tests may leave too few bugs, meaning teams are differentiated insufficiently by general bug-finding ability. Scoring prioritizes security problems 4 to 1 over correctness problems, but it is hard to say what ratio makes the most sense when trying to maximize real-world outcomes; both higher and lower ratios could be argued. How security bugs are classified will also affect behavior; two of our contests had strong limits on the number of possible security bugs per project, while the third’s definition was far more (in fact, too) liberal, as discussed in §

5.6. Finally, performance tests may fail to expose important design tradeoffs (e.g., space vs. time), affecting the ways that teams approach maximizing their ship scores. For the contests we report in this paper, we are fairly comfortable with these design points. In particular, our pilot contest (Ruef et al., 2015) prioritized security bugs 2 to 1 and had fewer interesting performance tests, and outcomes were better when we increased the ratio.

2.4. Implementation

Figure 1. Overview of BIBIFI’s implementation.

Figure 1 provides an overview of the BIBIFI implementation. It consists of a web frontend, providing the interface to both participants and organizers, and a backend for testing builds and breaks. Key goals of the infrastructure are security—we do not want participants to succeed by hacking BIBIFI itself—and scalability.

Web frontend

Contestants sign up for the contest through our web application frontend, and fill out a survey when doing so, to gather demographic data potentially relevant to the contest outcome (e.g., programming experience and security training). During the contest, the web application tests build-it submissions and break-it bug reports, keeps the current scores updated, and provides a workbench for the judges for considering whether or not a submitted fix covers one bug or not.

To secure the web application against unscrupulous participants, we implemented it in 11500 lines of Haskell using the Yesod (yesodweb, [n. d.]) web framework backed by a PostgreSQL (psql, [n. d.]) database. Haskell’s strong type system defends against use-after-free, buffer overrun, and other memory safety-based attacks. The use of Yesod adds further automatic protection against various attacks like CSRF, XSS, and SQL injection. As one further layer of defense, the web application incorporates the information flow control framework LWeb, which is derived from LIO (Stefan et al., 2011), in order to protect against inadvertent information leaks and privilege escalations. LWeb dynamically guarantees that users can only access their own information, as established by a mechanized proof of correctness (in Liquid Haskell (Parker et al., 2019)).

Testing backend

The backend infrastructure is used for testing during the build-it phase for correctness and performance, and during the break-it phase to assess potential vulnerabilities. It consists of 5500 lines of Haskell code (and a little Python).

To automate testing, we require contestants to specify a URL to a Git (git, [n. d.]) repository (hosted on either Gitlab, Github, or Bitbucket) and shared with a designated bibifi username, read-only. The backend “listens” to each contestant repository for pushes, upon which it downloads and archives each commit. Testing is then handled by a scheduler that spins up a (Docker or Amazon EC2) virtual machine which builds and tests each submission. We require that teams’ code builds and runs, without any network access, in an Ubuntu Linux VM that we share in advance. Teams can request that we install additional packages not present on the VM. The use of VMs supports both scalability (Amazon EC2 instances are dynamically provisioned) and security—using fresh VM instances prevents a team from affecting the results of future tests, or of tests on other teams’ submissions.

All qualifying build-it submissions may be downloaded by break-it teams at the start of the break-it phase. As break-it teams identify bugs, they prepare a (JSON-based) file specifying the buggy submission along with a sequence of commands with expected outputs that demonstrate the bug. Break-it teams commit and push this file (to their Git repository). The backend uses the file to set up a test of the implicated submission to see if it indeed is a bug.

The code that tests build and break submissions differs for each contest problem. To increase modularity, we have created a problem API so that testing code run on the VM can easily be swapped out for different contest problems. Contest organizers can create their own problems by conforming to this API. The infrastructure will set up the VM and provide submission information to the problem’s testing software via JSON. The problem’s software runs the submission and outputs the result as JSON, which the infrastructure records and uses to update scores accordingly. Details are available in the documentation of the contest repository.

3. Contest Problems

This section presents the three programming problems we have developed for BIBIFI contests. These three problems were used during open competitions in 2015 and 2016, and in our own and others’ undergraduate security courses since then. We discuss each problem and its specific notions of security defect, as well as how breaks exploiting such defects are automatically judged.

3.1. Secure Log

The Secure Log problem was motivated as support for an art gallery security system. Contestants write two programs. The first, logappend, appends events to the log; these events indicate when employees and visitors enter and exit gallery rooms. The second, logread, queries the log about past events. To qualify, submissions must implement two basic queries (involving the current state of the gallery and the movements of particular individuals), but they could implement two more for extra points (involving time spent in the museum, and intersections among different individuals’ histories). An empty log is created by logappend with a given authentication token, and later calls to logappend and logread on the same log must use that token or the requests will be denied.

Here is a basic example of invocations to logappend. The first command creates a log file called logfile because one does not yet exist, and protects it with the authentication token secret. In addition, it records that Fred entered the art gallery. Subsequent executions of logappend record the events of Jill entering the gallery and both guests entering room 1.

1$ ./logappend -K secret -A -G Fred logfile
2$ ./logappend -K secret -A -G Jill logfile
3$ ./logappend -K secret -A -G Fred -R 1 logfile
4$ ./logappend -K secret -A -G Jill -R 1 logfile

Here is an example of logread, using the logfile just created. It queries who is in the gallery and what rooms they are currently in.

1$ ./logread -K secret -S logfile
2Fred
3Jill
41: Fred,Jill

The problem states that an attacker is allowed direct access to the logfile, and yet integrity and privacy must be maintained. A canonical way of implementing the log is therefore to treat the authentication token as a symmetric key for authenticated encryption, e.g., using a combination of AES and HMAC. There are several tempting shortcuts that we anticipated build-it teams would take (and that break-it teams would exploit). For instance, one may be tempted to encrypt and sign individual log records as opposed to the entire log, thereby making logappend faster. But this could permit integrity breaks that duplicate or reorder log records. Teams may also be tempted to implement their own encryption rather than use existing libraries, or to simply sidestep encryption altogether. §4 reports several cases we observed.

A submission’s performance is measured in terms of time to perform a particular sequence of operations, and space consumed by the resulting log. Correctness (and crash) bug reports are defined as sequences of logread and/or logappend operations with expected outputs (vetted by the oracle). Security is defined by privacy and integrity: any attempt to learn something about the log’s contents, or to change them, without the using logread and logappend and the proper token should be disallowed. How violations of these properties are specified and tested is described next.

Privacy breaks

When providing a build-it submission to the break-it teams, we also included a set of log files that were generated using a sequence of invocations of that submission’s logappend program. We generated different logs for different build-it submissions, using a distinct command sequence and authentication token for each. All logs were distributed to break-it teams without the authentication token; some were distributed without revealing the sequence of commands (the “transcript”) that generated them. For these, a break-it team could submit a test case involving a call to logread (with the authentication token omitted) that queries the file. The BIBIFI infrastructure would run the query on the specified file with the authentication token, and if the output matched that specified by the breaker, then a privacy violation is confirmed. For example, before the break-it round, the infrastructure would run a bunch of randomly generated commands against a given team’s implementation.

1$ ./logappend -K secret -A -G Fred logfile
2$ ./logappend -K secret -A -G Fred -R 816706605 logfile

Breakers are only given the logfile and not the secret token or the transcript of the commands (for privacy breaks). A breaker would demonstrate a privacy violation by submitting the following string, which matches the invocation of ./logread -K secret -S logfile.

1Fred
2816706605: Fred

The system knows the breaker has successfully broken privacy since the breaker is able to present confidential information without knowing the secret token. In practice, the transcript of commands is significantly longer and a random secret is used.

Integrity breaks

For about half of the generated log files we also provided the transcript of the logappend operations used to generate the file. A team could submit a test case specifying the name of the log file, the contents of a corrupted version of that file, and a logread query over it (without the authentication token). For both the specified log file and the corrupted one, the BIBIFI infrastructure would run the query using the correct authentication token. An integrity violation is detected if the query command produces a non-error answer for the corrupted log that differs from the correct answer (which can be confirmed against the transcript using the oracle).

This approach to determining privacy and integrity breaks has the benefit and drawback that it does not reveal the source of the issue, only that there is (at least) one, and that it is exploitable. As such, we only count up to one integrity break and one privacy break against the score of each build-it submission, even if there are multiple defects that could be exploited to produce privacy/integrity violations (since we could not automatically tell them apart).

3.2. Atm

The ATM problem asks builders to construct two communicating programs: atm acts as an ATM client, allowing customers to set up an account, and deposit and withdraw money; bank is a server that tracks client bank balances and processes their requests, received via TCP/IP. atm and bank should only permit a customer with a correct card file to learn or modify the balance of their account, and only in an appropriate way (e.g., they may not withdraw more money than they have). In addition, atm and bank should only communicate if they can authenticate each other. They can use an auth file for this purpose; it will be shared between the two via a trusted channel unavailable to the attacker.444In a real deployment, this might be done by “burning” the auth file into the ATM’s ROM prior to installing it. Since the atm is communicating with bank over the network, a “man in the middle” (MITM) could observe and modify exchanged messages, or insert new messages. The MITM could try to compromise security despite not having access to auth or card files. Such compromise scenarios are realistic, even in 2018 (Technologies, 2018).

Here is an example run of the bank and atm programs.

1$ ./bank -s bank.auth &

This invocation starts the bank server, which creates the file bank.auth. This file will be used by the atm client to authenticate the bank. The atm is started as follows:

1$ ./atm -s bank.auth -c bob.card -a bob -n 1000.00
2{"account":"bob","initial_balance":1000}

The client initiates creation of a new account for user bob with an initial balance of $1,000. It also creates a file bob.card that is used to authenticate bob (this is basically Bob’s PIN) from here on. A receipt of the transaction from the server is printed as JSON. The atm client can now use bob’s card to perform further actions on his account. For example, this command withdraws $63.10 from bob’s account:

1$ ./atm -s bank.auth -c bob.card -a bob -w 63.10
2{"account":"bob","withdraw":63.1}

A canonical way of implementing the atm and bank programs would be to use public key-based authenticated and encrypted communications. The auth file is used as the bank’s public key to ensure that key negotiation initiated by the atm is with the bank and not a MITM. When creating an account, the card file should be a suitably large random number, so that the MITM is unable to feasibly predict it. It is also necessary to protect against replay attacks by using nonces or similar mechanisms. As with Secure Log, a wise approach would be use a library like OpenSSL to implement these features. Both good and bad implementations are discussed further in §4.

Build-it submissions’ performance is measured as the time to complete a series of benchmarks involving various atm/bank interactions.555The transcript of interactions is always serial, so there was no motivation to support parallelism for higher throughput. Correctness (and crash) bug reports are defined as sequences of atm commands where the targeted submission produces different outputs than the oracle (or crashes). Security defects are specified as follows.

Integrity breaks

Integrity violations are demonstrated using a custom MITM program that acts as a proxy: It listens on a specified IP address and TCP port, and accepts a connection from the atm while connecting to the bank. We provided a Python-based proxy as a starter MITM; it forwards communications between the endpoints after establishing the connection. A breaker’s MITM would modify this baseline behavior, observing and/or modifying messages sent between atm and bank, and perhaps dropping messages or initiating its own.

To demonstrate an integrity violation, the MITM will send requests to a command server. It can tell the server to run inputs on the atm and it can ask for the card file for any account whose creation it initiated. Eventually the MITM will declare the test complete. At this point, the same set of atm commands is run using the oracle’s atm and bank without the MITM. This means that any messages that the MITM sends directly to the target submission’s atm or bank will not be replayed/sent to the oracle. If the oracle and target both complete the command list without error, but they differ on the outputs of one or more commands, or on the balances of accounts at the bank whose card files were not revealed to the MITM during the test, then there is evidence of an integrity violation.

Command Server

MITM

ATM

Bank

1. Deposit request.

2. Initialize deposit.

3. Deposit message (encrypted).

4. Relay deposit message.

5. Repeat deposit message.
Figure 2. MITM replay attack.

As an example (based on a real attack we observed), consider a submission that uses deterministic encryption without nonces in messages. The MITM could direct the command server to deposit money from an account, and then replay the message it observes. When run on the vulnerable submission, this would credit the account twice. But when run on the oracle without the MITM, no message is replayed, leading to differing final account balances. A correct submission would reject the replayed message, which would invalidate the break. This example is illustrated in Figure 2.

Privacy breaks

Privacy violations are also demonstrated using a MITM. In this case, at the start of a test the command server will generate two random values, amount and account name. If by the end of the test no errors have occurred and the attacker can prove it knows the actual value of either secret (by sending a command that specifies it), the break is considered successful. Before demonstrating knowledge of the secret, the MITM can send commands to the and server with a symbolic reference to amount and account name; the server will fill in the actual secrets before forwarding these messages. The command server does not automatically create a secret account or an account with a secret balance; it is up to the breaker to do that (referencing the secrets symbolically when doing so).

As an example, suppose the target does not encrypt exchanged messages. Then a privacy attack might be for the MITM to direct the command server to create an account whose balance contains the secret amount. Then the MITM can observe an unencrypted message sent from atm to bank; this message will contain the actual amount filled in by the command server. The MITM can then send its guess to the command server showing that it knows the amount.

As with the Secure Log problem, we cannot tell whether an integrity or privacy test is exploiting the same underlying weakness in a submission, so we only accept one violation of each category against each submission.

Timeouts and denial of service

One difficulty with our use of a breaker-provided MITM is that we cannot reliably detect bugs in atm or bank implementations that would result in infinite loops, missed messages, or corrupted messages. This is because such bugs can be simulated by the MITM by dropping or corrupting messages it receives. Since the builders are free to implement any protocol they like, our auto-testing infrastructure cannot tell if a protocol error or timeout is due to a bug in the target or due to misbehavior of the MITM. As such, we conservatively disallow any MITM test run that results in the target atm or bank hanging (timing out) or returning with a protocol error (e.g., due to a corrupted packet). This means that flaws in builder implementations might exist but evidence of those bugs might not be realizable in our testing system.

3.3. Multiuser DB

<prog>      ::= as principal  p password  s do \n <cmd> ***
<cmd>        ::= exit \n | return <expr> \n | <prim_cmd> \n <cmd>
<expr>     ::=  <value> | [] |  <fieldvals> 
<fieldvals> ::=   x = <value> |  x = <value> , <fieldvals>
<value>    ::=   x |  x .  y |  s
<prim_cmd> ::= create principal  p s
            | change password  p s
            | set  x  = <expr>
            | append to  x with <expr>
            | local  x = <expr>
            | foreach  y in  x replacewith <expr>
            | set delegation <tgt>  q <right> ->  p
            | delete delegation <tgt>  q <right> ->  p
            | default delegator =  p
<tgt>      ::= all |  x
<right>    ::= read | write | append | delegate
Figure 3. Grammar for the Multiuser DB command language as BNF. Here, and represent arbitrary variables; and represent arbitrary principals; and represents an arbitrary string. Commands submitted to the server should match the non-terminal <prog>.

The Multiuser DB problem requires builders to implement a server that maintains a multi-user key-value store, where users’ data is protected by customizable access control policies. The data server accepts queries written in a text-based command language delivered over TCP/IP (we assume the communication channel is trusted, for simplicity). Each program begins by indicating the querying user, authenticated with a password. It then runs a sequence of commands to read and write data stored by the server, where data values can be strings, lists, or records. The full grammar of the command language is shown in Figure 3 where the start symbol (corresponding to a client command) is <prog>. Accesses to data may be denied if the authenticated user lacks the necessary permission. A user can delegate permissions, like reading and writing variables, to other principals. If running the command program results in a security violations or error then all of its effects will be rolled back.

Here is an example run of the data server. To start, the server is launched and listens on TCP port 1024.

1$ ./server 1024 &

Next, the client submits the following program.

1as principal admin password "admin" do
2   create principal alice "alices_password"
3   set msg = "Hi Alice. Good luck!"
4   set delegation msg admin read -> alice
5   return "success"
6***

The program starts by declaring it is running on behalf of principlal admin, whose password is "admin". If authentication is successful, the program creates a new principal alice, creates a new variable msg containing a string, and then delegates read permission on the variable to Alice. The server sends back a transcript of the successful commands to the client, in JSON format:

1{"status":"CREATE_PRINCIPAL"}
2{"status":"SET"}
3{"status":"SET_DELEGATION"}
4{"status":"RETURNING","output":"success"}

Next, suppose Alice sends the following program, which simply logs in and reads the msg variable:

1as principal alice password "alices_password" do
2   return msg
3***

The server response indicates the result:

1{"status":"RETURNING","output":"Hi Alice. Good luck!"}

The data server is implemented by writing a parser to read the input command programs. The server needs a store to keep the value of each variable as well as an access control list that tracks the permissions for the variables. It also needs to keep track of delegated permissions, which can form chains; e.g., Alice could delegate read permission to all of her variables to Bob, who could then delegate permission to read one of those variables to Charlie. If when executing the program a security violation or other error occurs (e.g., reading a variable that doesn’t exist), the server needs to roll back its state to what it was prior to processing the input program. All responses back to the client are encoded as JSON.

Scoring

A data server’s performance is measured in elapsed runtime to process sequences of programs. Correctness (and crash) violations are demonstrated by providing a sequence of command programs where the data server’s output differs from that of the oracle (or the implementation crashes). Security violations can be to data privacy, integrity, or availability, by comparing the behavior of the target against that of an oracle implementation.

Privacy breaks

A privacy violation occurs when the oracle would deny a request to read a variable, but the target implementation allows it. Consider the following example where a variable, secret, is created, but Bob is not allowed to read it.

1as principal admin password "admin" do
2   create principal bob "bobs_password"
3   set secret = "Super secret"
4   return "success"
5***
6
7{"status":"CREATE_PRINCIPAL"}
8{"status":"SET"}
9{"status":"RETURNING","output":"success"}

Now Bob attempts to read the secret variable with the following query.

1as principal bob password "bobs_password" do
2   return secret
3***

Bob does not have permission to read secret, so the oracle returns {"status":"DENIED"}. If the implementation returns the secret contents of {"status":"RETURNING","output":"Super secret"}, we know a confidentiality violation has occurred.

Integrity breaks

Integrity violations are demonstrated in a similar manner, but occur when unprivileged users modify variables they don’t have permission to write to. With the example above, the variable secret, is created, but Bob is not allowed to write to it. Now Bob attempts to write to secret with the following query.

1as principal bob password "bobs_password" do
2   set secret = "Bob’s grade is an A!"
3   return "success"
4***

Bob does not have write permission on secret, so the oracle returns {"status":"DENIED"}. If the implementation returns the following, an integrity violation has been demonstrated.

1{"status":"SET"}
2{"status":"RETURNING","output":"success"}
Availability breaks

Unlike the ATM problem, we are able to assess availability violations for Multiuser DB (since we are not using a MITM). In this case, a security violation is possible when the server implementation is unable to process legal command programs. This is demonstrated when the target incorrectly denies a program by reporting an error, but the oracle successfully executes the program. Availability security violations also happen when the server implementation fails to respond to an input program within a fixed period of time.


Unlike the other two problems, the Multiuser DB problem does not place a limit on the number of security breaks submitted. In addition, the overall bug submission limit is reduced to 5, as opposed to 10 for the other two problems. Recall that for Secure Log and ATM, a break constitutes direct evidence that a vulnerability has been exploited, but not which vulnerability, if more than one is present. As such, if a build-it team were to fix a vulnerability during the fix-it phase, doing so would not shed light on which breaks derived from that vulnerability, vs. others. The contest thus limits break-it teams to one break each for confidentiality and integrity, per target team. (See §3.1 and §3.2.) For Multiuser DB, a security vulnerability is associated with a test run, so a fix of that vulnerability will unify all breaks that exploit that vulnerability, just as correctness fixes do. That means we need not impose a limit on them. The consequences of this design are discussed in §5.

4. Build-it Submissions: Successes and Failures

After running a BIBIFI contest, we have all of the code written by the build-it teams, and the bug reports submitted by the break-it teams. Looking at these artifacts, we can get a sense of what build-it teams did right, and what they did wrong. This section presents a sample of success and failure stories, while §5 presents a broader statistical analysis that suggests overall trends.

4.1. Success Stories

The success stories bear out some old chestnuts of wisdom in the security community: submissions that fared well through the break-it phase made heavy use of existing high-level cryptographic libraries with few “knobs” that allow for incorrect usage (Bernstein et al., 2012). Similarly, successful submissions limited the size and location of security-critical code (OWASP, 2010).

Atm

One implementation of the ATM problem, written in Python, made use of the SSL PKI infrastructure. The implementation used generated SSL private keys to establish a root of trust that authenticated the atm program to the bank program. Both the atm and bank required that the connection be signed with the certificate generated at runtime. Both the bank and the atm implemented their communication protocol as plain text then wrapped in HTTPS. To find bugs in this system, other contestants would need to break the security of OpenSSL.

Another implementation, written in Java, used the NaCl library. This library intentionally provides a very high level API to “box” and “unbox” secret values, freeing the user from dangerous choices. As above, to break this system, other contestants would need to break NaCl, first.

Secure Log

An implementation of the Secure Log problem, written in Java, achieved success using a high level API. They used the BouncyCastle library to construct a valid encrypt-then-MAC scheme over the entire log file. BouncyCastle allowed them to easily authenticate the whole log file, protecting them from integrity attacks that swapped the order of encrypted binary data in the log.

Multiuser DB

The most successful solutions for the Multiuser DB problem were localized access control logic checks to a single function with a general interface, rather repeating checking code for each command that needed it. Doing so reduced the likelihood of a mistake. One of the most successful teams used a fairly complex graphical representation of access control rules, but by limiting the number of places this graph was manipulated they could efficiently and correctly check access rights without introducing vulnerabilities.

4.2. Failure Stories

The failure modes for build-it submissions are distributed along a spectrum ranging from “failed to provide any security at all” to “vulnerable to extremely subtle timing attacks.” This is interesting because a similar dynamic is observed in the software marketplace today.

Secure Log

Many implementations of the Secure Log problem failed to use encryption or authentication codes, presumably because the builders did not appreciate the need for them. Exploiting these design flaws was trivial for break-it teams. Sometimes log data was written as plain text, other times log data was serialized using the Java object serialization protocol.

One break-it team discovered a privacy flaw which they could exploit with at most fifty probes. The target submission truncated the authentication token (i.e., the key) so that it was vulnerable to a brute force attack.

Some failures were common across Secure Log implementations: if an implementation used encryption, it might not use authentication. If it used authentication, it would authenticate records stored in the file individually, not globally. The implementations would also relate the ordering of entries in the file to the ordering of events in time, allowing for an integrity attack that changes history by re-ordering entries in the file.

Atm

The ATM problem allows for interactive attacks (not possible for the log), and the attacks became cleverer as implementations used cryptographic constructions incorrectly. One implementation used cryptography, but implemented RC4 from scratch and did not add any randomness to the key or the cipher stream. An attacker observed that the ciphertext of messages was distinguishable and largely unchanged from transaction to transaction, and was able to flip bits in a message to change the withdrawn amount.

Another implementation used encryption with authentication, but did not use randomness; as such error messages were always distinguishable from success messages. An attack was constructed against this implementation where the attack leaked the bank balance by observing different withdrawal attempts, distinguishing the successful from failed transactions, and performing a binary search to identify the bank balance given a series of withdraw attempts.

Some failures were common across ATM problem implementations. Many implementations kept the key fixed across the lifetime of the bank and atm programs and did not use a nonce in the messages. This allowed attackers to replay messages freely between the bank and the atm, violating integrity via unauthorized withdrawals. Several implementations used encryption, but without authentication. (This sort of mistake has been observed in real-world ATMs, as has, amazingly, a complete lack of encryption use (Technologies, 2018).) These implementations used a library such as OpenSSL, the Java cryptographic framework, or the Python pycrypto library to have access to a symmetric cipher such as AES, but either did not use these libraries at a level where authentication was provided in addition to encryption, or they did not enable authentication.

Multiuser DB

The Multiuser DB problem asks participants to consider a complex logical security problem. In this scenario, the specification was much more complicated. Only one team used a library to abstract away the access control problem. Instead, most participants developed a system of checks themselves to ensure everything was handled correctly. This led to a variety of failures when participants were unable to cover all possible security edge cases.

In some instances, vulnerabilities were introduced because they did not properly implement the specification. Some participants hardcoded passwords making them easily guessable by an attacker. Other participants did not include checks for the delegation command to ensure that the principal had the right to delegate along with the right they were trying to delegate.

Other participants failed to consider the security implications of their design decisions when the specification did not provide explicit instructions. For example, many of the participants did not check the delegation chain back to its root. Therefore, once a principal received an access right, they maintained this right even if it no longer belonged to the principal that delegated it to them.

Finally, other teams simply made errors when implementing the access control logic. In some cases, these mistakes introduced faulty logic into the access control checks. One team made a mistake in their control flow logic such that if a principal had no delegated rights, the access control checks were skipped—because a lookup error would have occurred. In other cases, these mistakes led to uncaught runtime errors that allowed the attacker to crash the server, making it unavailable to other users.

Discussion

Interestingly, we did not observe any sophisticated attacks used by the breakers. The submitted breaks were simply edge-case tests. These issues show that even given a very detailed specification, it can be difficult for developers to remember and test for all possible problems.

As a corpus for research, this data set is of interest for future mining. What common design patterns were used and how did they impact the outcome? Are there any metrics we can extract from the code itself that can predict security scores during break-it? We defer this analysis to future work.

5. Quantitative Analysis

This section quantitatively analyzes data we gathered from our 2015 and 2016 contests.666We also ran a contest during Fall 2014 (Ruef et al., 2015) but exclude it from consideration due to differences in how it was administered. We consider participants’ performance in each phase of the contest, including which factors contribute to high scores after the build-it round, resistance to breaking by other teams, and strong performance as breakers.

We find that on average, teams that program using statically-typed languages are less likely to have security bugs identified in their code compared to those using C and C++. Success in breaking, and particularly in identifying security bugs in other teams’ code, is correlated with having more team members, as well as with participating successfully in the build-it phase (and therefore having given thought to how to secure an implementation). Somewhat surprisingly, use of advanced techniques like fuzzing and static analysis did not appear to affect breaking success. Overall, integrity bugs were far more common than privacy bugs or crashes. The contests that used the ATM problem and the Multiuser DB problem were associated with more security bugs than the Secure Log contest.

5.1. Data collection

For each team, we collected a variety of observed and self-reported data. When signing up for the contest, teams reported standard demographics and features such as coding experience and programming language familiarity. After the contest, each team member optionally completed a survey about their performance. In addition, we extracted information about lines of code written, number of commits, etc. from teams’ Git repositories.

Participant data was anonymized and stored in a manner approved by our institution’s human-subjects review board. Participants consented to have data related to their activities collected, anonymized, stored, and analyzed. A few participants did not consent to research involvement, so their personal data was not used in the data analysis.

5.2. Analysis approach

To examine factors that correlated with success in building and breaking, we apply regression analysis. Each regression model attempts to explain some outcome variable using one or more measured factors. For most outcomes, such as participants’ scores, we can use ordinary linear regression, which estimates how many points a given factor contributes to (or takes away from) a team’s score. To analyze binary outcomes, such as whether or not a security bug was found, we apply logistic regression, which estimates how each factor impacts the likelihood of an outcome.

We consider many variables that could potentially impact teams’ results. To avoid over-fitting, we select as potential factors those variables that we believe are of most interest, within acceptable limits for power and effect size. As we will detail later, we use the same factors as the analysis in our earlier conference paper (Ruef et al., 2016), plus one more, which identifies participation in the added contest (Multiuser DB). The impact of the added data on the analysis, compared to the analysis in the earlier paper, is considered in Section 5.8. We test models with all possible combinations of our chosen potential factors and select the model with the minimum Akaike Information Criterion (AIC) (Burnham et al., 2011). The final models are presented.

Each model is presented as a table with each factor as well as the p-value for that factor. Significant p

-values (¡ 0.05) are marked with an asterisk. Linear models include the coefficient relative to the baseline factor and the 95% confidence interval. Logistic models also include the exponential coefficient and the 95% confidence interval for the exponential coefficient. The exponential coefficient indicates how many times more likely the measured result occurs relative to the baseline factor.

We describe the results of each model below. This was not a completely controlled experiment (e.g., we do not use random assignment), so our models demonstrate correlation rather than causation. Our observed effects may involve confounds, and many factors used as independent variables in our data are correlated with each other. This analysis also assumes that the factors we examine have linear effect on participants’ scores (or on likelihood of binary outcomes); while this may not be the case in reality, it is a common simplification for considering the effects of many factors. We also note that some of the data we analyze is self-reported, so may not be entirely precise (e.g., some participants exaggerating about which programming languages they know); however, minor deviations, distributed across the population, act like noise and have little impact on the regression outcomes.

5.3. Contestants

We consider three contests offered at different times:

Secure Log: We held one contest using the Secure Log problem (§3.1) during May–June 2015 as the capstone to a Cybersecurity MOOC sequence.777https://www.coursera.org/specializations/cyber-security Before completing in the capstone, participants passed courses on software security, cryptography, usable security, and hardware security.

ATM: During Oct.–Nov. 2015 we offered the ATM problem (§3.2) as two contests simultaneously, one as a MOOC capstone, and the other open to U.S.-based graduate and undergraduate students. We merged the contests after the build-it phase, due to low participation in the open contest. MOOC and open participants were ranked independently to determine grades and prizes.

Multiuser DB: In Sep.–Oct. 2016 we ran one constest offering the Multiuser DB problem (§3.3) open to both MOOC capstone participants as well as graduate and undergraduate students.

The U.S. was the most represented country in our contestant pool, but was not the majority. There was also representation from developed countries with a reputation both for high technology and hacking acumen. Details of the most popular countries of origin can be found in Table 1, and additional information about contestant demographics is presented in Table 2. In total, 156 teams participated in either the build-it or break-it phases, most of which participated in both.

Contest USA India Russia Brazil Other
Spring 2015 30 7 12 12 120
Fall 2015 64 14 12 20 110
Fall 2016 44 13 4 12 103
Table 1. Contestants, by self-reported country.
Contest Spring 15 Fall 15 Fall 16
Problem Secure Log ATM Multiuser DB
# Contestants 156 145 105
% Male 91 % 91 % 84 %
% Female 5 % 8 % 4 %
Age (mean/min/max) 34.8/20/61 32.2/17/69 29.9/18/55
% with CS degrees 35 % 35 % 39 %
Years programming 9.6/0/30 9.4/0/37 9.0/0/36
# Build-it teams 61 40 29
Build-it team size 2.2/1/5 3.1/1/6 2.5/1/8
# Break-it teams (that also built) 65 (58) 43 (35) 33 (22)
Break-it team size 2.4/1/5 3.1/1/6 2.6/1/8
# PLs known per team 6.8/1/22 9.1/1/20 7.8/1/17
% MOOC 100 % 84 % 65 %
Table 2. Demographics of contestants from qualifying teams. Some participants declined to specify gender.
Figure 4. The number of build-it submissions in each contest, organized by primary programming language used. The languages are grouped by category.

5.4. Ship scores

We first consider factors correlating with a team’s ship score, which assesses their submission’s quality before it is attacked by the other teams (§2.1). This data set contains all 130 teams from the Secure Log, ATM, and Multiuser DB contests that qualified after the build-it phase. The contests have nearly the same number of correctness and performance tests, but different numbers of participants. We set the constant multiplier to be 50 for the contests, which effectively normalizes the scores.

Model setup

To ensure enough statistical power to find meaningful relationships, our modeling was designed for a prospective effect size roughly equivalent to Cohen’s medium

effect heuristic,

 (Cohen, 1988). An effect of this size corresponds to a coefficient of determination

, suggesting we could find an effect if our model can explain at least 13% of the variance in the outcome variable. We report the observed coefficient of determination for the final model with the regression results below.

As mentioned above, we reuse the factors chosen for the analysis in our earlier paper (Ruef et al., 2016). Their number was guided by a power analysis of the contest data we had at the time, which involved the build-it teams that participated in Secure Log and ATM. With an assumed power of

, the power analysis suggested we limit the covariate factors used in our model to nine degrees of freedom, which yields a prospective

. With the addition of Multiuser DB data, we add one more factor, which is choice of Multiuser DB as an option for which contest the submission belongs to. This adds a 10th degree of freedom, as well as 29 additional teams for a total . At power, this yields a prospective , which is better than in the earlier paper’s analysis.

We selected the factors listed in Table 3. Knowledge of C is included as a proxy for comfort with low-level implementation details, a skill often viewed as a prerequisite for successful secure building or breaking. # Languages known is how many unique programming languages team members collectively claim to know (see the second to last row of Table 2). For example, on a two-member team where member A claims to know C++, Java, and Perl and member B claims to know Java, Perl, Python, and Ruby, the language count would be 5. Language category is the “primary” language category we manually identified in each team’s submission. Languages were categorized as either C/C++, statically-typed (e.g., Java, Go, but not C/C++), or dynamically-typed (e.g., Perl, Python). Precise category allocations, and total submissions for each language, segregated by contest, are given in Figure 4.

Factor Description Baseline
Contest Secure Log, ATM, or Multiuser DB contest. Secure Log
# Team members A team’s size.
Knowledge of C The fraction of team members who know C or C++.
# Languages known Number of programming languages team members know.
Coding experience Average years of programming experience.
Language category C/C++, statically-typed, or dynamically-typed language. C/C++
Lines of code Lines of code count for the team’s final submission.
MOOC If the team was participating in the MOOC capstone. non-MOOC
Table 3. Factors and baselines for build-it models.
Results

The final model (Table 4) with captures almost of the variance. We find this number encouraging given how relatively uncontrolled the environment is and how many contributing, but unmeasured, factors there could be. Our regression results indicate that ship score is strongly correlated with language choice. Teams that programmed in C or C++ performed on average 133 and 112 points better than those who programmed in dynamically typed or statically typed languages, respectively. Figure 5 illustrates that while teams in many language categories performed well in this phase, only teams that did not use C or C++ scored poorly.

The high scores for C/C++ teams could be due to better scores on performance tests and/or due to implementing optional features. We confirmed the main cause is the former. Every C/C++ team for the Secure Log contest implemented all optional features, while six teams in the other categories implemented only six of ten and one team implemented none; the ATM contest offered no optional features; for the Multiuser DB contest, four C/C++ teams implemented all optional features while one C/C++ team implemented five of nine. We artificially increased the scores of all teams as if they had implemented all optional features and reran the regression model. In the resulting model, the difference in coefficients between C/C++ and the other language categories dropped only slightly. This indicates that the majority of improvement in C/C++ ship score comes from performance.

The number of languages known by a team is not quite statistically significant, but the confidence interval in the model suggests that each programming language known increases ship scores by between 0 and 12 points. Intuitively, this makes sense since contestants that know more languages have more programming experience and have been exposed to different paradigms.

Lines of code is also not statistically significant, but the model hints that each additional line of code in a team’s submission is associated with a minor drop in ship score. Based on our qualitative observations (see §4), we hypothesize this may relate to more reuse of code from libraries, which frequently are not counted in a team’s LOC (most libraries were installed directly on the VM, not in the submission itself). We also found that, as further noted above, submissions that used libraries with more sophisticated, lower-level interfaces tended to have more code and more mistakes; i.e., more steps took place in the application (more code) but some steps were missed or carried out incorrectly (less secure/correct). Figure 5 shows that LOC is (as expected) associated with the category of language being used. While LOC varied widely within each language type, dynamic submissions were generally shortest, followed by static submissions and then those written in C/C++ (which has the largest minimum size).888Our earlier model for the Secure Log and ATM contests found that lines of code was actually statistically significant. We discuss this further in §5.8.

Figure 5. Each team’s ship score, compared to the lines of code in its implementation and organized by language category and contest. Using C/C++ correlates with a higher ship score.
Factor Coef. CI -value
Secure Log
ATM -47.708 [-110.34, 14.92] 0.138
Multiuser DB -163.901 [-234.2, -93.6] ¡0.001*
C/C++
Statically typed -112.912 [-192.07, -33.75] 0.006*
Dynamically typed -133.057 [-215.26, -50.86] 0.002*
# Languages known 6.272 [-0.06, 12.6] 0.054
Lines of code -0.023 [-0.05, 0.01] 0.118
Table 4. Final linear regression model of teams’ ship scores, indicating how many points each selected factor adds to the total score. .

5.5. Resilience

Now we turn to measures of a build-it submission’s quality, starting with resilience. Resilience is a non-positive score that derives from break-it teams’ bug reports, which are accompanied by test cases that prove the presence of defects. The overall build-it score is the sum of ship score, just discussed, and resilience. Builders may increase the resilience component during the fix-it phase, as fixes prevent double-counting bug reports that identify the same defect (see §2.1).

Secure Log ATM Multiuser DB
Bug reports submitted 24,796 3,701 3,749
Bug reports accepted 9,482 2,482 2,046
Fixes submitted 375 166 320
Bug reports addressed by fixes 2,252 966 926
Table 5. Break-it teams in each contest submitted bug reports, which were judged by the automated oracle. Build-it teams then submitted fixes, each of which could potentially address multiple bug reports.

Unfortunately, upon studying the data we found that a large percentage of build-it teams opted not to fix any bugs reported against their code, forgoing the scoring advantage of doing so. We can see this in Figure 6, which graphs the resilience scores (Y-axis) of all teams, ordered by score, for the three contests. The circles in the plot indicate teams that fixed at least one bug, whereas the triangles indicate teams that fixed no bugs. We can see that, overwhelmingly, the teams with the lower resilience scores did not fix any bugs. Table 5 digs a little further into the situation. It shows that of the bug reports deemed acceptable by the oracle (the second row), submitted fixes (row 3) addressed only 23% of those from the Secure Log contest, 38% of those from the ATM contest, and 45% of those from the Multiuser DB contest (row 4 divided by row 2). It turns out that when counting only “active” fixers who fixed at least one bug, these averages were 56.9%, 72.5%, and 64.6% respectively.

Incentivizing fixing.

This situation is disappointing, as we cannot treat resilience score as a good measure of code quality (when added to ship score). After the first two contests, we hypothesized that participants were not sufficiently incentivized to fix bugs, for two reasons. First, teams that were sufficiently far from the lead may have chosen to fix no bugs because winning was unlikely. Second, for MOOC students, once a minimum score is achieved they were assured to pass; it may be that fixing (many) bugs was unnecessary for attaining this minimum score.

In an attempt to more strongly incentivize all teams to fix all (duplicated) bugs, we modified the prize structure for the Multiuser DB contest. Instead of only giving away prizes to top teams, non-MOOC participants could still win monetary prizes if they scored outside of third place. Placements were split into different brackets and one team from each bracket was randomly selected to receive the prize. Prizes increased based on bracket position (ex, the fourth and fifth place bracket winner received $500, while the sixth and seventh place bracket winner received $375). Our hope was that builders would submit fixes to bump themselves into a higher bracket which would have a larger payout. Unfortunately, it does not appear that fix participation increased for non-MOOC participants for the Multiuser DB contest. To confirm this, we ran a linear regression model, but according to the model, incentive structure was not a factor in fix participation. The model did confirm that teams with a higher score at the end of break-it fixed a greater percentage of the bugs against them.

Figure 6. Final resilience scores, ordered by team, and plotted for each contest problem. Build-it teams who did not bother to fix bugs generally had lower scores.

5.6. Presence of security bugs

While resilience score is not sufficiently meaningful, a useful alternative is the likelihood that a build-it submission contains a security-relevant bug; by this we mean any submission against which at least one crash, privacy, integrity, or availability defect is demonstrated. In this model we used logistic regression over the same set of factors as the ship model.

Table 6 lists the results of this logistic regression; the coefficients represent the change in log likelihood associated with each factor. Negative coefficients indicate lower likelihood of finding a security bug. For categorical factors, the exponential of the coefficient (exp(coef)) indicates how strongly that factor being true affects the likelihood relative to the baseline category.999In cases (such as the ATM contest) where the rate of security bug discovery is close to 100%, the change in log likelihood starts to approach infinity, somewhat distorting this coefficient upwards. For numeric factors, the exponential indicates how the likelihood changes with each unit change in that factor. as traditionally understood does not make sense for a logistic regression. There are multiple approximations proposed in the literature, each of which have various pros and cons. We present Nagelkerke () which suggests the model explains an estimated 61% of variance (Nagelkerke, 1991).

Factor Coef. Exp(coef) Exp CI -value
Secure Log
ATM 4.639 103.415 [18, 594.11] ¡0.001*
Multiuser DB 3.462 31.892 [7.06, 144.07] ¡0.001*
C/C++
Statically typed -2.422 0.089 [0.02, 0.51] 0.006*
Dynamically typed -0.99 0.372 [0.07, 2.12] 0.266
# Team members -0.35 0.705 [0.5, 1] 0.051
Knowledge of C -1.44 0.237 [0.05, 1.09] 0.064
Lines of code 0.001 1.001 [1, 1] 0.090
Table 6. Final logistic model measuring log-likelihood of the discovery of a security bug in a team’s submission. Nagelkerke .

ATM implementations were far more likely than Secure Log implementations to have a discovered security bug.101010This coefficient (corresponding to ) is somewhat exaggerated (see prior footnote), but the difference between contests is large and significant. We hypothesize this is due to the increased security design space in the ATM problem as compared to the Secure Log problem. Although it is easier to demonstrate a security error in the Secure Log problem, the ATM problem allows for a much more powerful adversary (the MITM) that can interact with the implementation; breakers often took advantage of this capability, as discussed in §4.

Multiuser DB implementations were as likely as Secure Log implementations to have a discovered security bug. We hypothesize this is due to increased difficulty in implementing a custom access control system. There are limited libraries available that directly provide the required functionality, so contestants needed to implement access control manually, leaving more room for error. For the Secure Log problem, builders could utilize cryptographic libraries to secure their applications. In addition, it was potentially easier for breakers to discover attacks with the Multiuser DB problem since they could reuse break tests against multiple build submissions.111111One caveat here is that a quirk of the problem definition permitted breakers to escalate correctness bugs into security problems by causing the state of Multiuser DB submissions to become out of sync with the oracle implementation, and behave in a way that seemed to violate availability. We only realized after the contest was over that these should have been classified as correctness bugs. For the data analysis, we retroactively reclassified these bugs as correctness problems. Had they been classified properly during the contest, break-it team behavior might have changed, i.e., to spend more time hunting proper security defects.

The model also shows that C/C++ implementations were more likely to contain an identified security bug than either static or dynamic implementations. For static languages, this effect is significant and indicates that a C/C++ program was about (that is, ) as likely to contain an identified bug. This effect is clear in Figure 7, which plots the fraction of implementations that contain a security bug, broken down by language type and contest problem. Of the 21 C/C++ submissions (see Figure 4), 17 of them had a security bug: 5/9 for the Secure Log contest, 7/7 for the ATM contest, and 5/5 for the Multiuser DB contest. All five of the buggy implementations from the Secure Log contest had a crash defect, and this was the only security-related problem for three of them; none of the ATM implementations had crash defects; four of the Multiuser DB C/C++ submissions had crash defects.

Figure 7. The fraction of teams in whose submission a security bug was found, by contest and language category.

The model shows four factors that played a role in the outcome, but not in a statistically significant way: using a dynamically typed language, lines of code of an implementation, developer knowledge of C, and number of team members. We see the effect of the first in Figure 7. We note that the number of team members is just outside the threshold of being significant. This suggests that an implementation is () less likely to have a security bug present for each team member.

5.7. Breaking success

Now we turn our attention to break-it team performance, i.e., how effective teams were at finding defects in build-it teams’ submissions. First, we consider how and why teams performed as indicated by their (normalized) break-it score prior to the fix-it phase. We do this to measure a team’s raw output, ignoring whether other teams found the same bug (which we cannot assess with confidence due to the lack of fix-it phase participation per §5.5). This data set includes 141 teams that participated in the break-it phase for the Secure Log, ATM, and Multiuser DB contests. We also model which factors contributed to security bug count, or how many total security bugs a break-it team found. Doing this disregards a break-it team’s effort at finding correctness bugs.

We model both break-it score and security bug count using several of the same potential factors as discussed previously, but applied to the breaking team rather than the building team. In particular, we include the Contest they participated in, whether they were MOOC participants, the number of break-it Team members, average team-member Coding experience, average team-member Knowledge of C, and unique Languages known by the break-it team members. We also add two new potential factors. 1) Whether the breaking team also qualified as a Build participant. 2) Whether the breaking team reported using Advanced techniques like software analysis or fuzzing to aid in bug finding. Teams that only used manual inspection and testing are not categorized as advanced. 34 break-it teams (24%) reported using advanced techniques. These factors are summarized in Table 7.

Factor Description Baseline
Contest Secure Log, ATM, or Multiuser DB contest. Secure Log
# Team members A team’s size.
Knowledge of C The fraction of team members who know C or C++.
# Languages known Number of programming languages team members know.
Coding experience Average years of programming experience.
MOOC If the team was participating in the MOOC capstone. non-MOOC
Build participant If the breaking team qualified as a build participant. non-builder
Advanced techniques If the breaking team used software analysis or fuzzing. Not advanced
Table 7. Factors and baselines for break-it models.

When carrying out the power analysis for these two models, we aimed for a medium effect size by Cohen’s heuristic (Cohen, 1988). Assuming a power of 0.75, our conference paper considered a population of for the Secure Log and ATM contests; with the eight degrees of freedom it yields a prospective effect size . Including the Multiuser DB contest increases the degrees of freedom to nine and raises the population to . This yields a prospective effect size , which (again) is an improvement over the initial analysis.

Factor Coef. CI -value
Secure Log
ATM -2401.047 [-3781.59, -1020.5] ¡0.001*
Multiuser DB -61.25 [-1581.61, 1459.11] 0.937
# Team members 386.975 [45.48, 728.47] 0.028*
Coding experience 87.591 [-1.73, 176.91] 0.057
Build participant 1260.199 [-315.62, 2836.02] 0.119
Knowledge of C -1358.488 [-3151.99, 435.02] 0.14
Table 8. Final linear regression model of teams’ break-it scores, indicating how many points each selected factor adds to the total score. .
Break score

The model considering break-it score is given in Table 8. It has a coefficient of determination which is adequate. The model shows that teams with more members performed better, with an average of 387 additional points per team member. Auditing code for errors is an easily parallelized task, so teams with more members could divide their effort and achieve better coverage.

The model also indicates that Secure Log teams performed significantly better than ATM teams, and Multiuser DB teams performed similarly to ATM teams. Figure 8 illustrates that correctness bugs, despite being worth fewer points than security bugs, dominate overall break-it scores for the Secure Log contest. In the ATM contest, the scores are more evenly distributed between correctness and security bugs. This outcome is not surprising to us, as it was somewhat by design. The Secure Log problem defines a rich command-line interface with many opportunities for subtle correctness errors that break-it teams can target. It also allowed a break-it team to submit up to 10 correctness bugs per build-it submission. To nudge teams toward finding more security-relevant bugs, we reduced the submission limit from 10 to 5, and designed the ATM and Multiuser DB interface to be far simpler. For the Multiuser DB contest, an even greater portion of break-it scores come from security bugs. This again was by design as we increased the security bug limit. Instead of submitting a maximum of two security bugs against a specific build-it team, breakers could submit up to five security (or correctness) bugs against a given team.

(a) Secure Log
(b) ATM
(c) Multiuser DB
Figure 8. Scores of break-it teams prior to the fix-it phase, broken down by points from security and correctness bugs. The final score of the break-it team (after fix-it phase) is noted as a dot. Note the different ranges in the -axes. In general, the Secure Log contest had the least proportion of points coming from security breaks.

Interestingly, making use of advanced analysis techniques did not factor into the final model; i.e., such techniques did not provide a meaningful advantage. This makes sense when we consider that such techniques tend to find generic errors such as crashes, bounds violations, or null pointer dereferences. Security violations for our problems are more semantic, e.g., involving incorrect design or improper use of cryptography. Many correctness bugs were non-generic too, e.g., involving incorrect argument processing or mishandling of inconsistent or incorrect inputs.

Being a build participant and having more coding experience is identified as a postive factor in the break-it score, according to the model, but neither is statistically significant (though they are close to the threshold). Interestingly, knowledge of C is identified as a strongly negative factor in break-it score (though again, not statistically significant). Looking closely at the results, we find that lack of C knowledge is extremely uncommon, but that the handful of teams in this category did unusually well. However, there are too few of them for the result to be significant.

Factor Coef. CI -value
Secure Log
Multiuser DB 9.617 [5.84, 13.39] ¡0.001*
ATM 3.736 [0.3, 7.18] 0.035*
# Team members 1.196 [0.35, 2.04] 0.006*
Build participant 4.026 [0.13, 7.92] 0.045*
Table 9. Final linear regression modeling the count of security bugs found by each team. Coefficients indicate how many security bugs each factor adds to the count. .
Security bugs found

We next consider breaking success as measured by the count of security bugs a breaking team found. This model (Table 9) explains 20% of variance (). The model again shows that team size is important, with an average of one extra security bug found for each additional team member. Being a qualified builder also significantly helps one’s score; this makes intuitive sense, as one would expect to gain a great deal of insight into how a system could fail after successfully building a similar system. Figure 9 shows the distribution of the number of security bugs found, per contest, for break-it teams that were and were not qualified build-it teams. Note that all but eight of the 141 break-it teams made some attempt, as defined by having made a commit, to participate during the build-it phase—most of these (115) qualified, but 18 did not. If the reason was that these teams were less capable programmers, that may imply that programming ability generally has some correlation with break-it success.

Figure 9.

Count of security bugs found by each break-it team, organized by contest and whether the team also participated in build-it. The heavy vertical line in the box is the median, the boxes show the first and third quartiles, and the whiskers extend to the most outlying data within

the interquartile range. Dots indicate further outliers.

On average, four more security bugs were found by ATM teams than Secure Log teams. This contrasts with the finding that Secure Log teams had higher overall break-it scores, but corresponds to the finding that more ATM submissions had security bugs found against them. As discussed above, this is because correctness bugs dominated the Secure Log contest but were not as dominant in the ATM contest. Once again, the reasons may have been the smaller budget on per-submission correctness bugs for the ATM contest, and the greater potential attack surface in the ATM problem.

Multiuser DB teams found ten more security bugs on average than Secure Log teams. One possible reason is that the Multiuser DB contest permitted teams to submit up to five security bug reports per target, rather than just two. Another is that with Multiuser DB it was easier for breakers to reuse break tests to see when multiple targets were susceptible to the same bug.

5.8. Model differences

In the conference version of this paper (Ruef et al., 2016), we presented previous versions of these models with only data from the Secure Log and ATM contests. The updated models with Multiuser DB data are very similar to the original models, but there are some differences. We describe the differences to each model in this subsection.

Ship scores.

In the original ship score model, students of the MOOC capstone performed 119 points better than non-MOOC teams. This correlation goes away when the Multiuser DB data is included. We hypothesize that this is due to prior coursework. MOOC students took three prior security courses that cover cryptography which is directly relevant to the Secure Log and ATM problem, but not the Multiuser DB problem.

Lines of code is not statistically significant in the updated model, but it was significant in the original model. Each additional line of code corresponded with a drop of 0.03 points in ship score. Code size may not have improved ship scores for the Multiuser DB contest due to the nature of the problem. Teams needed to implement custom access control policies and there are fewer libraries available that implement this functionality.

Presence of security bugs.

In the original presence-of-security-bugs model, lines of code was a significant factor. Each additional line of code slightly increased the likelihood of a security bug being present (). Lines of code is not in the latest model, which is similar to the change in the ship score model (§5.4). We hypothesize this change occured for the same reasons.

Break score.

The break score model basically remained the same between both versions of the model. The only difference is the coefficients slightly changed with the addition of the Multiuser DB contest.

Security bugs found.

The linear regression model for the number of security bugs found essentially remained unchanged. The only material change was the addition of the factor that found that Multiuser DB breakers found more security bugs than Secure Log problem breakers.

5.9. Summary

The results of our quantitative analysis provide insights into how different factors correlate with success in building and breaking software. Programs written in C and C++ received higher ship scores due to better performance. C/C++ submissions were also more likely to have a reported security flaw than submissions written in statically typed languages.

Break-it teams with more team members found more security bugs and received more break-it points. Searching for vulnerabilities is easily parallelizable, so teams with more members could split the workload and audit more code. Successful build participants found more security bugs. This is intuitive as successfully building a program gives insights into the mistakes other similar programs might make.

6. Related work

BIBIFI bears similarity to existing programming and security contests but is unique in its focus on building secure systems. BIBIFI also is related to studies of code and secure development, but differs in its open-ended contest format.

Contests

Cybersecurity contests typically focus on vulnerability discovery and exploitation, and sometimes involve a system administration component for defense. One popular style of contest is dubbed capture the flag (CTF) and is exemplified by a contest held at DEFCON (Inc, [n. d.]). Here, teams run an identical system that has buggy components. The goal is to find and exploit the bugs in other competitors’ systems while mitigating the bugs in your own. Compromising a system enables a team to acquire the system’s key and thus “capture the flag.” In addition to DEFCON CTF, there are other CTFs such as iCTF (Childers et al., 2010; Doupé et al., 2011; Trickel et al., 2017), S3 (Antonioli et al., 2017), KotH (Bock et al., 2018) and PicoCTF (Chapman et al., 2014). The use of this style of contest in an educational setting has been explored in prior work (Conti et al., 2011; Eagle, 2013; Hoffman et al., 2005). The Collegiate Cyber Defense Challenge (National Collegiate Cyber Defense Competition, [n. d.]; Conklin, 2006, 2005) and the Maryland Cyber Challenge & Competition (mdc3, [n. d.]) have contestants defend a system, so their responsibilities end at the identification and mitigation of vulnerabilities. These contests focus on bugs in systems as a key factor of play, but neglect software development.

Since BIBIFI’s inception, additional contests have been developed in its style. Make it and Break it (Yamin et al., 2018) is an evaluation of the Build-it, Break-it, Fix-it type of contest. Two teams were tasked with building a secure internet of things (IoT) smart home with functionality including remote control of locks, speakers, and lighting. Teams then broke each other’s implementations and found vulnerabilities like SQL injection and unauthorized control of locks. The contest organizers found this style of contest was beneficial in the development of cybersecurity skills and plan to run additional contests in the future. Git-based CTF (Wi et al., 2018) is similar to BIBIFI in that students were asked to implement a program according to a given specification. It differs in the fact that the CTF was fully run on Github and contestants used issue-tracking to submit breaks. In addition, builders were encouraged to fix breaks as soon as breaks were submitted since they periodically lost points for unfixed breaks. This seems to have been an effective motivation for convincing builders to fix their mistakes, and it may be a solution to improve BIBIFI’s fix-it participation.

Programming contests challenge students to build clever, efficient software, usually with constraints and while under (extreme) time pressure. The ACM programming contest (acm, [n. d.]) asks teams to write several programs in C/C++ or Java during a 5-hour time period. Google Code Jam (google, [n. d.]) sets tasks that must be solved in minutes, which are then graded according to development speed (and implicitly, correctness). Topcoder (topcoder, [n. d.]) runs several contests; the Algorithm competitions are small projects that take a few hours to a week, whereas Design and Development competitions are for larger projects that must meet a broader specification. Code is judged for correctness (by passing tests), performance, and sometimes subjectively in terms of code quality or practicality of design. All of these resemble the build-it phase of BIBIFI but typically consider smaller tasks; they do not consider the security of the produced code.

Secure Development Practices and Advice

There is a growing literature of recommended practices for secure development. The BSIMM (“building security in” maturity model) (bsimm, [n. d.]) collects information from companies and places it within a taxonomy. Microsoft’s Security Development Lifecycle (SDL) (Howard and Lipner, 2006) describes possible strategies for incorporating security concerns into the development process. Several authors make recommendations about development lifecycle and coding practices (McGraw, 2006; Viega and McGraw, 2001; Howard and LeBlanc, 2003; Seacord, 2013; Chess and West, 2007; Black et al., 2016). Acar et al. collect and categorize 19 such resources (Acar et al., 2017c).

Studies of secure software development

Researchers have considered how to include security in the development process. Work by Finifter and Wagner (Finifter and Wagner, 2011) and Prechelt (Prechelt, 2011) relates to both our build-it and break-it phases: they asked different teams to develop the same web application using different frameworks, and then subjected each implementation to automated (black box) testing and manual review. They found that both forms of review were effective in different ways, and that framework support for mitigating certain vulnerabilities improved overall security. Other studies focused on the effectiveness of vulnerability discovery techniques, e.g., as might be used during our break-it phase. Edmundson et al. (Edmundson et al., 2013) considered manual code review; Scandariato et al. (Scandariato et al., 2013) compared different vulnerability detection tools; other studies looked at software properties that might co-occur with security problems (Walden et al., 2014; Yang et al., 2016; Harrison and White, 2010). BIBIFI differs from all of these in its open-ended, contest format: Participants can employ any technique they like, and with a large enough population and/or measurable impact, the effectiveness of a given technique will be evident in final outcomes.

Other researchers have examined what factors influence the development of security errors. Common findings include developers who do not understand the threat model, security APIs with confusing options and poorly chosen defaults, and “temporary” test configurations that were not corrected prior to deployment (Fahl et al., 2013; Georgiev et al., 2012; Egele et al., 2013). Interview studies with developers suggest that security is often perceived as someone else’s responsibility, not useful for career advancement, and not part of the “standard” developer mindset (Xie et al., 2011; Oliveira et al., 2014). Anecdotal recommendations resulting from these interviews include mandating and rewarding secure coding practices, ensuring that secure tools and APIs are more attractive than less secure ones, enable “security champions” with broadly defined roles, and favoring ongoing dialogue over checklists (Wurster and van Oorschot, 2008; Weir et al., 2017; Becker et al., 2017). Developer Observatory (Stransky et al., 2017; Acar et al., 2017a, b) is an online platform that enables large-scale controlled security experiments by asking software developers to complete a security relevant programming tasks in the browser. Using this platform, Acar et al. studied how developer experience and API design for cryptographic libraries impact software security. Oliveira et al. (Oliveira et al., 2018) performed an experiment on security blindspots, which they define as a misconception, misunderstanding, or oversight by the developer in the use of an API. Their results indicate that API blindspots reduce a developer’s ability to identity security concerns, I/O functionality is likely to cause blindspots, and experience does not influence a developer’s ability to identify blindspots. Thompson (Thompson and Wagner, 2017) analyzed thousands of open source repositories and found that code review of pull requests reduced the number of reported security bugs.

Crash de-duplication

For accurate scoring, BIBIFI identifies duplicate bug reports by unifying the ones addressed by the same (atomic) fix. But this approach is manual, and relies on imperfect incentives. Other works have attempted to automatically de-duplicate bug reports, notably those involving crashes. Stack hashing (Molnar et al., 2009) and AFL (AFL, 2018) coverage profiles offer potential solutions, however Klees et al. (Klees et al., 2018) show that fuzzers are poor at identifying which underlying bugs cause crashing inputs. Semantic crash bucketing (van Tonder et al., 2018) and symbolic analysis (Pham et al., 2017) show better results at mapping crashing inputs to unique bugs by taking into account semantic information of the program. The former supports BIBIFI’s view that program fixes correspond to unique bugs.

7. Conclusions

This paper has presented Build-it, Break-it, Fix-it (BIBIFI), a new security contest that brings together features from typical security contests, which focus on vulnerability detection and mitigation but not secure development, and programming contests, which focus on development but not security. During the first phase of the contest, teams construct software they intend to be correct, efficient, and secure. During the second phase, break-it teams report security vulnerabilities and other defects in submitted software. In the final, fix-it, phase, builders fix reported bugs and thereby identify redundant defect reports. Final scores, following an incentives-conscious scoring system, reward the best builders and breakers.

During 2015 and 2016, we ran three contests involving a total of 156 teams and three different programming problems. Quantitative analysis from these contests found that the best performing build-it submissions used C/C++, but submissions coded in a statically-typed language were less likely to have a security flaw. Break-it teams that were also successful build-it teams were significantly better at finding security bugs. Break-it teams with more members were more successful at breaking since auditing code is a task that is easily subdivided.

We have freely released BIBIFI at https://github.com/plum-umd/bibifi-code to support future research. We believe it can act as an incubator for ideas to improve secure development. More information, data, and opportunities to participate are available at https://builditbreakit.org.

Acknowledgments

We thank Jandelyn Plane and Atif Memon who contributed to the initial development of BIBIFI and its preliminary data analysis. Many people in the security community, too numerous to list, contributed ideas and thoughts about BIBIFI during its development—thank you! Bobby Bhattacharjee and the anonymous reviewers provided helpful comments on drafts of this paper. This project was supported with gifts from Accenture, AT&T, Booz Allen Hamilton, Galois, Leidos, Patriot Technologies, NCC Group, Trail of Bits, Synposis, ASTech Consulting, Cigital, SuprTek, Cyberpoint, and Lockheed Martin; by a 2016 Google Faculty Research Award; by grants from the NSF under awards EDU-1319147 and CNS-1801545; by DARPA under contract FA8750-15-2-0104; and by the U.S. Department of Commerce, National Institute for Standards and Technology, under Cooperative Agreement 70NANB15H330.

References

  • (1)
  • Abadi et al. (2009) Martín Abadi, Mihai Budiu, Úlfar Erlingsson, and Jay Ligatti. 2009. Control-flow integrity principles, implementations, and applications. ACM Transactions on Information and System Security (TISSEC) 13, 1 (2009), 4:1–4:40.
  • Acar et al. (2017a) Y. Acar, M. Backes, S. Fahl, S. Garfinkel, D. Kim, M. L. Mazurek, and C. Stransky. 2017a. Comparing the Usability of Cryptographic APIs. In 2017 IEEE Symposium on Security and Privacy (SP).
  • Acar et al. (2017b) Yasemin Acar, Christian Stransky, Dominik Wermke, Michelle L. Mazurek, and Sascha Fahl. 2017b. Security Developer Studies with GitHub Users: Exploring a Convenience Sample. In Thirteenth Symposium on Usable Privacy and Security (SOUPS 2017).
  • Acar et al. (2017c) Yasemin Acar, Christian Stransky, Dominik Wermke, Charles Weir, Michelle L. Mazurek, and Sascha Fahl. 2017c. Developers Need Support Too: A Survey of Security Advice for Software Developers. In IEEE Secure Development Conference (SecDev 2017).
  • acm ([n. d.]) acm [n. d.]. The ACM-ICPC International Collegiate Programming Contest. http://icpc.baylor.edu. ([n. d.]).
  • AFL (2018) AFL 2018. American Fuzzing Lop (AFL). http://lcamtuf.coredump.cx/afl/. (2018).
  • Antonioli et al. (2017) Daniele Antonioli, Hamid Reza Ghaeini, Sridhar Adepu, Martin Ochoa, and Nils Ole Tippenhauer. 2017. Gamifying ICS Security Training and Research: Design, Implementation, and Results of S3. In Proceedings of the 2017 Workshop on Cyber-Physical Systems Security and PrivaCy (CPS ’17).
  • Becker et al. (2017) Ingolf Becker, Simon Parkin, and M. Angela Sasse. 2017. Finding Security Champions in Blends of Security Culture. In 2nd European Workshop on Usable Security (Euro USEC 2017). Internet Society.
  • Bernstein et al. (2012) Daniel J Bernstein, Tanja Lange, and Peter Schwabe. 2012. The security impact of a new cryptographic library. In International Conference on Cryptology and Information Security in Latin America. Springer, 159–176.
  • Black et al. (2016) Paul E. Black, Lee Badger, Barbara Guttman, and Elizabeth Fong. 2016. Dramatically Reducing Software Vulnerabilities: Report to the White House Office of Science and Technology Policy. Technical Report Draft NISTIR 8151. National Institute of Standards and Technology. http://csrc.nist.gov/publications/drafts/nistir-8151/nistir8151_draft.pdf.
  • Bock et al. (2018) Kevin Bock, George Hughey, and Dave Levin. 2018. King of the Hill: A Novel Cybersecurity Competition for Teaching Penetration Testing. In 2018 USENIX Workshop on Advances in Security Education (ASE 18).
  • bsimm ([n. d.]) bsimm [n. d.]. Building Security In Maturity Model (BSIMM). http://bsimm.com. ([n. d.]).
  • Burnham et al. (2011) Kenneth P Burnham, David R Anderson, and Kathryn P Huyvaert. 2011. AIC model selection and multimodel inference in behavioral ecology: some background, observations, and comparisons. Behavioral Ecology and Sociobiology 65, 1 (2011), 23–35.
  • Chapman et al. (2014) Peter Chapman, Jonathan Burket, and David Brumley. 2014. PicoCTF: A game-based computer security competition for high school students. In 2014 USENIX Summit on Gaming, Games, and Gamification in Security Education (3GSE 14).
  • Chess and West (2007) Brian Chess and Jacob West. 2007. Secure Programming with Static Analysis. Addison-Wesley.
  • Childers et al. (2010) Nicholas Childers, Bryce Boe, Lorenzo Cavallaro, Ludovico Cavedon, Marco Cova, Manuel Egele, and Giovanni Vigna. 2010. Organizing Large Scale Hacking Competitions. In DIMVA.
  • Cohen (1988) Jacob Cohen. 1988. Statistical Power Analysis for the Behavioral Sciences. Lawrence Erlbaum Associates.
  • Conklin (2005) Art Conklin. 2005. The Use of a Collegiate Cyber Defense Competition in Information Security Education. In InfoSecCD.
  • Conklin (2006) Art Conklin. 2006.

    Cyber defense competitions and information security education: An active learning solution for a capstone course. In

    HICSS.
  • Conti et al. (2011) Gregory Conti, Thomas Babbitt, and John Nelson. 2011. Hacking competitions and their untapped potential for security education. Security & Privacy 9, 3 (2011), 56–59.
  • DEF CON Communications, Inc. ([n. d.]) DEF CON Communications, Inc. [n. d.]. Capture the Flag Archive. https://www.defcon.org/html/links/dc-ctf.html. ([n. d.]).
  • Doupé et al. (2011) Adam Doupé, Manuel Egele, Benjamin Caillat, Gianluca Stringhini, Gorkem Yakin, Ali Zand, Ludovico Cavedon, and Giovanni Vigna. 2011. Hit ’Em Where It Hurts: A Live Security Exercise on Cyber Situational Awareness. In ACSAC.
  • dragostech.com inc ([n. d.]) dragostech.com inc. [n. d.]. CanSecWest Applied Security Conference. http://cansecwest.com. ([n. d.]).
  • Eagle (2013) Chris Eagle. 2013. Computer security competitions: Expanding educational outcomes. Security & Privacy 11, 4 (2013), 69–71.
  • Edmundson et al. (2013) Anne Edmundson, Brian Holtkamp, Emanuel Rivera, Matthew Finifter, Adrian Mettler, and David Wagner. 2013. An Empirical Study on the Effectiveness of Security Code Review. In International Symposium on Engineering Secure Software and Systems (ESSoS).
  • Egele et al. (2013) Manuel Egele, David Brumley, Yanick Fratantonio, and Christopher Kruegel. 2013. An empirical study of cryptographic misuse in android applications. In the 2013 ACM SIGSAC conference. ACM Press, 73–84. https://www.cs.ucsb.edu/~chris/research/doc/ccs13_cryptolint.pdf
  • Fahl et al. (2013) Sascha Fahl, Marian Harbach, Henning Perl, Markus Koetter, and Matthew Smith. 2013. Rethinking SSL development in an appified world. In Proc. ACM CCS. http://dl.acm.org/citation.cfm?doid=2508859.2516655
  • Finifter and Wagner (2011) Matthew Finifter and David Wagner. 2011. Exploring the relationship betweenweb application development tools and security. In USENIX Conference on Web Application Development (WebApps).
  • Georgiev et al. (2012) Martin Georgiev, Subodh Iyengar, Suman Jana, Rishita Anubhai, Dan Boneh, and Vitaly Shmatikov. 2012. The most dangerous code in the world: validating SSL certificates in non-browser software. In CCS ’12: Proceedings of the 2012 ACM conference on Computer and communications security. ACM. https://doi.org/10.1145/2382196.2382204
  • git ([n. d.]) git [n. d.]. Git – distributed version control management system. http://git-scm.com. ([n. d.]).
  • google ([n. d.]) google [n. d.]. Google Code Jam. http://code.google.com/codejam. ([n. d.]).
  • Harrison and White (2010) Keith Harrison and Gregory White. 2010. An empirical study on the effectiveness of common security measures. In Hawaii International Conference on System Sciences (HICSS).
  • Hoffman et al. (2005) Lance J. Hoffman, Tim Rosenberg, and Ronald Dodge. 2005. Exploring a national cybersecurity exercise for universities. Security & Privacy 3, 5 (2005), 27–33.
  • Howard and LeBlanc (2003) Michael Howard and David LeBlanc. 2003. Writing Secure Code. Microsoft Press.
  • Howard and Lipner (2006) Michael Howard and Steve Lipner. 2006. The Security Development Lifecycle. Microsoft Press.
  • icfp ([n. d.]) icfp [n. d.]. ICFP Programming Contest. http://icfpcontest.org. ([n. d.]).
  • Inc ([n. d.]) DEF CON Communications Inc. [n. d.]. DEF CON Hacking Conference. http://www.defcon.org. ([n. d.]).
  • Kim (2014) Queena Kim. 2014. Want to learn cybersecurity? Head to Def Con. http://www.marketplace.org/2014/08/25/tech/want-learn-cybersecurity-head-def-con. (2014).
  • Klees et al. (2018) George Klees, Andrew Ruef, Benji Cooper, Shiyi Wei, and Michael Hicks. 2018. Evaluating Fuzz Testing. In Proceedings of the 2018 ACM SIGSAC Conference on Computer and Communications Security (CCS ’18).
  • McGraw (2006) Gary McGraw. 2006. Software Security: Building Security In. Addison-Wesley.
  • mdc3 ([n. d.]) mdc3 [n. d.]. Maryland Cyber Challenge & Competition. http://www.fbcinc.com/e/cybermdconference/competitorinfo.aspx. ([n. d.]).
  • Molnar et al. (2009) David Molnar, Xue Cong Li, and David A. Wagner. 2009. Dynamic Test Generation to Find Integer Bugs in x86 Binary Linux Programs. In USENIX Security Symposium.
  • Nagelkerke (1991) N J D Nagelkerke. 1991. A note on a general definition of the coefficient of determination. Biometrika 78, 3 (09 1991), 691–692.
  • National Collegiate Cyber Defense Competition ([n. d.]) National Collegiate Cyber Defense Competition. [n. d.]. http://www.nationalccdc.org. ([n. d.]).
  • Oliveira et al. (2014) Daniela Oliveira, Marissa Rosenthal, Nicole Morin, Kuo-Chuan Yeh, Justin Cappos, and Yanyan Zhuang. 2014. It’s the Psychology Stupid: How Heuristics Explain Software Vulnerabilities and How Priming Can Illuminate Developer’s Blind Spots. In ACSAC.
  • Oliveira et al. (2018) Daniela Seabra Oliveira, Tian Lin, Muhammad Sajidur Rahman, Rad Akefirad, Donovan Ellis, Eliany Perez, Rahul Bobhate, Lois A. DeLong, Justin Cappos, and Yuriy Brun. 2018. API Blindspots: Why Experienced Developers Write Vulnerable Code. In Fourteenth Symposium on Usable Privacy and Security (SOUPS 2018).
  • OWASP (2010) OWASP. 2010. Secure Coding Practices - Quick Reference Guide. (2010). https://www.owasp.org/images/0/08/OWASP_SCP_Quick_Reference_Guide_v2.pdf
  • Parker et al. (2019) James Parker, Niki Vazou, and Michael Hicks. 2019. LWeb: Information Flow Security for Multi-tier Web Applications. Proc. ACM Program. Lang. 3, POPL (Jan. 2019).
  • Pham et al. (2017) Van-Thuan Pham, Sakaar Khurana, Subhajit Roy, and Abhik Roychoudhury. 2017. Bucketing Failing Tests via Symbolic Analysis. In International Conference on Fundeamental Approaches to Software Engineering (FASE).
  • Polytechnic Institute of New York University ([n. d.]) Polytechnic Institute of New York University. [n. d.]. CSAW - CyberSecurity Competition 2012. http://www.poly.edu/csaw2012/csaw-CTF. ([n. d.]).
  • Prechelt (2011) L. Prechelt. 2011. Plat_Forms: A web development platform comparison by an exploratory experiment searching for emergent platform properties. IEEE Transactions on Software Engineering 37, 1 (2011), 95–108.
  • psql ([n. d.]) psql [n. d.]. PostgreSQL: The world’s most advanced open source database. http://www.postgresql.org. ([n. d.]).
  • Ruef et al. (2016) Andrew Ruef, Michael Hicks, James Parker, Dave Levin, Michelle L. Mazurek, and Piotr Mardziel. 2016. Build It, Break It, Fix It: Contesting Secure Development. In CCS.
  • Ruef et al. (2015) Andrew Ruef, Michael Hicks, James Parker, Dave Levin, Atif Memon, Jandelyn Plane, and Piotr Mardziel. 2015. Build It Break It: Measuring and Comparing Development Security. In CSET.
  • Saltzer and Schroeder (1975) Jerome H. Saltzer and Michael D. Schroeder. 1975. The Protection of Information in Computer Systems. Proc. IEEE 63, 9 (1975), 1278–1308.
  • Scandariato et al. (2013) Riccardo Scandariato, James Walden, and Wouter Joosen. 2013. Static analysis versus penetration testing: A controlled experiment. In IEEE International Symposium on Reliability Engineering (ISSRE).
  • Seacord (2013) Robert C. Seacord. 2013. Secure Coding in C and C++. Addison-Wesley.
  • Stefan et al. (2011) Deian Stefan, Alejandro Russo, John Mitchell, and David Mazieres. 2011. Flexible Dynamic Information Flow Control in Haskell. In ACM SIGPLAN Haskell Symposium.
  • Stransky et al. (2017) Christian Stransky, Yasemin Acar, Duc Cuong Nguyen, Dominik Wermke, Doowon Kim, Elissa M. Redmiles, Michael Backes, Simson Garfinkel, Michelle L. Mazurek, and Sascha Fahl. 2017. Lessons Learned from Using an Online Platform to Conduct Large-Scale, Online Controlled Security Experiments with Software Developers. In 10th USENIX Workshop on Cyber Security Experimentation and Test (CSET 17).
  • Technologies (2018) Positive Technologies. 2018. ATM logic attacks: scenarios, 2018. https://www.ptsecurity.com/upload/corporate/ww-en/analytics/ATM-Vulnerabilities-2018-eng.pdf. (Nov. 2018).
  • Thompson and Wagner (2017) Christopher Thompson and David Wagner. 2017. A Large-Scale Study of Modern Code Review and Security in Open Source Projects. In Proceedings of the 13th International Conference on Predictive Models and Data Analytics in Software Engineering (PROMISE).
  • topcoder ([n. d.]) topcoder [n. d.]. Top Coder competitions. http://apps.topcoder.com/wiki/display/tc/Algorithm+Overview. ([n. d.]).
  • Trickel et al. (2017) Erik Trickel, Francesco Disperati, Eric Gustafson, Faezeh Kalantari, Mike Mabey, Naveen Tiwari, Yeganeh Safaei, Adam Doupé, and Giovanni Vigna. 2017. Shell We Play A Game? CTF-as-a-service for Security Education. In 2017 USENIX Workshop on Advances in Security Education (ASE 17).
  • Úlfar Erlingsson (2012) Úlfar Erlingsson. 2012. personal communication stating that CFI was not deployed at Microsoft due to its overhead exceeding 10%. (2012).
  • van Tonder et al. (2018) Rijnard van Tonder, John Kotheimer, and Claire Le Goues. 2018. Semantic Crash Bucketing. In IEEE International Conference on Automated Software Engineering (ASE).
  • Viega and McGraw (2001) John Viega and Gary McGraw. 2001. Building Secure Software: How to Avoid Security Problems the Right Way. Addison-Wesley.
  • Walden et al. (2014) James Walden, Jeff Stuckman, and Riccardo Scandariato. 2014. Predicting Vulnerable Components: Software Metrics vs Text Mining. In IEEE International Symposium on Software Reliability Engineering.
  • Weir et al. (2017) Charles Weir, Awais Rashid, and James Noble. 2017. I’d Like to Have an Argument, Please: Using Dialectic for Effective App Security. In 2nd European Workshop on Usable Security (Euro USEC 2017). Internet Society.
  • Wi et al. (2018) SeongIl Wi, Jaeseung Choi, and Sang Kil Cha. 2018. Git-based CTF: A Simple and Effective Approach to Organizing In-Course Attack-and-Defense Security Competition. In 2018 USENIX Workshop on Advances in Security Education (ASE 18).
  • Wurster and van Oorschot (2008) Glenn Wurster and P C van Oorschot. 2008. The developer is the enemy. In NSPW. 89.
  • Xie et al. (2011) J Xie, H R Lipford, and B Chu. 2011. Why do programmers make security errors?. In 2011 IEEE Symposium on Visual Languages and Human-Centric Computing. http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=6070393
  • Yamin et al. (2018) Muhammad Mudassar Yamin, Basel Katt, Espen Torseth, Vasileios Gkioulos, and Stewart James Kowalski. 2018. Make It and Break It: An IoT Smart Home Testbed Case Study. In Proceedings of the 2Nd International Symposium on Computer Science and Intelligent Control (ISCSIC ’18).
  • Yang et al. (2016) Joonseok Yang, Duksan Ryu, and Jongmoon Baik. 2016. Improving vulnerability prediction accuracy with Secure Coding Standard violation measures. In International Conference on Big Data and Smart Computing (BigComp).
  • yesodweb ([n. d.]) yesodweb [n. d.]. Yesod Web Framework for Haskell. http://www.yesodweb.com. ([n. d.]).