Live data from Hacker News

The Linux Backdoor Attempt of 2003 (2013)

freedom-to-tinker.com

121–130 of 144 posts

Re: The Linux Backdoor Attempt of 2003 (2013)

#121
post #103
post #85

Earlier quoted context omitted.

now I'm wondering if syntax highlighting shouldn't somehow make an assignment inside an if statement (and the variants) a bright red, or something like that.

It should really be forbidden by the compiler these days, or at least a very loud warning.

What about:

while((i = getchar()) != EOF) putchar(i);

This type of thing seems to be "encouraged"...

Re: The Linux Backdoor Attempt of 2003 (2013)

#122
post #117

Earlier quoted context omitted.

GCC warns of assignment in conditional, even without -Wall or -pendantic. I don't know when it started doing that, but it seems like a sore thumb today, different in 2003 maybe?

It only warns if the assignment doesn't have an extra pair of parentheses. These were added in this case, to silence the warning (so the attack would not be noticed). The parentheses are also needed in this case to get the precedence right, but they won't be needed if '==' were written, so anyone coding this by accident would immediately be warned of the mistake.

Oh wow, I didn't know that. Sneaky.

Re: The Linux Backdoor Attempt of 2003 (2013)

#123
post #115
post #81

Earlier quoted context omitted.

Even if you could break SHA1, it's unlikely that your replacement source code would look like it was human-written. Instead, it's going to look like human-written source code containing kilobytes or megabytes of random-looking comments. The comments will only be there to change the hash of the new content back to the hash of the original content. It's not going to be subtle at all.

Why would it require that much data? I always thought you wouldn't need to add or change more bytes than are in the output. Also, git hashes aren't just based on source code. You can add that data anywhere that git uses to generate the hash.

That's true of a CRC code, but hashes are a lot harder to break.

Git hashes each file, and puts those hashes into a tree object, like a directory listing. Then it hashes the trees, recursively back up to the root of the repository. Finally the hash of the root tree is put in the commit object, and the commit object is hashed. Thus the two places you can put additional data to be hashed are the file contents (either in existing files or new files), or in the commit message. You can get a few free bits by adjusting less obvious things like the commit timestamp or the author's email address, but not nearly enough to make your forged commit have the same hash as an existing commit.

Re: The Linux Backdoor Attempt of 2003 (2013)

#124
post #114
post #81

Earlier quoted context omitted.

Even if you could break SHA1, it's unlikely that your replacement source code would look like it was human-written. Instead, it's going to look like human-written source code containing kilobytes or megabytes of random-looking comments. The comments will only be there to change the hash of the new content back to the hash of the original content. It's not going to be subtle at all.

The git hash surely also takes the contents of binary files into account, so I imagine that in any repo that contains non-text files, an attacker would try to hide the garbage inside e.g. some metadata field of an image file.

That's true. PDFs and other document formats are also great because you can include large volumes of data that is never used in the final output.

Re: The Linux Backdoor Attempt of 2003 (2013)

#125
post #95
post #6

Something as important as "uid" should be "const".

There are legitimate reasons to change the uid at runtime. For example, some server software starts as root and then drops to a less-privileged user. Android relies on this too, zygote, the fully-initialized "blank" runtime process, runs as root and gets forked and changes uid to the corresponding unprivileged user whenever an app is launched.

Sure, and I don't disagree that uid might need to change at runtime, but here we're talking about a struct field being const.

Re: The Linux Backdoor Attempt of 2003 (2013)

#126
post #6

Something as important as "uid" should be "const".

I mean... my first reading of that is "what a dumb idea, the reason it isn't const is that there are legit reasons to switch userid". But then I have used exactly this pattern, and it looks something like: struct protected_stuff { int userid; ... }; void set_userid(const struct protected_stuff prot, int newuserid) { struct protected_stuff backdoor = (struct protected_stuff *)prot; backdoor->userid = newuserid; } and…

Yep... there are ways to make it happen.

Re: The Linux Backdoor Attempt of 2003 (2013)

#127
post #105
post #103

