Noncombatant đ About đ€ Other Writing đ§ Bandcamp đ” GitHub đ» Mastodon đ Bluesky đŠ
Iâve been talking with various people lately about how to get started in software security engineering. I noticed Iâve been having similar conversations with both newbies and experienced engineers, and I figured I should write things down in 1 place rather than keep repeating myself! I hope someone will find this useful.
Know your reasons for wanting to specialize in security. Here are some examples; youâll probably have more of your own:
You might want to rank your reasons, so that when youâre faced with career choices you know what path to follow. For example, you might have a job you like because itâs intellectually challenging, but someone comes along and offers you more money to do less-interesting work. Youâll have to decide which is more important to you. I find it comforting to have ranked my reasons and goals ahead of time, because for me it makes the choices much less stressful. And you will most certainly need a moral compass as you progress through this adventure.
You can, and should, get started right away! Yes, there is a lot to learn, but you can do it, and you can start being effective immediately. I know this from first-hand experience, and from seeing other people do it. You might feel daunted by the size of the problem â everyone is, whether they admit it or not. The only way anyone has ever made progress is bit by bit, and you can too.
There are more security problems right now than there are problem solvers. We need you!
Security is a specialization within the overall field of software engineering. In that sense, it is no different than any other specialization like networking, databases, performance, games, or whatever else. And software engineering is much more than just reading and writing code â it also includes design, technical and non-technical writing and communication, interpersonal and political skills, at least some understanding of business and economics, and more. Security engineers need those skills, too. Code is definitely important but it is not the whole story.
You can learn the general partly by focusing on the specific â and you can learn the specific by learning the general. That is, you can learn engineering by diving right into security specifically, and you can also learn about security by learning engineering generally. (After all, security is really just another form of engineering quality.)
I find itâs best to try to view things from both perspectives. In my experience, it has been productive to focus on security specifically for a while, then focus on application development for a while, and then iterate.
Within the field of software security engineering, there are sub-specializations. My main area is application security engineering: figuring out what kinds of assets and attacks on those assets are relevant in a particular applicationâs domain, and then trying to design and implement the application to best defend its assets. But there are other sub-specializations in security, such as digital forensics and incident response (DFIR), network security, anti-fraud (a close relative of actuarial science and statistics), anti-abuse/pro-social design, and more.
The most important thing about a good security engineer is their mindset: skeptical. A regular engineer is trying to build something that works; a security engineer is anxious until theyâve found a few new ways in which it doesnât work.
Much of computing science and software engineering is about managing complexity by creating abstractions. For example, consider this Python code:
f = open("something.txt", "r")
Python gives us this simple way to say, âGive me an object that represents a
persistent data store, and let me read that data.â But that straightforward code
hides tons and tons of complexity. For example, we have no idea (without reading
the Python interpreter and standard library source code) exactly how that object
f
works (nor what it costs). It could be a thin wrapper around the
C libraryâs FILE
type, which itself is a rather thick (and useful)
wrapper around the operating systemâs file descriptor or
handle concept. In turn, file descriptors are abstract representations
of a wide variety of hardware and software systems:
The pathname of the file, in this case something.txt
,
is also a very high-level abstraction. Different platforms implement different
pathname interpretation semantics, but most do a lot of work to hide complexity.
For example, on Unix-like platforms, pathnames can refer to a variety of kinds
of things:
/dev/disk1
)/dev/pty0
)/dev/bpf3
,
/dev/urandom
)/mnt/nfs/your-companys-file-server/accounting/FY2016Q3
Report.xls
)Windows systems have even stranger pathname semantics. PHP will also interpret pathnames as URLs and will perform certain transformations of the data based on the URL scheme!
They have to be â thatâs their value! The purpose of an abstraction is to hide complexity, and thereby help you get work done faster. An abstraction that does not hide something from its caller is not an abstraction at all.
But a security engineer is always skeptical, because they know that in the gap between what the abstraction seems to provide and what it actually provides, there are exploitable vulnerabilities.
Neal Stephenson called this metaphor shear (like windshear) in his hilarious essay In The Beginning Was The Command Line.
In general, itâs good engineering practice to understand the layer below where youâre working, and understand the layer above. Another way to say this is, know your callees, and know your callers. The difference between an engineer and a security engineer is that the security engineer is looking for the tension and friction in those edges.
For the rest of this post, Iâll talk about what skills I have found useful in application security. But there are other areas, and other paths into them â this is just one personâs perspective!
Certain skills will be of use throughout your career and will help you build a foundation from which you can learn anything else you need to learn.
After some years building your foundations, there are more things to learn and more adventures to enjoy. Here are some:
To thoroughly learn a programming language, I find it useful to read 1 very well written book that covers the languageâs syntax, semantics, standard library, and usage conventions. I like to read the book cover to cover, and then re-read all or part of it periodically. Preferably, 1 or more of the languageâs inventors or implementors should have written the book. The canonical example is The C Programming Language by Kernighan and Ritchie, and other books have continued and improved on the tradition: The Go Programming Language by Donovan and Kernighan; JavaScript: The Definitive Guide by Flanagan; The Java Programming Language by Arnold, Gosling, and Holmes; and Effective C++ by Meyers. People on Twitter say that The Hitchhikerâs Guide To Python by Reitz is a good Python book.
Saltzer and Schroederâs The Protection Of Information In Computer Systems is a foundational text.
For web security, I recommend The Tangled Web by Michal Zalewski. Zalewski also has another excellent book, Silence On The Wire, about techniques for passive surveillance in a variety of domains. Zalewski is also the author of American Fuzzy Lop, an excellent fuzzer.
Cryptography Engineering by Ferguson, Schneier, and Kohno is a good introduction to applied cryptography.
TCP/IP Illustrated, at least volume 1, is crucial.
For understanding C and doing reverse engineering, youâll want a good assembly language book, such as Art Of Assembly Language by Hyde.
Ross Andersonâs excellent omnibus, Security Engineering, is available online and on paper. Another great book is The Art Of Software Security Assessment by Dowd, McDonald, and Schuh.
There are many also good blogs and magazines. A random sampling might include the Project Zero blog, PoC||GTFO, Joanna Rutkowskaâs blog, and Matthew Greenâs blog.