For a toy example, imagine the format says [number of bytes to come] [the bytes]. Allocate an array with the specified size and then copy the rest of the message into it. Right?
Now you’ve got a remote buffer overflow. How about [start sentinel byte] [up to N data bytes] [end sentinel byte]? Just put more than the allowed bytes before the end sentinel.
Unless a format is designed to facilitate secure implementation (which would include being very simple), there are going to be at least a few vulnerable implementations. Is it a backdoor? Read the patch yourself, decide whether the original authors and reviewers knew what they were doing.
Well then you're doing it wrong. You copy [number of bytes to come] bytes, not [rest of message] size bytes, only once you've validated that [rest of message size] is not too large to begin with. That is a completely toy example. A decent programmer would never trust the remote end to actually just send [number of bytes to come] bytes.
Well, I applaud your optimism, anyways, but programmers of almost any skill level make egregious security mistakes, especially when working on a deadline. Maybe not everyone would make this mistake, but managing trust while writing optimal code is very tricky.
LZO is a fantastic example of a library that had an "obvious" security flaw for many years, with a fairly trivial integer overflow bug, due to how the decoder dealt with the variable length int encoding.
And that kind of attitude is why we still have security bugs.
Absolutely poppycock. We could all program in completely memory safe languages tomorrow with only one signed integer type and crap programmers would still find a way to write security holes into their programs.
I'm in no way condoning the use of C/C++ forever, the writing is on the wall for those languages, as much as I love them.
But programmers have to learn first and foremost to take responsibility; if you're writing code that runs with elevated privileges then BE CAREFUL. If you're writing code that is reading data from an untrusted source (disk, network or otherwise) then BE CAREFUL. Hell, being careful even if you think the data source can be trusted is a good starting point - defensive programming 101.
We cannot blame our tools forever, but we can improve them.
And there are those working on mitigating some of the worst issues with those languages, maybe someday they will bear practical fruit as well.
If you know your tools there is less risk that you produce security bugs. You know the sideeffects of all the commands and functions. If you use a black box and trust it fully, you will (unknowingly) find ways to make new security holes noone ever thought of before.
I'm not saying that we should not innovate, just that we should not rush head first into the blue sky thinking everything is fine just because we use the new shiny thing where we can't make bugs ever.
In "From the Earth to the Moon" [1], someone explains that the main problem of the Apollo 1 fire was that nobody thought to label that test "hazardous". Sitting on the ground was supposed to be safe.
We should expect perfection when writing C code, but we should also be clear that writing C is a hazardous activity, and not to be taken lightly. My surgeon is a human being, so I don't expect him to never make a mistake, but he's also a skilled and careful professional, and I do expect him to never make a 101-level mistake while holding a scalpel.
So why doesn't everyone go with the better tool? Large problem is that experienced programmers encourages new programmers to use the older & less secure tools. I guess in a way to stay relevant.
Just this past week it has been an article about C programming almost everyday on the top list here at Hacker News.
I agree in general, but not necessarily if the "better tool" doesn't run on or generate code for your target platform, or doesn't meet your performance requirements, or memory constraints, or the requirements to interface with other languages via a common ABI etc, etc etc.
And, in those situations, you need to BE CAREFUL.
> Large problem is that experienced programmers encourages new programmers to use the older & less secure tools. I guess in a way to stay relevant.
Oh I get it. Blame the older generation who wrote the platforms & tools that gave you a job in the first place. If that doesn't work, blame the tools. Blame anything but yourself for writing shit code. I see.
We have newer languages, but also a lots of languages have gotten better to interface lower level libraries.
Experienced programmers can be a huge asset, but at the same time a curse, there is no contradiction there. And I'm not arguing for a revolution to throw out all of what has been gained in software, I just say that new projects should to leave the old tools behind.
I am of course also guilty for proselytizing bad ideas & writing bad code.
Sure, why not. Almost all of them write "shit code", by your definition.
https://www.cvedetails.com/vulnerability-list/vendor_id-72/p...
https://www.cvedetails.com/vulnerability-list/vendor_id-33/p...
https://www.cvedetails.com/vulnerability-list/vendor_id-97/p...
Plenty of people claim they can write secure C code, and 99% of them are rookies that have learned the rules but not their own limitations, IMO.
- Perform periodic external security reviews
- Use fuzzing for all uncontrolled/user-inputs
- Use static analysis tools
- Maintain a security bounty program
- Send your employees to security training
- Use a memory safe programming language
But if you need all that to spot the obvious issue in the OP's original specification ... then wow.
Also, checklists. Checklists are good. And an inventory of used components, and their versions. (This makes it easy to do a CVE review from time to time, and then to automate the review eventually, so only the list maintenance will remain manual.)
Defense in depth, but not through obscurity. (There usually are low hanging fruits. Enforce use of password managers, invest in centralized credential storage, don't overdo password expiration and 2FA. Security training is also a good idea, but the real goal is to nurture a security aware office/team culture.)
Social engineering [or just plain old laziness] is still a serious threat.
Timeboxing. Set aside 1-2 days every month to work on meaningful security-conscious goals. So try to upgrade to lay the fundamentals for that library upgrade that is overdue for years, try to make systems reproducible (also good for DR), try to add a few simple validations here and there against local file inclusion (or whatever comes up during the month, or during the checklist review).
Also, accepting that maintaining network facing systems have an inherent ongoing cost. (Unless you want your iToaster to eventually end up as part of a botnet.) Sometimes we have to let things go, accept that some business models (or hobbyist projects) are not worth it to do sanely and securely.
That's not going to happen as long as all our licenses include something like "This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
> if you're writing code that ...
Being careful (I'd add: learn how to be careful) is a good platitude, though might as well just say so without the ifs. Especially for open source, you don't always know the context in which your program will run. There's responsibility of the dev, but also responsibility of downstream users. When companies wrap a cli program behind a web server they're asking for trouble.
Not failing on the data parse example above is expected of competent C/C++ programmers. I do think these days if you're going to use such languages outside of well-defined low-security-impact targets like non-networked games you're morally obligated to be better than competent. I can't change what exists though.
Managed languages help so much. I do think Java achieved its mission statement of dragging many C++ programmers halfway to Common Lisp (if halfway is a GC) and preventing many security bugs, but if more people were to go all the way, I think Naggum points to a big obstacle I don't know how to overcome: "What has to go before Common Lisp will conquer the world is the belief that passing unadorned machine words around is safe just because some external force has «approved» the exchange of those machine words."
You might want to Google for ImageTragick. Or heartbleed. Or shell shock. Or Java deserialization. Or flash. But please, tell me more about what a decent programmer would never do.
This might be shocking to a flawless supercomputer AI such as yourself but humans make mistakes.
> imagine the format says [number of bytes to come] [the bytes]. Allocate an array with the specified size and then copy the rest of the message into it. Right?
If your client came to you and said that was the specification, you'd be negligent to fail to point out the obvious flaw with the logic, wouldn't you?
"Unfortunately, the OpenSSL basket was being watched somewhat less than very carefully. Yeah, it has bugs, but surely somebody else will fix them. And worst case scenario, since everybody uses the same library, everybody will be affected by the bugs. Nobody wants to be alone".
https://www.openbsd.org/papers/eurobsdcon2014-libressl.html
So I'm pretty sure the one example you have picked here reinforces my point.
Is that real world enough for you?
But you go ahead and believe it's because of dumb luck if you like.
> we strive everyday to provide new mitigations and defense in depth to prevent its exploitation.
I'm fairly confident that even if you didn't do that it wouldn't make much of a difference, because the likelihood of anyone attempting to exploit your particular niche program are quite low.
> But you go ahead and believe it's because of dumb luck if you like.
I didn't say it was dumb luck. The fact of the matter is that most software isn't hardened in the way you describe, for simple economical reasons.
If you honestly think that emergency services infrastructure is less of a valuable target to a rogue operator than Internet Widgets Inc. or whatever then I think we are done here for now.
This is all a huge over-reaction to my initial point which was; the format that the OP proposed was busted, and any good C/C++ programmer should notice that immediately rather than implement it blindly. If they can't do that then, yes, definitely stick to a managed language. Which I agree is good advice anyway.
Thank you and have a nice day.
It is in your original statement (abbreviated):
If there were easily exploited buffer overflow in <our program>, ambulances and fire engines <for our customers> would never be called to their destinations nor arrive on time.
One doesn't follow from the other. Your statement implies there are bad actors in existence that would actually exploit such flaws in order to disrupt the service. That may or may not be true, therefore it does not follow.
> The previous poster purported that I mustn't have much "real world" experience in coding, and I responded that I and my team wouldn't be entrusted to successfully maintain a program and network that coordinates emergency services first responders over a large land mass and number of people if that was the case.
That's not what I actually replied to, but it's also a non-sequitur. It would be entirely plausible that you could be a reckless band of cowboy coders that happens to be able to produce a working product that is nevertheless full of theoretically exploitable flaws that just happen to not get exploited, because nobody cares. Also, whoever "entrusted" you may themselves be entirely reckless or incompetent.
I'm not saying that any of this is the case, I'm simply saying you can't logically deduce one from the other. Therefore it doesn't really work as an argument.
Rubbish. If the service in question was directly accessible from a public network and its source code known and published, it would be attacked in less than 5 minutes. That is the assumption that causes millions of dollars to be spent on securing the application and the environment every year. We are not prepared to take that risk, and we secure appropriately and expensively.
> Also, whoever "entrusted" you may themselves be entirely reckless or incompetent.
That is how employment works in the wider world of Internet Widgets etc. but not in critical government regulated infrastructure like emergency services.
Yes we are unable to prove 100% that the application has no externally exploitable bugs, despite our best efforts, so we don't claim that it is and go and make it accessible to untrusted sources of input.
You just keep going with the non-sequitur, but now you're also moving the goalpost. Your original statement didn't contain anything about "directly accessible from a public network" (which I assume isn't the case) or "source code known and published" (which you said wasn't the case).
And it is still a non-sequitur. Why would anybody expend non-trivial resources to find exploitable flaw in an open-source codebase to actually bring down emergency service? There's no reasonable way to profit from that. If you're some foreign hacker, you might want to find the exploit, but you wouldn't attack right away. Again, I'm not saying nobody would possibly do it, but one does not automatically follow from the other.
Heartbleed really is the best example on how a critical piece of software infrastructure (including a lot of government regulated infrastructure) had a publicly visible flaw that went undetected (and presumably unexploited) for several years.
> That is how employment works in the wider world of Internet Widgets etc. but not in critical government regulated infrastructure like emergency services.
I don't know man, I'm here arguing with this guy who doesn't seem to grasp a basic concept in logical reasoning, yet he's working on critical government infrastructure.
It's already been discussed in this thread how old OpenSSL is - it dates back to 1998 when the risk of buffer overflows was not as well understood or publicised as it is now. It has also been addressed that code audits of OpenSSL were done as a result, which has lead to both forks and patches.
In the context of the new, one liner graphics format proposed by the OP in 2019 that had an obvious bug written straight into its specification, this thread has now reached absurd levels.
> Again, I'm not saying nobody would possibly do it, but one does not automatically follow from the other.
Ok. I'll tell my customer we don't need all the firewalls, IDS, code inspection, risk assessment and hardening because zeroname on HN told me it was OK.
> I don't know man, I'm here arguing with this guy who doesn't seem to grasp a basic concept in logical reasoning, yet he's working on critical government infrastructure.
I'm not at all offended by your ridiculous insults, I feel rewarded every day that my team and I are working on something worthwhile, and also the white-knuckled fear on that goes with it on occasion when we worry whether we've missed something or not.
Let's just both be thankful you don't live in an area where my team provides emergency services then.
Again, have a nice day, "man".
That's completely irrelevant to the point I am making. I'm using it as a counterexample to your reasoning that if code for (your) critical infrastructure was published, any obvious flaws in it would almost immediately be discovered and exploited. That's completely orthogonal to how old or poorly written the codebase is.
> Ok. I'll tell my customer we don't need all the firewalls, IDS, code inspection, risk assessment and hardening because zeroname on HN told me it was OK.
Well, I didn't. You're clearly not only unwilling to engage in logical reasoning, you also seem to lack basic reading comprehension.
> I'm not at all offended by your ridiculous insults...
I don't mean it as an insult, but I'm really losing my patience here. Your ego is so tied to being right that you can't admit to having made a little logical blunder there. Logical fallacies are actually really common, there's no shame in them. In fact, I'm prone to arguing the same If-this-then-that fallacies myself.
Either way, if you really care to be right, it doesn't matter what your job is or who gave it to you and how smart and diligent your team is. You just have to get your propositional logic correct.
Simple example:
False: If I leave the door unlocked, people will come and steal my stuff. (Non Sequitur)
True: If I leave the door unlocked, a thief will have it much easier to come in and steal my stuff.
The Morris worm was released in 1988.
People are prone to make logical errors and to overlook stuff, even when they are aware of the risks. Thinking is hard, and every little bit of help is useful, either from peers or from tools.
Do not take what zeroname wrote as an insult. He simply pointed out the mistake you made (indeed, it does not follow what you wrote - it may be possible, and probable, but it does not follow automatically).
You can look at all this as a peer review, just not for code, but for thought/logic argumentation.
- that is not simply pointing out mistakes. That's ridiculous insults that have no place on HN. I didn't think zeroname came off better in that exchange at all, in terms of who was trying to communicate, not just appear superior. There was a crossed wire, and condescending lectures in basic logic mixed with insults did not help.
And PHP was seen as harmless fun.
And malware was thought of as boot sector viruses and even though the first worm (1988, the Morris) worked exactly like what people are harping about (buffer overrun), no one cared, because C++ was slow to compile, and managed runtimes are evil.
And still no one cares. It takes some competence to stop using C, but it's easier to simply shout at those who point out the obvious.
And when someone brings out the good old Therac-25 everyone starts to fall silent. (Even if healthcare accreditation is very expensive, it's expensive exactly because the whole IT field is still full of unverifiable code.)
Yes it might have been easy to get away with writing the OP's faulty specification into code back then. After 25 years of people screaming about the dangers of buffer/integer overflows, it's very hard for me to think that a serious C/C++ programmer could look at that specification and not see the issue before blindly committing it to code today. I suppose it could happen.
OpenSSL (which everyone else here is crying about as an example) is also over 20 years old.
> And still no one cares. It takes some competence to stop using C, but it's easier to simply shout at those who point out the obvious.
Well imagine trying to rewrite the Linux kernel today in a memory safe language, without losing any support for any of the current target architectures. Or NetBSD even more so for that matter. Nobody has convinced me it could be done, and as of yet, it hasn't been.
Throwing away C and C++ for good is fine - if you don't want to do much in the way right now of embedded programming, or working with sophisticated games engines (eg. UE4), just for fun.
If you're not confident of the quality of the code, then maybe don't deliver it to for all and sundry saying its fit for purpose. And if you are confident, then check it again. That's all I'm saying.
Agreed. And even though it could be done, but it'd of course came at an enormous cost to the current pace of driver and other updates.
Google is trying something with Fuchsia though.
And there are experiments similar to how Linux itself got started. (Redox OS comes to mind.)
Aware of both of these, but yeah, wake me up when either are close to being capable of being even a niche competitor, for example, as complete and accessible as Haiku currently is.
Most of the BSD's didn't have decent working SMP for a period longer than that either.
I think it's kind of sad that it takes a company the size of Google to create something like Fuchsia, which we can't be sure will ever see the light of day for most users, even given the vast pools of code available in Linux and BSD they could reference.
Hardware has grown exponentially in complexity since Linux was initially developed of course, which makes the job of writing a new OS much tougher. But you could probably find 20-30 different hobby OS's over on osdev.org that are more complete and accessible for the end user than Fuschsia or Redox right now, even if they are just more boring POSIX clones.
Though, interestingly hardware also got a lot smarter (because usually they have some kind of microprocessor and RTOS on them), so in theory interfacing with it should be more easier. (Serial buses, simple enumerate, simple addressing, we have a lot of good abstractions, no need to fiddle with registers, just use a PCI-E, DMA, I2C library.)
But of course at the same time just supporting these smart standards is hard (because initialization of things is not trivial, even just getting DDR RAM to work requires tinkering with MSRs, and ACPI is its own special hell).
Er ... what? Where are you getting this information? Haiku has been in development since 2002, and has SMP support since ... 2003/2004?
NUMA support is a little shaky, but I know users who have run Haiku on 32-core Ryzens with no issues. So we definitely have SMP support.
Now re-reading it, the article clearly states that development started in 2001, and that it has rudimentary SMP support.
Maybe the phrase "a decent programmer would never" unfairly assigns blame to an individual's skill, but I think it would be fair to say that the programmers who designed and implemented these bugs were not doing decent work on the day that they made these mistakes.
If our standards for C programmers don't include bounds checking of array access, what exactly do they include?
https://news.ycombinator.com/item?id=19138602
If we could get rid of that 70% that would be great, but it still leaves programmers doing other stupid shit in the other 30% of cases.Decent programmers also try to err on the side of safety, use the right tool for the job, and so on. And writing parsers should not be done directly, instead the parser code should be generated by a battle tested library/framework. (Or via using parser combinators, etc.)