Beta
×

Welcome to the Slashdot Beta site -- learn more here. Use the link in the footer or click here to return to the Classic version of Slashdot.

Thank you!

Before you choose to head back to the Classic look of the site, we'd appreciate it if you share your thoughts on the Beta; your feedback is what drives our ongoing development.

Beta is different and we value you taking the time to try it out. Please take a look at the changes we've made in Beta and  learn more about it. Thanks for reading, and for making the site better!

How Do You Know Your Code is Secure?

Zonk posted more than 7 years ago | from the batten-down-the-hatches-mates dept.

349

bvc writes "Marucs Ranum notes that 'It's really hard to tell the difference between a program that works and one that just appears to work.' He explains that he just recently found a buffer overflow in Firewall Toolkit (FWTK), code that he wrote back in 1994. How do you go about making sure your code is secure? Especially if you have to write in a language like C or C++?"

cancel ×

349 comments

Sorry! There are no comments related to the filter you selected.

TAHT first post? (-1, Troll)

Anonymous Coward | more than 7 years ago | (#17506096)

TAHT first post?

Frist psot (0, Redundant)

impeachgod (982062) | more than 7 years ago | (#17506102)

Bill Goatse annouces incorporation of Negrosoft Inc.

1st post (-1, Redundant)

Anonymous Coward | more than 7 years ago | (#17506106)

1st post ?

You don't (5, Funny)

CockMonster (886033) | more than 7 years ago | (#17506118)

Just get others to formally review it so if anything is found, there's collective responsibilty

Re:You don't (2, Funny)

Anonymous Coward | more than 7 years ago | (#17506602)

Prophylactic: [medterms.com] A preventive measure. The word comes from the Greek for "an advance guard," an apt term for a measure taken to fend off a disease or another unwanted consequence.


Sorry CockMonster, with today's DNA testing, getting others to participate in your virgin sacrifice wouldn't save you if you had a buffer overflow.

*Warning* as appropriate as prophylactic might seem under its definition for use in the computer industry when talking about firewalls, sandboxes, etc, please keep in mind that some female is probably going to holler sexual harassment when they hear it. Just as they would if you mentioned their stack overflow.

TAHT (1)

edittard (805475) | more than 7 years ago | (#17506120)

Tihs Zokn guy, has he toltatty lots the polt or waht?

Verified (5, Funny)

Anonymous Coward | more than 7 years ago | (#17506122)

I get mine verified by microsoft

Secure? (2, Insightful)

nahime (1048362) | more than 7 years ago | (#17506124)

Secure?? What does it mean?

Re:Secure? (0)

Anonymous Coward | more than 7 years ago | (#17506182)

Hey pardner... I reckon you need someone to sec ure dick?

Code schmode (-1, Offtopic)

Anonymous Coward | more than 7 years ago | (#17506132)

Zonk and other slashdot editors can't even check taht the spelling in article submissions is correct. What chance would a mere mortal have of checking taht his code was bug-free?

Shovel method (4, Funny)

dangitman (862676) | more than 7 years ago | (#17506140)

I hit it with a shovel. If the code doesn't fall apart, I know it's pretty securely attached to my computer. If not, I add more epoxy glue.

Don't use C++ as if it was only "C with classes" (4, Insightful)

quigonn (80360) | more than 7 years ago | (#17506146)

Modern C++ provides a very nice and functional Standard Library which provides a lot of functionality and data structures such as strings, vectors, lists, maps, sets. While using these available classes does not completely rule out making programming mistakes related to buffer overflows and such, it at least minimizes the risk of producing stupid buffer overflow through badly done string handling. At least that's what my experience is.

Actually, the best thing would be not to use C or C++ at all, but that's where reality comes into play. Most developers don't even have the choice which language they should use, but that is predetermined by the employer and/or supervisor.

Re:Don't use C++ as if it was only "C with classes (2, Insightful)

Viol8 (599362) | more than 7 years ago | (#17506288)

The mostly STL gets rid of the old problems such as buffer overflows but introduces new ones that can a lot more subtle and harder to track down such as deep/shallow copy issues. Personally (and I'm probably in the minority) I prefer to deal with the old fashioned bugs since you can usually guess where they're happening whereas in a highly abstracted C++ program using the STL with lots of objects being copied and references flying around it can be a LOT harder to figure out whats really going on , especially since different compilers do different things under the hood.

Re:Don't use C++ as if it was only "C with classes (3, Insightful)

Diablo1399 (859422) | more than 7 years ago | (#17506362)

You would sacrifice the flexibility and usefulness of the STL to get a class of bugs that are old and well-known? Hardly seems like a fair trade-off to me.

Re:Don't use C++ as if it was only "C with classes (2, Insightful)

Viol8 (599362) | more than 7 years ago | (#17506460)

Not necessarily , all I'm saying is that the STL can introduce bugs of its own that can be a lot harder to find than old style buffer overruns so its not a solution that will get rid of obscure coding (as opposed to logic) bugs.

Re:Don't use C++ as if it was only "C with classes (1)

Delirium Tremens (214596) | more than 7 years ago | (#17506446)

Developers can chose their employer.

Re:Don't use C++ as if it was only "C with classes (1)

quigonn (80360) | more than 7 years ago | (#17506522)

But the number of employers where you actually get a chance to use languages like Eiffel, Ada, Dylan, ... is very small.

Re:Don't use C++ as if it was only "C with classes (2, Funny)

orangeyoda (958347) | more than 7 years ago | (#17506718)

Which is a good thing, Ada was awful to learn and worse to debug. I've seen the light, no more c++ spending hours to decode meglomaniac's tempalates , no more java exception hell , bye bye vb6 error unhandling . Hello C#

Re:Don't use C++ as if it was only "C with classes (3, Informative)

shutdown -p now (807394) | more than 7 years ago | (#17506630)

Uh... let's see. Open the most recent ISO C++ standard, and search for all occurences of "undefined". Repeat for "implementation-defined". Make a notice of how many of those are from the sections related to the Standard Library. Then meditate on the results.

Yes, sure, if you use STL, you need not worry about getting the buffer size wrong. And that's about it - container indexing is not bound-checked (unless you use at() instead of operator[] - and that's about the only instance of run-time safety check I remember seeing in STL!), iterators can go outside their container without notice, or can suddenly become invalid depending on what their container is and what was done to it. Even leaving library issues aside, there are some nasty things about the language itself - it's just way too easy to get an uninitialized variable or a class member, or to mess up with the order of field initializers in constructor.

This is not to say that C++ is not a good language. All of the above are features in a sense they are there for a reason - but they certainly don't make writing secure software easier.

Avoid direct memory access (4, Insightful)

Ed Avis (5917) | more than 7 years ago | (#17506156)

You introduce buffer overflows when you deal with buffers directly. In conventional C with its standard library you're encouraged to do this rather a lot, for example many of the string functions expect you to allocate a char buffer of big enough size and pass it in. The language's arrays are just syntactic sugar for accessing raw memory, with no bounds checks.

However you don't have to do it like this, especially not in C++ which has a safe string class (for example) as part of its standard library. Unfortunately C++'s vector type still doesn't do bounds checking with the usual [] dereferencing - you have to call the at() method if you want to be safe. But the general principle is: don't do memory management yourself, use some higher-level library (which exist for C too) and let someone else do the memory management for you.

You can write a C++ program and be pretty confident it doesn't have buffer overruns simply because it doesn't use pointers or fixed-size buffers, but relies on the resizable standard library containers.

Re:Avoid direct memory access (5, Informative)

ojQj (657924) | more than 7 years ago | (#17506286)

Unfortunately stl isn't binary compatible. That means you have to make sure you've compiled with exactly the same version of the stl with all the components of your program which accept and pass strings. This in turn makes it impossible to release different parts of your program separately from each other if you are using the stl at the interface between your components.

There are a couple of solutions to this problem:

1.) Pass character arrays at the interfaces between your components and immediately put those character arrays under the control of your library once they come in.
2.) Write or find your own string library and pass that string class between program components. Be careful when doing this. Mistakes will come back to byte you.

All of it's kind of nasty. It'd be nice if C++ could standardize their binary representation, even if it's only a standard valid per platform.

Then there's also:

3.) Choose a language which unlike C++ already has a standardized binary representation for strings, or a system global interpreter for a varying binary representation. This is just an extension of the "higher-level library which does the memory management for you" option really.

Don't get me wrong -- I'm agreeing with the parent post. I'm just adding a caveat.

What do you think about... (1)

hummassa (157160) | more than 7 years ago | (#17506370)

4) passing strings (or ANY data, for that matter) between separately-compiled, out-of-process components of your program ONLY via safe IPC marshalling mechanisms (like streams, files, pipes, etc...); keep in mind that the STL already has a mature marshalling-to-ASCII/UNICODE mechanism in <iostream>

Re:What do you think about... (1)

ojQj (657924) | more than 7 years ago | (#17506726)

Actually I was thinking about separately-compiled in-process components when writing the above. If you are otherwise in-process marshalling is kind of expensive. Out-of-process components is not an area in which I do much programming, so it sounds like you know more than me. Feel free to elaborate :o)

Re:Avoid direct memory access (0)

Anonymous Coward | more than 7 years ago | (#17506740)

It'd be nice if C++ could standardize their binary representation, even if it's only a standard valid per platform.

Yes. They could call it cross vendor C++ ABI [codesourcery.com] or something.

Re:Avoid direct memory access (1)

ojQj (657924) | more than 7 years ago | (#17506910)

It's certainly very useful to enforce rules about your vtables and etc. It's actually a pre-requisite for ever getting to the problem with the strings. The ABI for Windows is COM; there your binary string representation is BSTR. BSTRs can be manipulated using various libraries, they are however not explicitly associated with the STL or any other library, much less a library which is part of the C++ standard. So you can pick a library, or you can do your memory management, avoid buffer-runs and etc yourself.

That would be option 1 above.

Re:Avoid direct memory access (4, Insightful)

Viol8 (599362) | more than 7 years ago | (#17506306)

"simply because it doesn't use pointers "

Err, how much C++ have you written? I've yet to see any complex C++ *without* pointers since you cant reference or use dynamically created objects using the new operator without them. Not to mention in 101 other instances where they're useful.

Re:Avoid direct memory access (0)

Anonymous Coward | more than 7 years ago | (#17506464)

boost::shared_ptr is your friend :)

Re:Avoid direct memory access (1)

ZorbaTHut (126196) | more than 7 years ago | (#17506802)

I've seen, and written, a lot of complex C++ that didn't use pointers directly. I try to avoid pointers in general - any case where I use pointers is carefully hidden behind abstraction.

(This doesn't count pointers-as-function-parameters, as long as they're not stored anywhere. I use those pretty often. But I've found that generally stored pointers are just plain difficult to deal with properly, unless ownership and invalidation semantics are utterly 100% clear, and even then they're tough.)

Re:Avoid direct memory access (1)

Jeff DeMaagd (2015) | more than 7 years ago | (#17506314)

I think there's a qualifier that needs to be added here. A C++ program is safe if you use standard C++ coding methods, the classes that you are using are safe and don't have to write your own classes. Having the STL classes helps a lot here but there may be situations where one might want an alternative data storage class which might require the coder to do memory management.

I don't. (1, Redundant)

WalterGR (106787) | more than 7 years ago | (#17506164)

How do you go about making sure your code is secure? Especially if you have to write in a language like C or C++?

I don't. I just open source my code, and other people find the security bugs for me. More eyeballs and all, ya know?

;)

Re:I don't. (5, Informative)

Anonymous Coward | more than 7 years ago | (#17506298)

Grammar tip: "Effect" is a verb. "Affect" is a noun.

Um, how's that?

Your poor grammar has a chilling effect on me. If I were you, I'd find a way to effect an improvement in your knowledge. Luckily it affects me only a little. But the fact that so few seem to understand that these two words are both verb and noun leaves me of sad affect.

Easy (5, Funny)

$pearhead (1021201) | more than 7 years ago | (#17506166)

Just make sure your buffers are really really REALLY big:

char nooverflowbuffer[234523400];

sprintf("Enter something:");
scanf("%s", nooverflowbuffer);
... or maybe not ...

Re:Easy (0)

Anonymous Coward | more than 7 years ago | (#17506706)

You're not so far of as you may think. When people say that languages like Java prevent buffer overflow errors, they don't mean that the compiler will magically generate the correct code to handle the overflow situation. It can't, what is the correct(tm) solution? Throw the rest away? Read it in multiple passes? Make the buffer bigger? Stop the program with an error message? What Java does (at least with classes like string), is to simply make the buffer bigger when there isn't room enough. That won't work forever. First you'll run out of RAM (another fixed size buffer), and then virtual memory. So, basically the solution IS to make the buffer REALLY BIG, until it consumes all RAM and VM.

(And after it runs out of RAM and VM, it will stop with an OutOfMemoryException, unless the box has trashed itself to death before that, making it into a nice DOS attack).

Security (2, Insightful)

El Lobo (994537) | more than 7 years ago | (#17506170)

It is hard to be sure that your code have no bugs or security holes. That's because even the Hello world program is using implicity a lot of libraries/dependences that are not written by you and are sometimes very complex. For example, writting Hello World to the console invokes a string handling unit in any hight level languge. String handling units are per se complex unit and there may be a lot of bugs there that may affect your code's security if those bugs are exploited.

Writting in C/C++ doesn't do the whole thing better. A strong/typed language like Delphi or a managed language like C# are less likely to have any buffer overflow type bugs, etc, but you never know. Code writting is not pizza baking.

Re:Security (1)

beakerMeep (716990) | more than 7 years ago | (#17506720)

Apparently you have never suffered from disastrous cheese overflow.

How Do You Know Your Code is Secure? (1)

Duds (100634) | more than 7 years ago | (#17506174)

Easy, I never ever run the program.

Re: How Do You Know Your Code is Secure? (1)

Rogerborg (306625) | more than 7 years ago | (#17506260)

But can you discount the possibility that your program may already be running (or not running) on a quantum computer somewhere?

Re: How Do You Know Your Code is Secure? (1)

Rik Sweeney (471717) | more than 7 years ago | (#17506452)

Easy, I never ever run the program.

You'd make a great Doctor:

It hurts when I do this.... ouch!

Don't do that then.

Same way you hunt bugs (5, Informative)

Llywelyn (531070) | more than 7 years ago | (#17506184)

0) Don't "roll your own" security unless absolutely necessary. Find someone else's implementations and work with those.

1) Design the code for security, code to that design. I've seen of security bugs creep into code because it was never designed to be secure.

2) Use static code checkers--such as Splint [splint.org] for C/C++ and FindBugs [sourceforge.net] for Java--that look for security vulnerabilities.

3) Peer reviews/code audits. Sit down with your code (and have others who know how to look for security vulnerabilities sit down with your code) and do a full review.

Nothing is foolproof, but every little bit helps. It should be noted that all of the above also improve the overall quality of the code and reduce the number of overall bugs: Finding existent implementations of features that can be used can reduce maintenance and reduce bugs; Designing the code and putting it through a proper design review can catch a lot of logic problems and ensure that the code fits the requirements list--I've seen a huge number of synchronization bugs in Java simply because the author didn't know how to use synchronization properly; static code checkers find a lot more than just security bugs; and Peer Reviews/Code Audits can help isolate a variety of problems.

Re:Same way you hunt bugs (1, Interesting)

Anonymous Coward | more than 7 years ago | (#17506612)

Don't "roll your own" security unless absolutely necessary. Find someone else's implementations and work with those.

This is correct for crypto, wrong for everything else. I've often replaced third party authentication code that was above and beyond what was required in terms of complexity.

Design the code for security, code to that design. I've seen of security bugs creep into code because it was never designed to be secure.

In principle I agree, in the real world it's about finding a balance. You can't design away security bugs and you can't spend 60% of your runtime stuck in input validation and security procedures.

The answer is simple - you never know (4, Insightful)

tuxlove (316502) | more than 7 years ago | (#17506186)

Anyone who develops software knows the axiom - the number of bugs discovered in any piece of software is directly proportional to the amount of testing you perform on that software. From this, it follows that you can keep testing forever and at best only asymptotically approach bug-free code. Sounds hyperbolic, but I've observed it to be true in my experience. And as long as there are bugs, there are bound to be security bugs.

You can only minimize the risk that security issues will be found with any software. The best way to do this is to perform a rigorous code audit, preferably by security professionals. And if you can, make the software open source. You get a lot more eyes staring at it for free that way.

Re:The answer is simple - you never know (2, Informative)

Rogerborg (306625) | more than 7 years ago | (#17506280)

Another issue with (manual) testing is that testers tend to pursue bugs aggressively in whatever area they first happen to find some, which means you get good depth coverage, but can end up missing out on testing whole areas of functionality.

Re:The answer is simple - you never know (4, Interesting)

TheRaven64 (641858) | more than 7 years ago | (#17506804)

Don't trust your own code. The reason OpenBSD is secure is party because the code is security audited constantly, but also partly because much of the system is written on the assumption that the rest of it is buggy. Isolate your code as much as possible. If you can get away with it, fork off separate modules and communicate between them over a well-defined interface. Validate everything that is received. Don't let any of your code run with more privileges than it needs; make good use of chroot and setuid. If you don't need to be able to access anything on the filesystem then the first thing you should do is make an empty directory and chroot there; that way an attacker who compromises your code can't do anything useful.

The best advice I read was from the Erlang documentation. It suggested that you program defensively on a system level, but not on a module level. If a module receives input it can't understand, or thinks it is in an invalid state, the correct behaviour is for it to crash. A system of monitors should deal with failures of components, because they can determine how the failure will affect other components. There has only been one remote root hole in OpenBSD in the last ten years, and it would have been avoided if the OpenSSH developers had used this principle.

What's the matter with C/C++? (4, Insightful)

mangu (126918) | more than 7 years ago | (#17506188)

Why do people keep this meme that C/C++ is so insecure? Remember, deep down inside the other languages, there often is a compiler, library, interpreter, etc written in C/C++.


It's not that C/C++ is so insecure by itself, the problem is that programmers may not have used the best programming practices. There are plenty of libraries for handling strings and memory allocation in C, in C++ there are string and storage classes that do as much or as little checking as you need.


When you are an expert programmer there are places where you need more efficiency than the super-safe string routines can give you. It's the job of the expert to determine exactly how to balance efficiency against security, and only C/C++ can give you this balance.

Re:What's the matter with C/C++? (5, Funny)

Anonymous Coward | more than 7 years ago | (#17506256)

'It's not that C/C++ is so insecure by itself'

yeah a gun by itself is not insecure either....
try giving it to a baby.....
well I prefer a baby with a knife...I can still run faster than him...

Re:What's the matter with C/C++? (4, Insightful)

Viol8 (599362) | more than 7 years ago | (#17506318)

C/C++ are very powerful languages because they let you do pretty much what you like. But with this freedom comes the ability to shoot yourself in the foot badly either due to design errors, sloppy programming or just genuine mistakes. Personally I don't mind this risk but other people (usually the types who knock C/C++) can't really function in an enviroment that doesn't hold their hand and protect them from their own mistakes. Horses for courses.

Re:What's the matter with C/C++? (0)

Anonymous Coward | more than 7 years ago | (#17506492)

Remember, deep down inside the other languages, there often is a compiler, library, interpreter, etc written in C/C++.

And remember deep down inside C/C++ there is assembler! ;-)

I think we should just look upon programming languages as the tools that they are, in the right hands a true expert can create masterpieces with almost any language and in the hands of an idiot they can break even the smartest language. Indeed it could be said that there is now a "general" problem not just with security due to the fact that programming has now been dumbed down so much to the point that many proper programmers now spend their lives either replacing badly written access databases, excel macros or getting requests/complaints from someone who hasn't a clue what they are doing as they try to reinvent the wheel as a square block.

When I was taught to program I was taught to design the program to do the task correctly first and make it look pretty later. Unfortunately with the advent of "visual programming" we now see the modern approach of people writing programs to look pretty first and then only later putting functionality in such as security. That is to say that they don't even give a thought to security when they are busy putting their 3 big buttons onto their macro launcher.

Don't get me wrong I'm not totally against visual programming, I just feel the interfaces should encourage people to write the functional part first (with security) and then make the front end look pretty later. In the same way that it annoys the hell out of me to see animation for the sake of animation when the underlying task is given second priority. (e.g. copying files in windows) - it looks pretty but it now takes forever for the task to happen!

In addition I also think that most companies should stop using their intern/students, junior/novice programmers to write their installation programs as that would resolve a lot of install/removal problems in the world. Anyone who knows coding knows what I mean here, the newbies are asked to write either the install or the launcher. Many a time a decent program has been dropped due to someone being unable to write a install program, even with helpful advent of NSIS you still see people who can't even us NSIS correctly - scary !

Re:What's the matter with C/C++? (1, Interesting)

Anonymous Coward | more than 7 years ago | (#17506624)

max planck, the famous german physicist whoose name is immortalized in the planck, once observed that it is not tthat scientists retrain themselves as theorys become obsolete, but that the new genrations don't learn the errors of hte past

Re:What's the matter with C/C++? (2, Interesting)

TheRaven64 (641858) | more than 7 years ago | (#17506816)

Remember, deep down inside the other languages, there often is a compiler, library, interpreter, etc written in C/C++.
Not in the case of Smalltalk. The Squeak VM is written in a subset of Smalltalk which is compiled by a compiler written in Smalltalk into native code. Most of the Java VM and compiler, I believe are written in the same way.

There are plenty of libraries for handling strings and memory allocation in C, in C++ there are string and storage classes that do as much or as little checking as you need.
Once you have added enough to a language that it no longer looks like the original, then it's time to ask yourself if you picked the correct language for the job to start with. I could write a dynamic dispatch mechanism with inheritance for use in C, but I would start to wonder if I shouldn't really have written the entire project in Objective-C instead.

Grammar (2, Insightful)

noz (253073) | more than 7 years ago | (#17506208)

Marucs Ranum notes taht [...]
Marucs' code is more secure than Zonk's editing.

Re:Grammar (-1, Offtopic)

Bob54321 (911744) | more than 7 years ago | (#17506488)

I do believe there is a difference between grammar and spelling, although I do not claim to be good at either.

Zonk, Oink! (-1, Offtopic)

Anonymous Coward | more than 7 years ago | (#17506212)

First step is to check for no typos.

-- Mr "taht"

Some possibilities (2, Insightful)

AArmadillo (660847) | more than 7 years ago | (#17506232)

You cannot know for sure (unless you want to develop code by mathematical proof, which requires a considerable amount of effort). However, you can do some things to help prevent buffer overflows and security problems in general: - encapsulate all buffer access, and make the interface overflow-safe. Then you need only ensure your encapulation is secure. - use a static code analysis tool that detects buffer overflows. I do not know of any open source ones off the top of my head, but I remember seeing an article on slashdot a few months ago about a new open source static analysis tool - avoid unsafe functions. Nearly all standard C functions that deal with buffers are unsafe (that is, a typo or oversight can give you a difficult to detect buffer overflow). Sprintf and strcpy are common culprits off the top of my head. If you're writing for Windows, the Microsoft extensions to the standard library have equivalent 'secure' functions (usually postfixed with _s). I do not know if there is an open source equivalent. - Use your compiler's buffer overrun detection. I think this is -fmudflap for gcc. That's all I can think of for now.

Re:Some possibilities (5, Funny)

zCyl (14362) | more than 7 years ago | (#17506308)

You cannot know for sure (unless you want to develop code by mathematical proof

In the words of the great Donald Knuth, "Beware of bugs in the above code; I have only proved it correct, not tried it."

Easy... (1)

D-Cypell (446534) | more than 7 years ago | (#17506258)

How Do You Know Your Code is Secure?


Easy! It doesn't run :)

Valgrind (5, Informative)

chatgris (735079) | more than 7 years ago | (#17506266)

By using valgrind. It's a virtual machine of sorts that runs your code and checks for any memory problems at all, including use of uninitialized memory. Combine that with thorough test cases, and you can be virtually assured that you have no memory errors in your C/C++ code.

However, security is a lot more than buffer overflows... but at least it brings you up to the relative security of Java, with speed to boot.

Re:Valgrind (0)

Anonymous Coward | more than 7 years ago | (#17506378)

... Combine that with thorough test cases ...
That is the problem, right there. Generally you will not get 100% code coverage in tests, i.e. it is is not possible to test the program with all possible inputs and all possible error conditions.

Re:Valgrind (1)

Tony Hoyle (11698) | more than 7 years ago | (#17506744)

Nope. Valgrind will find crashing bugs, not security issues.

It can only find actual overflows as they happen not potential overflows. You need code analysis to do that - there are a number of tools on the market that can do that kind of analysis (not sure if there are any free/oss ones though.. never seen any).

Assume failure (5, Insightful)

zCyl (14362) | more than 7 years ago | (#17506282)

Every function should be designed with the assumption that its input is faulty, and should have safe failure modes for every possible value and all possible content. Any unsafe external libraries must be wrapped in handlers which verify the data being passed to them with a similar mindset. Do not EVER presume data will be of a certain form, or that a function will be used a certain way. If sequential routines are becoming long such that you cannot verify the accurate function or the absence of a buffer overflow immediately in your head, then stop and look for a way to break it down into smaller abstract pieces.

Combine this mentality with the usage of safe classes as datatypes whenever possible, so that you can wrap your input verification into the functionality of the classes. If prudent, wrap external library routines in classes which manage the interaction with them, and which verify the data content being passed.

Use test suites to test every component of your program, and be sure to include invalid and pathologically insane input in your test suites.

Do not trade security for efficiency. And don't forget to cross your fingers.

Re:Assume failure (-1)

Anonymous Coward | more than 7 years ago | (#17506676)

> Every function should be designed with the assumption that its input is faulty

Fuck off, private functions below the public API should never have to check their input.

Re:Assume failure (4, Funny)

TheRaven64 (641858) | more than 7 years ago | (#17506880)

Fuck off, private functions below the public API should never have to check their input.
I completely agree. There are no bugs in my code, just in the code of people calling my code.

Re:Assume failure (1)

TheRaven64 (641858) | more than 7 years ago | (#17506852)

Do not trade security for efficiency. And don't forget to cross your fingers.
I disagree on this point. Only trade efficiency for security when you know what you are doing. If you are writing HPC code that is going to run on a private supercomputer or cluster, or code that will be run in a VM which is then thrown away, you can do this. Whenever you do, however, add a #warning line reminding users of the code where it's insecure so that anyone who wants to take the code and use it in production will know what to fix.

Perspective (0)

Anonymous Coward | more than 7 years ago | (#17506300)

Change your perspective on the issue. The "insecurities" are a result from what the programmer has written. Rather than viewing them as branches of execution that should not happen, view them as unintended parts of the program that do happen. If you do not want your program to behave that way, then do not write your code that way.

Think about the code as you are writing it. Think about every possible outcome of executing the code you have programmed.

I know the last two are difficult with the hustle and bustle we live in now, but I don't know of a less time consuming solution.

Unless you can account for every instruction in your code, you do not know that your code is secure,

Good luck.

Just Say No (0, Troll)

iliketrash (624051) | more than 7 years ago | (#17506310)

"How do you go about making sure your code is secure? Especially if you have to write in a language like C or C++?" Don't write in C or C++. Duh. Where is it written that all software must be written in C or C++? Is anyone capable of independent thought? There are plenty of fine languages that are safe. Ada comes to mind. Maybe others will come to your mind (if you have one).

Re:Just Say No (2, Insightful)

hAckz0r (989977) | more than 7 years ago | (#17506426)

Ada comes to mind.

Ok, What language is your Ada compiler written in? There are very few self-hosted languages that do not rely on "C" at some level. Also, the OS and the system libraries were written in C. At some level you need to deal with the stated problem. All that being said many people are probably better off with Ada unless they actually "study" software security on a daily basis.

Re:Just Say No (1)

gbjbaanb (229885) | more than 7 years ago | (#17506556)

The stated problem is obviously programmers who don't know enough about what they're doing and require an easy-to-use language that makes up for their shortcomings. :-)

Re:Just Say No (0)

Anonymous Coward | more than 7 years ago | (#17506518)

Well its not that simple. A lot of softwares require to use C/C++ for efficiency/performance. You can't always use Java or .NET or Scripting languages for those tasks.

Easy (0, Flamebait)

Sodki (621717) | more than 7 years ago | (#17506312)

How about not using languages that allow buffer overflows?

Re:Easy (0)

Anonymous Coward | more than 7 years ago | (#17506408)

How about realizing the overflows are not the only security problem out there. And any developer worth their bones would write functions that have explicit bounds checks anyways.

C is a decent language, you just have to not "suck" at it. And lots of review. In the >5 years I've been working crypto I've had maybe a half dozen buffer problems (usually overruns not overflows).

Everyone seems to naively assume that languages like Java or C# solve all these problems, but it's totally easy to have race conditions (for instance) in a Java application which allows "teh nasty" to happen.

And god forbid you be working with cryptography, then you have to actually USE it right too (not just write secure code).

Don't let them use it where it matters (5, Funny)

Anonymous Coward | more than 7 years ago | (#17506316)

I let my code have evident, gaping security flaws and make them well known. This way people will never use it in situations where security matters.

regards,
The author of sendmail

String overflows (2, Informative)

Rik Sweeney (471717) | more than 7 years ago | (#17506344)

I think for some people, moving from using a language like Java to using C can cause them a multitude of problems since there's no bounds checking by default and overruns aren't caught.

For example, I recently fixed a bug Blob And Conquer to do with Strings, the code was something like this:

char nm[2];

nm[0] = mission[11];
nm[1] = mission[12];

The code then went on to doing a

missionNum = atoi(nm);

Most of the time, this'd work OK because of the way atoi works. Other times though it'd stray off into other memory and pick up a random number and return a three or more digit number instead.

Obviously there's an easy way to fix it.

Re:String overflows (0)

Anonymous Coward | more than 7 years ago | (#17506758)

WOW!

Now you are a full fledged programmer! Let's all be complacent in our limited knowledge and fool ourselves that since we know hot to program, we know everything else! This is because we have inherited the world, like "Revenge of the Nerds" has taught us. Never mind that we are the butt of jokes by mathematicians, physicists and other real scientists! We can just continue on having undeserved arrogance, saying "OMG YOU DONT KNOW WHAT VIRTUAL MEMORY IS LOLOL"

Re:String overflows (1)

Tony Hoyle (11698) | more than 7 years ago | (#17506768)

That's just college level programming though.. nobody would make that kind of mistake who had any experience.

99% of the time that code would just crash, or the compiler/runtime would throw up an error saying what you'd done. If anyone actually committed something like that on my watch they'd be in trouble.

So how much did Fortify pay for the ad on /.? (-1, Troll)

Anonymous Coward | more than 7 years ago | (#17506366)

nuff said...

Proving the Unprovable (2, Insightful)

Sub Zero 992 (947972) | more than 7 years ago | (#17506368)

How do you validate code for correctness? Well, either you use some cool formal specification language, such as Z, and then spend a great deal of time and effort validating (which is actually very advisable for critical code in, say, device controls for medical equipment) or you use blind luck and "proven" techniques, collectively known as Good Programming Practice.

Traditionally it has been important to "specify and validate" requirements acribically, in the belief that this is was the way to write good code. This is partly true, but that way can quickly turn your process into a dinosaur - stifling change and preventing improvement because of non-compliance with "The Requirements".

You can try "defensive coding", which really treats all messages with great suspicion, messages being an old term for parameters. This is a cool technique, but can lead to slower code than necessary, and can lead to some bug being buried if code attempts to heuristically correct for "bad" messages (there is rarely any way to formally specify what is "bad"). You can use LINT tools (and there are very many, very sophistacted tools) which will catch a whole lot of stuff before it leaves the developer's screen. You can try practices such as pair programming and independent code inspection. On the coding side, you can even try (gasp) such methods as test driven development and contract based development.

On the testing side, there is nothing quite like having an experienced, qualified, motivated and _empowered_ testing team. A testing team which knows how to find bugs, knows how to communicate with coders and has the power to step defects going in to production. A technique I particularly like is defect insertion - secretly insert 10 bugs into the code base and see how many get squashed, this will give you an estmate of how many defects your process doesn't find. There are other cool techniques too, some based on mathematical analysis of the code's attribute - the more complex the code the costlier it is to maintain.

Opening up the codebase to many people might well increase the chance that someone will find the line which causes an error - but IMHO no one goes around looking for bugs unless they are looking for weaknesses. And there we have another (unethical) method - pay some hacker doodz to 'sploit your code. Hopefully they will not find a higher bidder LOL.

All of these methods are likely to increase development effort and cost, decrease the number of defects, increase user satisfaction, decrease maintainance costs and increase well-being and harmony. So it is a trade off, perfect code is incredibly difficult to create - the question is what level of perfection are you (and your customers) willing to pay for. Problems mostly arise when expectation does not meet reality - some flakiness in an F/oss application suite is more acceptable to me than random crashes in software which cost me hundreds - or tens of thousands - or millions - of dollars.

In order to increase some quality aspect of code (security, performance, robustness, correctness...) one can therefore focus on one or several categories - the people, the process, the culture, the tools, the technique, the time&cost etc. The choice of what to focus on is dictated by reality: no one has unlimited resources (except, almost, Google).

There is no silver bullet - but there are golden rules. Finding people who know the difference is crucial I believe.

(Full disclosure: Yeah, I'm looking for heavy duty PM work :)

As the saying goes (1)

starmang (661689) | more than 7 years ago | (#17506388)

Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.

In my opinion... (1)

joxeanpiti (789529) | more than 7 years ago | (#17506390)

How do you go about making sure your code is secure?

In my opinion the unique way is by trying to exploit/crash you program during development using logical and/or fuzzing techniques. Many programmers think that "security" is the last step they need to follow when writting a piece of software but they missed that security is one of the "intermediate" steps, not the last.

In my case, I always conduct an audit in my software when a module (in example) is finished, when I added a new functionality, etc...

Does language matter? (2, Interesting)

forgoil (104808) | more than 7 years ago | (#17506428)

In this case it doesn't in one important way. Programming is the same regardless of language, since humans are the same regardless of language. What you need to write good software (again, why just secure? Why focus on a certain aspect, why not just generalize?) is skills/knowledge and good habits. My best advice here is to make sure you give yourself good coding habits. Don't say things like "I'll clean that up later" or "I will add error checks later" or something equally damaging. Give yourself good, sensible, habits and follow them. Any average programmer must know what buffer overflow means, and how to correct it. You can't even be an average programmer unless you know. So why is such insecure code written in C/C++ then? My thinking is plain mistakes and bad habits.

Absence of errors (1)

Sique (173459) | more than 7 years ago | (#17506450)

You don't know your code is secure. You just know that it handles certain test cases apparently correct.

(Ok... Silly examples like "while(TRUE);" are partially correct, because they never terminate, and thus you can't tell they handle the test cases incorrectly.)

It's like scientific theories. You will never know if a scientific theory is entirely correct. You just can point to the test cases you have thrown at the theory which it was able to handle, and to the results you got from using the theory. It still doesn't prove that the theory is correct, only that you were unable to poke holes in it until now.

So all you can do is check for known traps, border cases, predictable error conditions, and in general following the KISS principle to keep the number of test cases down. And keep all documentations for tests and checks you were doing as long as you are supporting the code.

Re:Absence of errors (1)

gkhan1 (886823) | more than 7 years ago | (#17506912)

This is not strictly true. Scientific theories cannot be proven 100% true because they rely on inductive logic, throwing test cases at them as you say. However, programming is fundamentally a branch of mathematics (remember that every program in a Turing complete language is essentially just a Turing machine), and mathematics is not inductive, its deductive. From that you can, in fact, prove that it would be impossible for code to buffer overflow (given that the compiler, OS or hardware isn't malfunctioning, of course).

The only sure way I know of: Lambda calculus (4, Interesting)

Berkana (471619) | more than 7 years ago | (#17506466)

If you program using strictly functional programming, you can not only verify that your code is 100% secure, but you can even automate the process. (Preferably in a functional programming language such as Scheme, caml, Haskel, LISP, or Erlang; imperative languages make it very difficult/slow to do with functions what functional languages do very naturally and easily.) Purely functional code can be subjected to automated code auditing easily, whereas code auditing imperative code cannot be guaranteed to catch every bug and unintentionally available abuse.

Here's why, and why just about any computational problem can be solved using FP (functional programming):
Functional languages conform to lambda calculus, which has been shown to be Turing equivalent, which means that any program that can be computed on a Turing machine can be solved using Lambda calculus. So long as you program using strictly functions, your program can be verified according to the rules of lambda calculus, and the verification would be as sure as a mathematical proof. This is the only sure way I know of really knowing with mathematical certainty that your application is secure.

Pure functional programming has no assignment statements; there are no state changes for you to keep track of in your program, and in many cases abuses resulting unintended changes of state are the root of security problems. This is not to say that there is no state in functional programming; the state is maintained through function call parameters. (For example, in an imperative programming language, iteration loops keep track of a state variable that guides the running of the loop, whereas a functional program never actually keeps track of state with a variable that changes value; a functional program would carry out iteration by recursion, and the state is simply kept as a parameter passed to each call of the function. No variable with changing state is ever coded.)

Since functional programs lack assignment statements, and assignment statements make up a large fraction of the code in imperative programs, functional programs tend to be a lot shorter for the same problem solved. (I can't give you a hard ratio, but depending on the problem, your code can be up to 90% shorter when described functionally.) Shorter code is easier to debug, which helps in securing code. The reason functional code is so much shorter is that functional programing describes the problem in terms of functions and composition of functions, whereas imperative code describes a step by step solution to the problem. Descriptions of problems in terms of functions tend to be far shorter than algorithmic descriptions of solving them, which is required in imperative code.

Here's the biggest benefit of managing complexity with functional programming: as a coder, you NEVER have to worry about state being messed with. The outcome of each function is always the same so long as the function is called with the same parameters. In imperative programming as done in OOP, you can't depend on that. Unit testing each part doesn't guarantee that your code is bug free and secure because bugs can arise from the interaction of the parts even if every part is tested and passed. In functional programming, however, you never have to deal with that kind of problem because if you test that the range of each function is correct given the proper domain, and pre-screen the parameters being passed to each function to reject any out-of-domain parameters, you can know with certainty where your bugs come from by unit testing each function.

If you need to guarantee the order of evaluation (something that critics of FP advocates sometimes use to dismiss FP advocacy), you can still use FP and benefit: in functional programming, order of evaluation can be enforced using monads. Explaining how is beyond the scope of a mere comment though, but in any case, if you need really reliable code, consider using a functional programming style.

I can't do justice to the matter here; for more information, see this:
http://www.defmacro.org/ramblings/fp.html/ [defmacro.org]
A quote from the article I linked above, to whet your interest:
A functional program is ready for concurrency without any further modifications. You never have to worry about deadlocks and race conditions because you don't need to use locks! No piece of data in a functional program is modified twice by the same thread, let alone by two different threads. That means you can easily add threads without ever giving conventional problems that plague concurrency applications a second thought!

If this is the case, why doesn't anybody use functional programs for highly concurrent applications? Well, it turns out that they do. Ericsson designed a functional language called Erlang for use in its highly tolerant and scalable telecommunication switches. Many others recognized the benefits provided by Erlang and started using it. We're talking about telecommunication and traffic control systems that are far more scalable and reliable than typical systems designed on Wall Street. Actually, Erlang systems are not scalable and reliable. Java systems are. Erlang systems are simply rock solid.

The concurrency story doesn't stop here. . .
There are times where you cannot simply use FP because your code must interface with other code that does care about state. In those cases, use functional programming as much as possible, and limit the parts that use imperative code and state to a minimum. That way, you limit the places where your code can have state related problems, and improve your chances of securing the code, since there is far less of it for you to sift through and secure.

If this has caught your curiosity, I urge you to read the link above. As for what functional language I advocate, my personal favorite is Scheme, because of its simplicity, but if you want to do OOP, CLOS, OCaml, and various Scheme object systems can implement just about any object based program you need.

Re:The only sure way I know of: Lambda calculus (-1, Offtopic)

Anonymous Coward | more than 7 years ago | (#17506530)

Sucking the functional dick is not going to earn you fast points here on Slashdot. Just saying.

Re:The only sure way I know of: Lambda calculus (1, Insightful)

Sub Zero 992 (947972) | more than 7 years ago | (#17506614)

To be honest, I have got _no_ idea what you are trying to say.

By the way, I meant to say this also (3, Interesting)

Berkana (471619) | more than 7 years ago | (#17506574)

If you want to learn about Lambda Calculus (which was developed by Alonzo Church, a contemporary of Allan Turing), Wikipedia is a good place to start (http://en.wikipedia.org/wiki/Lambda_calculus [wikipedia.org] ), but mastering Lambda Calculus is not necessary; first master a functional programming language, and a lot of the lambda calculus will be made easier.

To summarize, here's how you verify with mathematical certainty that a functional program is secure:
  1. You use purely functional code; that guarantees that there are no changes of state involved in the operation of your program.
  2. you unit test each function to make sure that given the correct domain/scope, their return values are always conforming to the desired range (and I don't just mean numbers when I say "range"; I mean correct data formatting, list/tree formatting, data structures, etc.), and you set up input filters that exclude any call parameters that are not part of your desired function domain.
  3. You check to see what functions call which functions, and make sure that they never call a function with parameters that are incorrectly formatted or out of the correct domain
  4. You make sure that every function and every constant is properly scoped.

That's the gist of it. Anything more on this topic, such as automatic code auditing with the certainty of mathematical proofs (by means of lambda calculus proofs) is beyond my expertise. I just know that it's possible to truly secure functional code with mathematical certainty, whereas with imperative code, you can only be sure that your code has not yet failed or exposed a rare bug or failure condition.

Correct but irrelevant (0)

Anonymous Coward | more than 7 years ago | (#17506818)

All the above statements on the power and elegance of FP are true, but totally unrelated to how programs are actually cracked.

The essence of cracking an application today is to break the semantics of the computational model. Once the attacker breaks that, end of story. This is the common denominator of buffer overflows, memory allocation exploits, TOCTTOU attacks, etc.

Re:The only sure way I know of: Lambda calculus (4, Insightful)

TheRaven64 (641858) | more than 7 years ago | (#17506918)

When you start to introduce concurrency into a functional program, you end up with something closer to Pi calculus. The verification of both Pi and Lambda calculus expressions is still an open research problem (being worked on by some very bright people on the floor below me). There are a huge number of problems, not least of which in my mind is Gödel's incompleteness theorem, which states (roughly) that any system can only be completely described by a system more complicated than itself. You can generate a proof from your lambda program, but you still need to verify it and the proof will be more complicated (and thus harder to verify) than your original problem.

There is also the question of what the proof actually says. You can't prove, for example, whether a lambda program will terminate (Halting Problem), and in fact you can prove that you can't prove this. If you have a sufficiently well expressed specification for your program, you can verify that the program and the specification match. Unfortunately, if you have a specification that concrete, you can just compile it and run it.

By the way, Scheme is not a functional language. It has a number of properties that make it possible to write functional code, but saying Scheme is a functional language is like saying C++ is an object oriented language.

Security? What's that? (2, Insightful)

JHWH (1046444) | more than 7 years ago | (#17506478)

You can write code that can be as secure as you want, but what about libraries, compilers and hardware?
I think the question itself makes little sense without a deeper investigation in the system!

buffer overruns should be easy, at least? (1)

Mirar (264502) | more than 7 years ago | (#17506500)

Avoiding buffer overruns should be fairly easy, anyway, shouldn't it? Don't used fixed size buffers, unless you really have a control of what's going in them. And if you do, don't place them on the stack.

Now the *other* security flaws... ...but I agree with previous speakers. Open your source, let the world check it. If you don't, chances are someone will disassemble it and find the flaws anyway, but wont tell you.

Port it to Visual Basic (0)

Anonymous Coward | more than 7 years ago | (#17506508)

just port your proggy to Visual Basic and you'll be fine ;)

my 2 cents (0)

Anonymous Coward | more than 7 years ago | (#17506562)

Every function handling alien data should be foulprof. Double check it, let someoneelse double check it. After the incomming data has been verified as correct.. then.. well.. dont care to much, just make sure the logic of the program works. The important thing is after all that no one else can break your program, less important if you can.. If you do you will surely see it in the tests.. But always, always verify all input data the program has. If it doesn't fit what the program exspected, complain and reject or even exit(-1). Never Ever process data in your program you dont have control of.

3 Things (1, Interesting)

Anonymous Coward | more than 7 years ago | (#17506638)

a) good coding practices
b) formal peer reviews for pre-design, design, code, test specifications, and test results
c) Purify!!! http://www-306.ibm.com/software/awdtools/purify/ [ibm.com] A license for every developer AND tester!

I haven't written any code since 1999, but that was how I setup the development team for that company. The reviews also are a form of cross training and team building. Nobody is perfect and showing our individual errors helps everyone fit in. OTOH, there was 1 guy who clearly didn't understand header files and was labled "Mr. Header" for almost a year. After the first 1 week of taunts by his peers, he quickly learned when and how to avoid putting too many header files into his code.

Other code issues were discovered and learned by the entire team. We didn't hide errors, we published them within the team and never told management anything about who caused what to happen.

Coding 101 (4, Insightful)

Tom (822) | more than 7 years ago | (#17506652)

We all know the answer if we've studied computer science. The problem is that the answer is boring, lots of work and totally non-hip.

It's specifications, pre- and post-conditions, all that "theoretical bullshit" we learned in university. It's just that writing code that way is very un-exciting, and that's a vast understatement.

old versions of purify (2, Interesting)

joss (1346) | more than 7 years ago | (#17506692)

Helped a lot for this kind of thing. The tool went downhill quite
a long way but its still useful. Electric fence helps too.
Then a lot of old fashioned software engineering.. use raw arrays
as little as possible, add bounds checking to std::vector [] if you
feel inclined, use gprof to identify any code not being excercised
by your unit tests [you do have unit tests, right]. Lastly, actually
read the darn code and make sure anytime you are using raw arrays
you check the size.

Half a solution (3, Funny)

DoofusOfDeath (636671) | more than 7 years ago | (#17506712)

How Do You Know Your Code is Secure?

Make it part of the critical path in music DRM. Then you know it's not secure.

Not sure about the flip-side, though.

If it compiles... (2, Funny)

GroovBird (209391) | more than 7 years ago | (#17506750)

...you can ship it.

It's that simple!

Is it all about buffer overflows ?! (1)

neurorebel (914891) | more than 7 years ago | (#17506784)

How about user/password management ? No matter how your shiny GC collects the garbage you create on memory... You still have the opportunity to make a mess out of faulty authentication schemes or stupid array usage... Besides even though your code is secure, the environment on which it runs may be configured/set up/run by a stupid administrator with all those bullshit certificates in his back. Does it sound familiar ??

Meh (1)

Rob T Firefly (844560) | more than 7 years ago | (#17506874)

Who needs security? Thanks to the DMCA, all I have to do is keep my code proprietary. Then it's illegal for people to hax my code, so it won't happen!

SPARK (5, Insightful)

Rod Chapman (781256) | more than 7 years ago | (#17506882)

For high-integrity stuff, we use SPARK (http://www.sparkada.com/ [sparkada.com] ) - a design-by-contract subset of Ada95 that is entirely designed-from-scratch for verification purposes.
The verification system implements Hoare-logic and is supported by a theorem prover. Buffer Overflow is only one of many basic correctness properties that can be verified. Properties that can be verified are only limited to what can be expressed as an assertion in first-order logic.
SPARK is a small language (compared to C++ or Java...) but the depth and soundness of verification is unmatched by anything like FindBugs, SPLINT, ESC/Java or any of the other tools for the "popular" languages.
(If you don't know or care what soundness is in the context of static analysis, then you've probably missed the point of this post... :-) )
- Rod Chapman, Praxis

misspellings (1)

capoccia (312092) | more than 7 years ago | (#17506898)

"Marucs Ranum notes taht 'It's really hard to tell the difference between a program that works and one that just appears to work.'
it's hard to tell the difference between being human, and appearing to be human... oh, wait -- there's a misspelling. i think he's real... or maybe just a robot with bad programming.
Load More Comments
Slashdot Login

Need an Account?

Forgot your password?