Speculations on Teaching Secure Programming
I have taught secure programming for several years, and along the way I developed a world view of how teaching it is different from teaching other subject matters. Some of the following are inferences from uncontrolled observations, others are simply opinions or mere speculation. I expose this world view here, hoping that it will generate some discussions and that flaws in it will be corrected.
As other fields, software security can be studied from several different aspects, such as secure software engineering, secure coding at a technical level, architecture, procurement, configuration and deployment. Similarly to other fields, effective software security teaching depends on the audience—its needs, its current state and capabilities, and its potential for learning. Learning techniques such as repetition are useful, and students can ultimately benefit from organized, abstracted thought on the subject. However, teaching software security is different from teaching other subjects because it is not just teaching facts (data), “how to” (skills) and theories and models (knowledge), but also a mindset and the capability to repeatably derive and achieve a form of wisdom in various, even new situations. It’s not just a question of the technologies used or the degree of technological acumen, but of behavioral psychology, economy, motivation and humor.
Behavioral Psychology— Security is somewhat of a habit, an attitude, a way of thinking and life. You won’t become a secure programmer just because you learned of a new vulnerability, exploit or security trick today, although it may help and have a cumulative effect. Attacking requires opportunistic, lateral, experimental thinking with exciting rewards upon success. It somewhat resembles the capability to create humor by taking something out of the context for which it was created and subjecting it to new, unexpected conditions. I am also surprised sometimes by the amount of perseverance and dedication attackers demonstrate. Defending requires vigilance and a systematic, careful, most often tedious labor and thought, which are rewarded slowly by “uptime” or long-term peace. They are different, yet understanding one is a great advantage to the other. To excel at both simultaneously is difficult, requires practice and is probably not achievable by everyone. I note that undergraduate computer science rewards passing tests, including sometimes provided software tests for assignments, which are closer to immediate rewards upon success or immediate failure, with no long-term consequences or requirements. On top of that, assignments are most often evaluated solely on achieving functionality, and not on preventing unintended side-effects or not allowing other things to happen. I suspect that this produces graduates with learned behaviors unfavorable to security. The problem with behaviors is that you may know better than what you’re doing, but you do it anyways. Economy may provide some limited justification.
Economy—Many people know that doing things securely is “better”, and that they ought to, but it costs. People are “naturally optimizing” (lazy)—they won’t do something if there’s no perceived need for it, or if they can delay paying the costs or ultimately pay only the necessary ones (“late security” as in “late binding”). This is where patches stand; vulnerability disclosures and patches are remotely possible costs to be weighted against the perceived opportunity costs of delays and additional production expenses. Isolated occurrences of exploits and vulnerability disclosures may be dismissed as bad luck, accidents or something that happens to other projects. An intense scrutiny of some works may be necessary to demonstrate to a product’s team that their software engineering methods and security results are flawed. There is plenty of evidence that these attempts at evading costs don’t work well and often backfire.
Even if change is desired, students can graduate with negligible knowledge of the best practices presented in the SOAR on Software Security Assurance 2007. Computer science programs are strained by the large amount of knowledge that needs to be taught; perhaps software engineering should be spun off, just like electrical engineering was spun off from physics. Companies that need software engineers, and ultimately our economy, would be better served by that than by getting students that were just told to “go and create a program that does this and that”. While I was revising these thoughts, “Crosstalk” published some opinions on the use of Java for teaching computer science, but the title laments “where are the software engineers of tomorrow?” I think that there is just not enough teaching time to educate people to become both good computer scientists and software engineers, and the result is something that satisfies the need for neither. Even if new departments aren’t created, two different degrees should probably be offered.
Motivation—For many, trying to teach software security will be in one ear, out the other unless consequences are demonstrated. Most people need to be shown the exploits that a flaw enables, to believe that it is a serious flaw. This resembles how a kid may ignore warnings about burns and hot things until a burn is experienced. Even as teenagers and adults, every summer some people have to re-learn how sunscreen is needed, and the possibility of skin cancer is too remote a consideration for others. So, security teaching needs to contain a lot of anecdotes and examples of bad things that happened. I like to show real code in class and analyze the mistakes that were made; that approach seems to get the interest of undergraduates. At a later stage, this will evolve from “security prevents bad things” to “with security you can do this safely”. Actualizing secure programming can make it even more interesting and exciting, by discussing current events in class.
Repetition—Repeated experiences reinforce learning. Security-focused code scanners repeat and reinforce good coding practice, as long as the warnings are not allowed to be ignored. Code audits reinforce the message, this time coming from peers, and so result in peer pressure and the risk of shame. They are great in a company, but I am ambivalent about using code audits by other students, due to the risk of humiliation—humiliation is not appropriate while learning, for many reasons. Also, the students doing the audit may not be competent yet, by definition, and I’m not sure how I would grade the activity. Code audits by the teacher do not scale well. This leaves scanners. I have been looking into it and I tried some commercial code scanners, but what I’ve seen are systems that are unmanageable for classroom use and don’t catch some of the flaws I wish they would.
Organization and abstraction—Whereas showing exploits and attacks is good for the beginner, more advanced students will want to move away from black lists of things not to do (e.g., “Deadly Sins”) to good practices, assurance, and formal methods. I made a presentation on the subject almost two years ago.
In conclusion, teaching secure programming differs from typical subject matters because of how the knowledge is utilized; it needs to change behaviors and attitudes; and it benefits from different tools and activities. It is interesting in how it connects with morality. Whereas these characteristics aren’t unique in the entire body of human knowledge, they present interesting challenges.