5

Let’s say I have this kind of code :

// In revision.c
char *path_name(const struct name_path *path, const char *name) // by design, name_path->len is a 32 bits int, but this doesn’t concern name
{
      const struct name_path *p;
      char *n, *m;
      int nlen = strlen(name); // the size is converted to a positive number (the correct size was allocated previously with an unsigned long). I got 705804100
      int len = nlen + 1;

      for (p = path; p; p = p->up) { //loop is skipped (except in another case fixed since 2.7.1)
          if (p->elem_len)
              len += p->elem_len + 1;
      }
      n = xmalloc(len); // if len is negative, it will also be converted to a negative 64 bits integer *(which explains it is normally trying to allocate serveral Pb of ram most of the time)* which will be read as positive after that. // but this isn’t the run case that is interesting here.
      m = n + len - (nlen + 1); // the size of m is lower than name
      strcpy(m, name); // strcpy rely on the null terminating character. The result is written in an unallocated memory from heap. This is the definition of heap overflow enabling server side remote code execution if name[] contains assembly, and have the correct size. This open the way to defeat canaries aslr, and nx combined see http://security.stackexchange.com/q/20497/36301#comment182004_20550
      for (p = path; p; p = p->up) {
          if (p->elem_len) {
              m -= p->elem_len + 1;
              memcpy(m, p->elem, p->elem_len);
              m[p->elem_len] = '/';
          }
      }
      return n;
}

Could there be a case where the system let the overflow happen while keeping the path to remote code execution completely closed ?

A crafted path in a git database (a git tree) should contains binary code for performing the remote code execution. However, a path can’t contains thenulbyte (since it’s used as a delimiter in a git tree).

If a specific case is needed, it’s Ubuntu with linux version <3.16 and all security protections enabled (I mean nx aslr and dep combined but canaries excepted). The architecture is x86_64. libc is an old (but security patched) version of glibc.

Update :

Now, creating a proof should be easier.

user2284570
  • 1,402
  • 1
  • 14
  • 33
  • 1
    In fact there’s some debate about [this](https://bounty.github.com/researchers/ytrezq.html). They state they could have prevented the remote code execution after the overflow, so they a require me a proof of concept they can run in order to update the description. For me it’s obvious as soon as that specific overflow happens, the difficult path to remote code execution is opened. – user2284570 Feb 25 '16 at 20:17

3 Answers3

7

A buffer overflow (of the "write" kind) gives any advantage to an attacker only if the attacker can arrange for the overflow to spill over other bytes that are used for something else. At any time, the process runs in an address space, most of which being unallocated. If the buffer which is overflown is at the end of the address space, or is followed only by unused bytes then an unmapped page, then the overflow won't help the attacker.

I remember a case with the rlogin command-line tool on SunOS 4.1.4 (sparc systems). It was root suid, and you could get it to segfault if the TERM environment variable contained a string longer than 64 characters. However, the overflown buffer was at the very end of the data section, and there was nothing beyond that to overwrite.

Mind, though, that malloc() may use extra bytes before and after each allocated block to keep track of which blocks are allocated. Depending on the implementation of malloc(), modifying these bytes may or may not help the attacker. The bottom-line is that while some buffer overflows cannot be exploited, it is usually very hard to make sure that a buffer overflow cannot be exploited. It is safer to assume that any buffer overflow can lead to drastic consequences, and not allow them to happen at all.

Thomas Pornin
  • 320,799
  • 57
  • 780
  • 949
  • As the fix was pushed into master, the question know include the real code. – user2284570 Feb 25 '16 at 21:53
  • In most cases it will be a lot less work to fix the bug than to figure out whether it can be exploited or not. That is the primary argument for fixing them all. There are exceptions of course, but the exceptions tend to be those cases where it is obvious that the bug is exploitable, and in those cases you also need to fix the bug. If one need more arguments for fixing the bug, then defense-in-depth principles imply that you need to fix bugs even if they are not exploitable. – kasperd Feb 26 '16 at 15:24
  • @kasperd : As GitHub pointed out, I was able to read the process memory because the same code offer a possibility for an underflow *(and in fact I did on their servers)*. But I didn’t what information I could get in the git-upload program. So their were really a bug that needed to be fixed *(please note they don’t pay or react at all if you simply demonstrate a segmentation fault due to a programming error)*. I can exploit it. it’s the matter of finding an already builded generic string for that kind of tipicall buffer overflow *(the same kind as using char`*gets(char *s);`)* – user2284570 Feb 29 '16 at 20:03
  • @kasperd : since writing binary assembly is beyond my knowledge. – user2284570 Feb 29 '16 at 20:10
1

Not all buffer overflows lead to remote code execution. It depends on how the buffer is allocated, and if the instruction pointer can be controlled by the attacker. There are many factors that go into whether or not remote code execution is a possibility.

RoraΖ
  • 12,317
  • 4
  • 51
  • 83
0

Ubuntu uses data execution protection. This stops code being executed from memory in the data portion of the process. This will effectively make code injected via a buffer overflow impossible to be executed. So the overflow can occur though execution cannot. Techniques such as ROP are used to work around DEP.

Neil Smithline
  • 14,621
  • 4
  • 38
  • 55
  • Does rop can’t be applied in the current case ? – user2284570 Feb 25 '16 at 20:22
  • What is "the current case"? – Neil Smithline Feb 25 '16 at 20:24
  • The specific one which is being described in the question. – user2284570 Feb 25 '16 at 20:26
  • Ah. ROP is *typically* used for stack overflows because it relies on their being a return address in the stack. That said, there can be code pointers in the heap in, for example, [exception handling](https://en.wikipedia.org/wiki/Exception_handling) data structures. For this, [SEHOP](https://en.wikipedia.org/wiki/Exception_handling) is the protection. I do not think that Linux supports something like SEHOP, but am not certain. So I'm not certain if it can be used, but think it can. – Neil Smithline Feb 25 '16 at 20:59
  • At least not supported by ubuntu *(part of the current case)*. As it’s know fixed, I posted the real code. – user2284570 Feb 25 '16 at 22:01