NSA Says Its Secure Dev Methods Are Publicly Known
Trailrunner7 writes "Despite its reputation for secrecy and technical expertise, the National Security Agency doesn't have a set of secret coding practices or testing methods that magically make their applications and systems bulletproof. In fact, one of the agency's top technical experts said that virtually all of the methods the NSA uses for development and information assurance are publicly known. 'Most of what we do in terms of app development and assurance is in the open literature now. Those things are known publicly now,' Neil Ziring, technical director of the NSA's Information Assurance Directorate, said in his keynote at the OWASP AppSec conference in Washington Wednesday. 'It used to be that we had some methods and practices that weren't well-known, but over time that's changed as industry has focused more on application security.'"
...it is definitely possible to write secure software if you just simply follow sound and smart development methods and practices... and don't write half-assed, slipshod, thrown-together-in-a-hurry code.
If the NSA has something that really is Schneier-proof, they wouldn't tell the public. And understandably so, since part of their job is in part to ensure signal security for US agencies that deal in classified information.
I am officially gone from
It's that word most in "Most of what we do..." that may be important here. Most doesn't mean all. Also note he did not mention their cryptographic techniques, which is where I would expect them to be especially advanced.
Security, especially in software development, doesn't suffer from the "we don't know how to do it" problem. It suffers from the "we don't have time/budget/patience/interest in doing what we know we should be doing" issue.
Assorted stuff I do sometimes: Lemuria.org
That's a closed source/open source distinction. It has nothing to do with development methodology... except that there are more eyes when it's open.
Depending on whose eyes for closed source, I'm pretty sure the NSA has plenty of great eyes looking over code.
More Twoson than Cupertino
security doesn't come from obscurity
Exactly right.
The best security is the kind where everyone knows how it works, but even given the source code, you can't beat it, or you can't beat it in any useful length of time.
That being said, the automated code inspection packages you can buy these days look only for the obvious noobie programmer mistakes.
SELinux, originally from NSA, solves many of the problems of running untrusted code on your box, but even that is not 100% secure, and the maintenance problems it introduces mean that it is seldom used in real life.
The problem is not how this agency (the NSA) cleans up their code.
The problem is that we don't know about what backdoors exist in our hardware and our operating systems. Because so much code is embedded in silicon, and so few people actually look at that code, its easy to imagine all sorts of pownage living there.
A compromised Ethernet card (just sayin by way of example), would be both Obscure, and hard to detect, and have access to just about everything going in and out of your machine.
Security does not come from obscurity, but insecurity often does.
Sig Battery depleted. Reverting to safe mode.
I suspect it's more along the lines of people expecting there to be something significant that they have for writing secure code. I'm willing to bet that the only thing they have that most other organizations don't have is a substantial budget for auditing the code for vulnerabilities. They probably wait longer before deploying code as well until it's been thoroughly vetted.
The Soviets almost never used to crack codes. They just social-engineered (blackmail, sex, gifts, schmoozed, etc) to get all the information they wanted.
It's how Mitnick did most of his work as well.
Because the card has smarts, and the cable does not.
Because the card lives on your bus, and the cable does not.
But try not to belabor the point, as I said, it was just an example. Substitute any other device resident in your computer which you feel better demonstrates the point.
Sig Battery depleted. Reverting to safe mode.
If we start with the fact that the NSA is responsible for the Rainbow Series, partly responsible for Common Criteria, totally responsible for the NSA guidebook on securing Linux, and also totally responsible for the concepts in SELinux (remember, they talk about methods not code), it follows that the NSA is implying that the processes used to develop this public information are rigorous, sound and the methods the NSA use internally for projects they don't talk about. It actually doesn't say that what the NSA publishes is what they use - they only say that methods that are public are what they use. The source is implied.
It's a small world and it smells funny; I'd buy another if it wasn't for the money; Take back what I paid (SoM)
Writing bulletproof code isn't really all that hard, but it does take discipline. Discipline to use only those constucts which have been verified with both the compiler and linker.
Some simple things that coders can do:
- avoid the use of pointers.
- Initialize all variables to known values.
- Perform comparisons with the LHS using a static variable, so you don't accidentally get an assignment instead of a comparison
- When you are done with a value, reset it to a "known" value. Zero is usually good.
- Keep functions less than 1 page long. If you can't see the entire function on a single editor page, it is too long.
Simple.
BTW, I wrote code for real-time space vehicle flight control systems. When I look at OSS and see variables not set to initial values, I cringe. Sure, it is probably ok, but there isn't any cost to initializing the variables. This is a compile-time decision. Without knowing it, many programmers are counting on memory being zero'ed as the program gets loaded. Not all OSes do this, so if you are writing cross platform code, don't trust it will happen. Do it yourself.
Oh, and if you want secure programs, loosely typed languages are scary.
Not starting from a clean slate is immaterial. A new component can be 100% self-contained (and therefore verifiably clean within itself), communicating via some intermediary layer that handles legacy APIs, network connections, pipes, shared memory, et al.
The new component can therefore be as provably secure as you want. Security holes will then be contained (they must be in pre-existing code and cannot spread into new code).
This is not often done in the business world because they're stupid and prefer to burn huge amounts covering their backsides when inevitable breakins occur rather than the relatively small extra needed to properly secure systems in the first place. (It's stupid because such a method can never be cost-efficient in the long-run and only looks very marginally better on the books in the short-term.)
It's a small world and it smells funny; I'd buy another if it wasn't for the money; Take back what I paid (SoM)
Initialize all variables to known values
And remember to reset them to known values as soon as they are no longer necessary. Not only is it good practice, whether or not the compiler has a job, but it encourages the programmer to keep his variables in mind.
the NPG electrode was replaced with carbon blac
Actually, programming is one of the few disciplines where practice can be exactly the same as the theory - the bits and bytes are all the same, they don't break from material fatigue; and if you write software for which you have a proof of correctness, it will simply work correctly. Few other branches of human endeavor are free from the evils of the material world to such a degree.
Ezekiel 23:20
Because the card lives on your bus, and the cable does not.
More specifically most devices on the bus can do DMA to host memory, that enables them to read and write any byte of memory, completely bypassing OS memory protection.
In fact, firewire ports are a favorite of the digital forensics guys for exactly this reason - they can come along, plug their dohickey into the firewire port of most any PC that has one and do a complete memory dump of the system without the OS or any other program even noticing.
When information is power, privacy is freedom.
In a corporation, you not only have accounting, HR, managers, VPs and such looking over your budget but you also have investors. If it costs you too much to produce something of "equal" quality to a competitor, they will start asking questions. A problem with insecure code probably won't cost the company the entire business.
The NSA, I think, mostly has a black budget. There's only a few people who know how much, where and to whom (employees) this money goes to. So there's not really a budget you have to account for. A problem (leak) because of bad code or anything else could be damaging to National Security. It will also, likely, become a political embarrassment and one to the DoD, NSA/CIA establishments. The people who approve the budgets will almost undoubtedly approve expenses to account for increases in security in any area incl. programming.
Writing bulletproof code isn't really all that hard, but it does take discipline. Discipline to use only those constucts which have been verified with both the compiler and linker.
Some simple things that coders can do: - avoid the use of pointers.
Pointers aren't themselves bad; they just add some layers of complication to the otherwise stack-oriented game. The only reason the stack is nicer than pointers is because they're implicitly managed for you.
Rather than avoid pointers, what you need is good code structure. Design functions that either manage the lifecycle of a pointer or are explicitly clear about how and what the pointer is going to be used as. Use const aggressively, and avoid typecasting as much as possible. Using good pointer naming techniques and management functions also dissipate the burden. Pointers are too useful to avoid religiously ... rather, build pointer security and management techniques into your coding style from the ground up. Choose descriptive names and try and constrain each pointer to its specific type (this lets the compiler help you keep your pointers straight).
Initialize all variables to known values.
Meh, I'm divided on this one. It's one thing to explicitly initialize global variables to either zero (which costs nothing, since they just end up in BSS sections) or non-zero (which puts them statically in the data segment). Stack variables, on the other hand, only really need to be initialized before they're used the first time. Pre-initializing them could lead to wasted instructions initializing them multiple times or cause them to be initialized in all code paths when they're only used in a few. My general rule of thumb is to be smart about it and, once again, naming conventions.
Perform comparisons with the LHS using a static variable, so you don't accidentally get an assignment instead of a comparison
Great tip; it's weird at first writing "if( NULL != p )", and you get a few funny stares, but after seeing enough "if( i = 10 )"s lying within seemingly-functional code, it's an easy selling point to make.
- When you are done with a value, reset it to a "known" value. Zero is usually good.
Definitely do this with pointers, descriptors, and other handle types. It also makes cleanup and pointer management easier. Less important to do with things like iterators and intermediate variables.
- Keep functions less than 1 page long. If you can't see the entire function on a single editor page, it is too long.
It's a good rule of thumb. I would like to add "any time you can't do this, make absolutely certain that you're not doing it for a good reason."
Good tips, though. One thing I'd like to add: -Wall -Wextra -Werror (or your language's equivalent). If your code can't compile without a single warning, then you need to re-write your code and either manually disarm situations (e.g., override the compiler's common-sense with an assurance that you know what you're doing) or fix the warnings, which are actually bugs and errors. It's always fun to take someone's "bulletproof" code and turn on these flags and watch the crap spill out. Warnings are amazing, and they are absolutely your friend when it comes to writing bug-free and secure code.
Security does not come from obscurity, but insecurity often does.
Security comes in many forms, and obscurity is actually quite a good form, as long as there are other layers.
The "best" security comes from defense in depth and obscurity can certainly be part of that, and in fact probably should be. I will go through a few different layers where security by obscurity actually works quite well.
Consider a random binary on Usenet. Even if I 'encrypt' the payload with ROT-13 I have achieved a decent amount of security simply through obscuring the target in a sea of ones and zeros.
Now, consider the challenge-response system. It used to be that some systems would tell you whether your username, password (or both) was bad. It turns out that this lack of obscurity allows attackers quicker access to systems, since they can hit upon usernames by letting the system tell them which were valid. Simply obscuring the error response fixes this.
And this brings up a good point about obscurity as a security practice. If you use it - don't tell anyone! You would have thought this was a "duh", but the previous example is a great one in that regards. Usernames are simply obscured data, but if the login system can be used as an oracle ... not so much.
Now, on a systems level, network security is often predicated on obscurity - that's why you don't find many companies publishing their internal network maps! If those maps were published, then attackers would have a much easier time to penetrate the organization. Security by obscurity.
Now, on a home level, if I am using port knocking (as one example) as one means of controlling access to ssh, then every attacker that does not know this will fail out of the box. Of course, it is better if I also have key exchange turned on, and even moreso if that and password enabled. But, even moreso if I simply run it on a non-standard port - which is security thorugh obscurity.
So, while I wouldn't rely strictly on security through obscurity (except in cases it makes sense), it is a valuable tool in a security toolbox, and generally can be a show stopper for an attacker if they aren't able to obtain the knowledge. But again, security comes from defense in depth, and one layer of that depth should be considered obscurity.
Regards.
Without knowing it, many programmers are counting on memory being zero'ed as the program gets loaded
Any compliant C compiler will initialise all statics to 0 (stack values are different - they are not automatically initialised). From the C99 spec, 5.1.2:
All objects with static storage duration shall be initialized (set to their initial values) before program startup.
From 6.7.8.10:
If an object that has static storage duration is not initialized explicitly, then:
You can guarantee that any standards-compliant C implementation will do this. You can't guarantee anything about an implementation that doesn't comply with the standard - it may deviate from it in other ways.
I am TheRaven on Soylent News
Stack variables, on the other hand, only really need to be initialized before they're used the first time. Pre-initializing them could lead to wasted instructions initializing them multiple times or cause them to be initialized in all code paths when they're only used in a few.
Unless your compiler really sucks, it will perform some trivial dataflow analysis and not generate code for the initialisation if the value is never used. Even really simply C compilers do this. If the value is used uninitialised on any code paths, then the initialisation will be used (although it may be moved to those code paths), and you don't want the compiler to remove it.
From the flags you recommend, I'm guessing that you use gcc, which not only does this analysis it will even tell you if the value is used uninitialised.
I am TheRaven on Soylent News