Curl’s backdoor threat
daniel.haxx.se
daniel.haxx.se
Unfortunately, most of the language- and environment-specific package managers have pretty much ignored that issue. There's too often no way to verify that the code you just downloaded hasn't been tampered with. Heck, half the time you can't even be sure it's a version that's compatible with everything else you have. It's a total farce.
Software distribution is too important, security-wise and other-wise, to leave it to dilettantes as an afterthought to other things they were doing. Others should follow curl's example, instead of just dumping code into an insecure repo or (even worse) putting it on GitHub with a README that tells users to sudo the install script.
The code is what we are trying to verify, not that someone claiming to be user x published it.
Most trust on a typical Ubuntu install, for example, is still chained back to an TLS download of an ISO (or maybe torrent file). That bootstraps your repo public keys.
https://tutorials.ubuntu.com/tutorial/tutorial-how-to-verify...
You can check the sums over time and acquire them using multiple connections to verify they are all the same to gain a higher level of confidence, but this is actually annoying for someone with a high level of technical skill and basically impossible for most people. I only do this for things that require the highest levels of operational security, like, say, if I am setting up a system to sign certificates in a CA or something.
A slightly easier approach is to strip down your CAs to a bare minimum in your browser config, and double check the certificates being presented on TLS download sites. You can still be owned by a MiTM if the CAs actively collude with a nation state and have given them signing keys, but... there isn't much to do about that. The options really aren't that great in terms of really verifying things.
They do.
https://github.com/blog/1068-public-key-security-vulnerabili...
Commit signing can help to mitigate that.[0] Note that GitHub now offers the ability to add your GPG public key to your profile and show whether a commit is signed with that key or not. I find this more dangerous than useful: if an attacker compromises the account and adds his/her key, and adds a malicious commit, GitHub would show it as verified.
I can see requiring every commit on the primary repo to be signed, but it's a larger nightmare to accept pull requests from forks if they are also forced to sign their commits.
What's ultimately important for trust is that the maintainers (or whomever you are to trust) sign commits. They may choose to pass this responsibility down the line a bit (e.g. how Linus has his "lieutenants"), but if some random contributor does or does not sign a commit, do we care? Are they in the maintainers' web of trust? What benefit does verifying their identity actually have with respect for the project?
So in that case, a maintainer may decide to just review the patches and sign the merge commit.
That contributor may want to _assert_ their identity---e.g. have their signed commit committed to the repository to show that they actually did that work---but that's a different issue.
If I have distro maintainers sign the packages they build, then I can avoid keeping their private keys on the package servers. That's cool, and it can make it harder for an attacker to ship evil bits. But there's a bootstrapping problem: How did the user's machine originally learn the packagers' public keys, to know what signatures to look for? It got the public keys that were baked into the installation disk, and that disk was almost certainly downloaded from an HTTPS website, without checking any other signatures. (Or even _with_ extra signatures, if the key fingerprint for those was hosted on the same server.) Compromising the server still lets you own all the users.
At the end of the day, running a whole system of offline package signing and key distribution buys you a kind of subtle difference in security: If an attacker owns the package/image server, they can own machines that are set up after that point, but not machines that were set up before. Is that difference worth the effort of maintaining a system like that? Maybe! But it's not really the difference between "secure" and "insecure".
With a package signing key, it can be held on a more easily secured system, and is therefore less likely to be compromised.
This is something Windows seems to have got right, with Authenticode and Catalog signatures - it's easy to verify who signed a file, and if it's been tampered with.
What options are there for this on Linux? File integrity monitoring (Tripwire, Ionx Verisys, whatever) will tell you when files change, but that doesn't help to know if a file is in a 'trusted' state.
You have RPM signatures and the like to verify the authenticity of packages at the point of installation. If you mean detection of changes to files after the installation, then we need to talk about what it is you're trying to protect against.
If you want to detect accidental corruption (e.g. clobbering of distro-provided files through pip or 'make install'), the built-in verification functionality of RPM (rpm -V) or dpkg (dpkg -V) does a good job at that.
Malicious modification is something else entirely. Your system files are only modifiable by root. So if an attacker was able to mess with these files, any tool intended to detect that situation might've also been messed with so that it always gives the "everything is fine" assessment.
You can tackle this problem using special hardware. Or do the assessment on a different system using a disk snapshot.
The former can be done on Linux using a TPM and the trousers framework. If the protected set of software changes frequently, it's a pain in the ass to manage though.
That's as clear a statement of security theater as I can think of.
If you make it cumbersome to build packages for a distro and get them accepted into that distro, your distro then ends up with language-level package managers doing an end-run around that "secure" package-managing apparatus.
Meanwhile, non-dilettante security experts are sandboxing the code that they aren't able to verify. Chrome/Chromium does that. Firefox is doing that more and more. What are the cumbersome-package-having distros doing?
That's one of the reasons I'm skeptical of the Ethereum smart-contract concept. In theory it works, but in practice I'm not sure at all. The DAO heist was one early example of security bugs in smart contracts, but I fear they will become more common when malware developers turn to "contract-engineering".
[1] https://superuser.com/questions/301646/linux-keylogger-witho...
[2] https://www.schneier.com/blog/archives/2009/10/evil_maid_att...
[1] https://arstechnica.com/information-technology/2013/10/meet-...
The tinfoil hats would have loved to say "told you so", but even they had not predicted the true scale of things.
Intel ME is not just some BIOS code, but a separate hardware component that is deeply connected with all CPU actions.
Real tinfoilers have been warning about this since the 80's
OK, makes sense
>looks and feels like the real thing
Not really, because you can't turn off virtualization
To be clear what I mean is, the bios can be made to look and feel like the real bios when in fact it could be a compromised bios which still shows the manufacturers logo, menu options etc etc.
Bottom line is, if someone can make it, someone can modify it.
Only getting a SOIC clip hooked up to something like a RaspberryPi to get a copy of the chip code will you possibly be able to tell otherwise. Something like this might get people pointed in the right direction. http://www.win-raid.com/t58f16-Guide-Recover-from-failed-BIO...
One of the other attributes I have seen with this "suite of malware" is its ability to spread over the USB bus. If hit with it and it stops your usb devices including printers, mouse & keyboard, PS/2 mouse and keyboards still work so you can safely shutdown your machines instead of pressing and holding the power button to force a shutdown which can lose work. Lets face it, when looking at how USB works, its a disaster waiting to be exploited when considering how much attention goes into monitoring ethernet traffic. Having spoken with Tomasz the developer of this tool http://desowin.org/usbpcap/ on windows, you only get what windows will show you, so a separate malicious OS using CPU virtualisation could still interfere with the USB bus.
One file I've isolated when using partedmagic will not display its entire contents in the included opensource hex editor if its accessed using the hex editors file load method, but if you read the block device sector by sector, you can navigate to where the suspect file is stored and then read the entire contents of the suspect file. There seems to be a sort of magic string which prevents further investigation of suspect files including the ability to dd dev zero block devices which is a nuisance.
In all, who ever is behind this is IMO hacking chips so that even if you do a full disk wipe to whatever standard and reinstall the OS, you'll never get rid of it unless you reprogram the chips, it like a complex zero day spread over hardware and software, so in isolation parts look innocent enough but when combined becomes malicious. Its very very clever whoever is behind it and theres not many entities with the resources or knowledge to pull something like this off IMO.
Plus when considering the NDA's that exist with chip/cpu/hardware manufacturers, the knowledge at this level is even more restricted.
If you want to get lucky, dont always follow industry standard practices, its sometimes the only way to spot the anomalies.
It's definitely possible to build a full virtualization environment that feels pretty seamless, but that was only a portion of the claim.
As speakers can be used as microphones (technology is essentially the same just different ohms and materials used for the cone) and modern motherboards can detect when a 3.5mm jack plug is plugged into a headphone socket, it might be possible to have the speakers acting as a microphone in some situations. Its something I'm still looking into, but I have noticed the some DJ mixes on Youtube will play up ie going quiet when you have headphone's plugged in but not when using built in speakers like those found on a laptop. You can reset the mix going quiet by unplugging the 3.5mm stereo jack, now whether this is some sort of DRM technology being used as some of the DJ mixes will be illegal copies uploaded to Youtube, I dont know yet just like I dont know if these are related or separate events to BadBios. Its not unheard of big corps to employ methods to disrupt illegal copies of music & films, the Sony rootkit on some of their music CD's is one such example of big corporations hacking their customers. https://en.wikipedia.org/wiki/Sony_BMG_copy_protection_rootk...
But don't you need something on the other side to receive and decode the data being sent? What's the BadBIOS story for how the infection initially happened?
(Is the assertion that something along the lines of Intel ME is already listening for control instructions over ultrasound?)
From there, it's turtles all the way down; you "only" need to deliver an ulterior, possibly tailored, payload from any of the several methods described in this thread.
The following part of this classic (2009) article caught my eye:
> Symantec’s CTO Mark Bregman was recently advised by "three-letter agencies in the US Government" to use separate laptop and mobile device when traveling to China, citing potential hardware-based compromise.
It is strange how much this changed after the Snowden relevations. In Europe, now you get that same advice when travelling to the US.
Even US companies advise their overseas employees to be careful and thoughtful as to what you bring with you, b/c of what can happen at the border: https://github.com/basecamp/handbook/blob/master/internation...
But the theory is written into real programs by humans, who make mistakes. The math is unassailable until, oops, it isn't, because someone forgot a bounds check!
This whole "move fast and break things" philosophy should be unacceptable, if you want people to trust in your new cryptocurrency/voting machine/etc, but try telling your investors that it'll take 5 years to develop the software instead of 5 weeks to "a first prototype" whose bugs and bad design decisions will haunt you forever...
2) Extraction is not the only approach to verifying software with Coq (see Verifiable C, or Bedrock). In other proof assistants, e.g., in Isabelle or HOL extraction isn't even available and so other approaches are common. For a nice example look at the bootstrapping process of CakeML (https://cakeml.org/).
3) Even if it wasn't, the point is that the trusted base with verified software is tiny compared to anything else that people are actually using. "It's not perfect" is not an excuse if it is basically perfect in practice. See the Csmith paper ("Finding and Understanding Bugs in C Compilers", https://embed.cs.utah.edu/csmith/) and what they had to say about CompCert.
Doesn't matter on windows. The binaries are authenticode signed.
While technically true, yet, you are comparing air travel safety with motorbike safety.
Suppose you are a medium-sized IT company (large enough to be a valuable target, but not google-large where you can employ a really good security team that knows their hardware in an out). And then think of all the hardware you buy from all different vendors and manufacturers, and make a list of those that could totally own you if there was a backdoor. What can you even do except shudder in horror?
In safe languages, backdoors must be far more explicit, so we close off the likely scenario posited here.
C may be awful in some respects but for quality it's going to be hard to beat 15 years of peer review with any new languages cool features.
For scenario 1, all that functionality has to be duplicated, including "defects". Are you sure that the functionality is 100% there or did you miss any use cases? Decision for leaving it.
Scenario 2, new widget. Most likely, coding in SPIFFY will be a better choice.
Slowly expand the percentage of traffic coverable by the new safe code.
The 80 percent case can be written and coded in a small amount of time. In curls example, it is fetching a file over http 1.1 using an encoding, possibly following some redirects. Then post and put requests, then chunked uploads, downloads, then?
Need gopher and ftp? Run the old codepath.
These two terms are far from identical.
You might be masquerading your conservative approach to new languages by hiding behind "C is mature". No it's not. Right now somebody on the planet is introducing a buffer overflow without knowing it, while coding in the "mature C".
Get real already, please. It's high time.
Random example: I dislike Go's error handling but the explicit nature of it has saved me from working half-asleep 50+ times already. Another one: one meager if/else in a supervised Elixir worker saved a server from infinite repeating of a bugged task that would otherwise keep crashing forever. There are others, lots of them. I am sure people can give plenty of examples for Rust as well.
Sorry.
I do believe most of Linux userland has to be rewritten though. Be it Go, Rust, Nim, D, doesn't matter much as long as it's a memory-safe language.
Why? I'm sympathetic to the argument that 2017 computing shouldn't be on the basis of 1970s UNIX limitations and mindset, but changing that would require a lot more than just rewriting the user land applications, and would require a bigger re-think.
But assuming that the shell's functionality is OK as it is, what's to be gained in a re-write?
In any case, I feel (and I don't have tens of facts, I admit) we're dragged by the past for far too long. Others have documented their gripes with the current incarnation of Ops / sysadmin problems much better than I could. Here in HN (but I think years ago).
We need to find a way to extend sandboxing to dynamic libraries in a way that is descriptive at the ops level. Something that can be applied a system management rule so that it can be distributed to end users now and not wait for the safe versions to get disseminated.
With C, there are several routes to bootstrapping your compiler of choice – there are countless implementations that can be used as intermediates (both closed and open source, for all sorts of architectures, with decades worth of binaries and sources available), and diverse double compilation is a thing.
Rust? Unless you want to go back to the original OCaml version and build hundreds of snapshots (and providing you actually trust your OCaml environment), you've got no choice but to put your faith in a blob.
I'm not against Rust as a language, but it seems counterintuitive to use a language that only has one proper implementation and requires a blob to bootstrap, as a defense against backdoors.
One kind of compiler should be like current compilers, with a focus on speed, resource consumption, optimization. Most actual commercial applications would use this compiler, because it provides the fastest and most efficient software.
But beyond that, it might be beneficial to implement compilers with a focus on simplicity and a minimum of dependencies. For example, implement a compiler on an ARM CPU in assembler. The translation step to run this code on an actual CPU is too small and simple to be backdoor'd, and the CPU should be simple or even open.
Such a simplicity oriented compiler could provide a source of truth, if all components are too simple to backdoor'd.
FTFY.
I'm rapidly thinking of safe languages in the same way as "nothing up my sleeve numbers". Code written in a safe language is much easier to verify that there aren't any intentional or unintentional backdoors put in by the author.
Evil organisations and/or big government agencies are probably working on finding vulnerabilities and using them without reporting them.
That sounds more efficient and impossible to spot or prove, than trying to implement backdoors directly.
That said there are a number of possible mitigations and the fact that they're not more widespread is, to me, an indication that people who rely on software don't think that this threat is worth the trade-off of the additional costs or time that mitigating it would take.
For example :-
- Requiring packages signed by the developers for all package managers (e.g. https://theupdateframework.github.io/ ) . This would help mitigate the risk of a compromise on the package managers hosting, but we see many large software repositories that either don't have the concept or don't make much use of it (e.g. npm, rubygems, pip)
- Having some form of third party review of software packages. It would be possible for popular packages like curl to get regular security reviews by independent bodies. That doesn't completely remove the problem of backdoors but it makes it harder for one to go undetected. This one has obvious costs both in financial terms and also in terms of delaying new releases of those packages while reviews are done. There are some things which act a bit like this (e.g. bug bounty programmes) but they're not uniform or regular.
- Liability for insecure software. Really only applies to commercial software, but at the moment there doesn't seem to be much in the way of liability for companies having insecure software, which in turn reduces their incentives to spend money addressing the problem.
I'm sure a load of commercial software includes curl or libcurl, but if there was a backdoor in it that affected that sofware, I don't think the companies would have any liability for it at the moment, so there's no incentive for them to spend money preventing it.
The next day, I was due to meet a developer from a vendor organisation I'd been working with, and he came and found me during the curl talk Daniel was giving. Because the talk was ongoing, I didn't really get a chance to say hello to him or anything.
Cue the Q&A section. My vendor contact sticks his hand up, and is the first person to be picked to ask a question. His question "Have you put any backdoors in curl?".
You couldn't make it up.
[edit] I can't spell "Daniel" :(
The thing is, one can write memory safe code in C. The problem is the difficulty in verifying it is memory safe.
I've opined before that this is why, soon, people will demand that internet facing code be developed with a memory safe language.
EDIT: typos
The Core Guidelines have been in development for a long time now; and they do only catch a subset of issues. I'm all in favor of making languages safer overall though!
For applications that demand both maximum speed as well as maximum security, the best solution is probably something like a C compiler that requires the code to be accompanied by formal proofs of defined behavior. Even this will necessarily sacrifice speed in a theoretical sense, because there are certain problems for which the fastest solution is safe but can't be proven safe within (PA/ZF/ZFC/insert any consistent foundation of mathematics you like).
Eventually we'll have people writing fast programs and proving their soundness using large cardinal axioms which might or might not actually be true. Then someday one of those large cardinal axioms will turn out to be inconsistent [1] and suddenly some "proven" code will be proven no more.
[1] https://en.wikipedia.org/wiki/Kunen%27s_inconsistency_theore...
A contrived example: there are certain large cardinal axioms that imply the consistency of ZFC. Thus ZFC cannot prove those axioms unless ZFC is inconsistent (Godel's incompleteness theorem). Consider the following problem: "If ZFC can prove 1=0 in n steps, output 1. Else, output 0." A naive solution would brute-force search all ZFC-proofs of length n. A faster solution would be: "Ignore n and immediately output 0." This is correct, because ZFC never proves 1=0. You could formally verify the correctness by using certain large cardinal axioms, but not using raw ZFC.
One can generate safe C code. We have ample evidence that a human being can't sit down and write it.
http://delivery.acm.org/10.1145/360000/358210/reflections.pd...
[0]: https://www.ece.cmu.edu/~ganger/712.fall02/papers/p761-thomp...
Daemon had me hooked, it's great when an actual techie does sci-fi.
I don't believe that's quite true. Anyone can sign a curl release, so can I. It's just that Daniel's key being used to sign a release of curl carries the trust that this is legitimate. If he were to pass away or be somehow incapacitated, another curl maintainer could start signing the releases.
It sucks to think about it, but I'm glad that I've set up Gmail's inactive account manager this way.
Big open-source projects have plenty of meatspace to draw on. It's the little projects that 'come from somewhere' that actually only have one or two people 'in the know' that are the ones at risk.
A good example is glibc; several years back, a huge number of people were using the eglibc fork, not because glibc upstream (Ulrich Drepper) stopped being able to do releases, but simply because he was refusing patches for architectures he didn't like and other similar changes. Very few end users even noticed that they weren't using "real" glibc. (Ulrich has now stepped down and the eglibc changes have been merged back in.)
I don't mean a bug like heartbleed, but an actual intentional backdoor.
(Reflections on Trusting Trust)
The dissertation likely addresses all your concerns. Sticking with the Basic example, say you wanted to see if tcc was vulnerable, but you don't trust gcc, icc, borland, clang, etc. either as compilers to use directly or as compilers to compile your trusted one.. And you don't want to write your own in Java or Python because you don't trust the VMs. Whip out an Altair BASIC binary from the 70s and write your compiler with that, just enough to compile tcc. Perform DCC. If the tcc source does not correspond with its binary, you'll know.
Nip this entire discussion in the bud; just use a deterministic build process for any binaries you release. Like Gitian: https://gitian.org
I implemented this for Zcash (see https://z.cash/blog/deterministic-builds.html), more software projects should be doing this in general.
A modern idiom is "curl https://$THING/ | sudo /bin/bash "
And the arguments around it being secure because it's https...
"Additionally, I’m a Swede living in Sweden. The American organizations cannot legally force me to backdoor anything, and the Swedish versions of those secret organizations don’t have the legal rights to do so either (caveat: I’m not a lawyer). So, the real threat is not by legal means."
Considering how well Assange's things turned out with Sweden, that makes me wonder. Of course he is Australian, so there is a big difference.
Security is a matter of layers, there is not one layer that fixes all.
The argument that it would probably take too much code and would be too obvious doesn't seem solid. I'm no expert in this area but curl sends data over a network and sometimes runs as part of a larger application. It seems like the big dangerous bits are there and it wouldn't take a major bug to send the wrong thing.
Are there any commercial or non-profit organisations that maintain lists/repos of audited and trusted software with their checksums? It seems like there would a demand for a package manager like that.
I suppose some Linux distros have pretty OK repositories?
I wouldn't trust npm, pip, gem etc. though.
> Or get it from a trusted source that did the review for you.
Incidentally, curl has been reviewed by the Mozilla Secure Open Source project [0], who maintain lists of audits which include checksums within the report. Maybe you're looking for something similar?
In order for this process to be truly secure, every single software version needs to be audited.
You don't have to do a full audit on each version, auditing the deltas should be fairly comprehensive. Now, there could be some malicious code hidden that gets triggered by a begnin change, but otoh, no audit ever will guarantee full security.
That's exactly what someone who has deliberately put a backdoor into curl would say.
Definitely.
The issue here is now, how can we be collectively sure that the code is safe...
> If I had cooperated in adding a backdoor or been threatened to, then I wouldn’t tell you anyway and I’d thus say no to questions about it.