Earlier quoted context omitted.

It should really be forbidden by the compiler these days, or at least a very loud warning.

It would break these kinds of constructs, which are common. if ((fd = open(...)) != -1) { /* do something with fd */ } else { perror("open"); } The compiler outputs a warning when you have something like "if (a = b)". If that's what you mean (it sometimes is), you have to write it "if ((a = b))" to silence the warning.

TBF, that doesn't actually work - you have to write:

  int fd; /* fd must be declared in order to be assigned */
  if ((fd = open(...)) != -1) {
      /* do something with fd */
  } else {
      perror("open");
  }
which would be better written as:

  int fd = open(...);
  if (fd != -1) /* etc */
It would be nice for scoping reasons to be able to write something like:

  if ((int fd = open(...)) != -1) /* etc */
but

  if ((int fd == open(...)) != -1) /* etc */
isn't valid code.

Re: The Linux Backdoor Attempt of 2003 (2013)

#128

Earlier quoted context omitted.

:= Still seems easy to overlook at a cursory glance.

What db48x neglected to mention is that some of those languages also featured assignment as strictly a statement; it could not be a subexpression. As in: fun(x := 42); (* syntax error in Pascal *) x := 42; (* OK *) x = 42; (* hopefully a statement with no effect warning *) If assignment is a statement, it's possible to use the same token. Classic BASIC: 10 X = 5 20 IF X = 5 GOTO 10 This doesn't cause the C problem of…

That is true, but has nothing to do with "==" vs "=" vs ":=". You can do:

  func(x = 42); /* syntax error: expression operator expected, got '=' */
  x = 42; /* OK */
  x == 42; /* warning: statement expression has no effect */
just fine if you require "=" to be a statement.

Re: The Linux Backdoor Attempt of 2003 (2013)

#129
post #82

Earlier quoted context omitted.

I can't point to any evidence, but two things to note: A) Even on HN the temptation has come up. e.g. some comments in posts about ransomware make a similar argument for transparently damaging and self-serving actions. Three letter agencies with much more power and ability probably had people making the same arguments. B) The payoff was extremely low compared to the possibilities. Either whomever did this was unaware…

This theory seems so outrageously far fetched to me. Why in the world would a "friendly" intelligence agency sneak a working backdoor into a project to "teach a lesson"?? Here's what our intelligence agencies do when they decide to "teach a lesson"[1]. It doesn't include sneaking working backdoors into software. They do THAT when they plan on using the backdoors. https://www.marketwatch.com/story/nsa-alerts-microsoft…

I'm pretty fine with the script kiddie thesis. But if we go for an intelligence agency, we have to explain why the hack was so.. small. A local privilege escalation that is relatively easy to find* should be of very limited use at best. They(tm) get ability to fake linux kernel source and that's all they do!?

* Even if the linux kernel folks had failed to notice the CVS hack, someone would have eventually diffed the kernel versions and found it. Assigning uid to 0 is rather obvious, and quite a lot of linters warn about assignment in comparison.

But if they had included (for example) some sort of off-by-one buffer overflow, the hack would have been a lot less apparent. Now do that for a remote exploit, and they get way more possibilities.

Re: The Linux Backdoor Attempt of 2003 (2013)

#130
post #74

This is an obvious backdoor attempt, as the code doesn't make sense otherwise. Yet, the attempt was far too unsubtle and underspecific for agencies such as the NSA. The payoff was low compared to the possibilities - local privilege escalations were a dime-a-dozen. Worse, agencies such as the NSA have two missions: offence and defence. Adding in backdoors helps the offensive mission, but hurts the defensive mission, s…

If memory serves me right the CVS bug was originally discovered and exploited by a member of an infamous file sharing site. After descriptions(?) of that bug were leaked in underground circles, an east European hacker wrote up his own exploit for it. This second exploit was eventually traded for hatorihanzo.c, a kernel exploit, which was also a 0-day at the time. The recipient of the hatorihanzo.c then tried to backd…

This is great storytelling, thanks. Maybe worth a letter to 2600 magazine?
Post reply on HN