Question

I'm writing a Perl script which will scan the filesystem for files that are writable by everyone. I've looked at a couple items that have helped me. Primarily this Stonehenge.com post from 2001 and a question previously asked here. Both have directed me to most of a solution. I am able to now find files that are writable by everyone, however, I have some concerns.

For starters, my script:

#!/usr/bin/perl

use warnings;
use strict;
use File::Find;
use Sys::Hostname;

my $hostname = hostname;
my $file = "/tmp/$hostname" . "_ww_files.txt";

open (WWFILE, ">>$file");

find sub {
  return unless (stat)[2] & 00002; # ...and world writeable
  return if "$File::Find::name" =~ m/(\/tmp)|(^\/dev)/;
  print "$File::Find::name\n";

}, "/";

My first concern is that when I run the script it frequently throws an error on several files that states Use of uninitialized value in bitwise and (&) at ./ww_files.pl line 15.. This, of course, being the line that checks the mode of the file and then does a bitwise AND in order to find only those that have a "w" in the second column of each octet. Or so I'd like to believe, but I'm quite certain I'm not really looking for the right permissions with that method.

To be clear on this, all I care about is the "w". I don't care if a file is readable by everyone or even executable by everyone. So I suppose my second concern by way of the question I should be asking is what should that AND mask be in order to ignore everything but the "w"?

Was it helpful?

Solution

From the File::Find docs "if you use the warnings pragma, File::Find will report warnings for several weird situations." I wouldn't worry too much about them. To be sure about the mask you could use the constant S_IWOTH from Fcntl:

use Fcntl ':mode';
use File::Find;
no warnings 'File::Find';

find sub {
    return unless (stat)[2] & S_IWOTH; # ...and world writeable

OTHER TIPS

Probably the file could not be stated and so the value is undefined. You can easily trap that, though;

my @s = stat();
unless (@s) {
    warn "$File::Find::name: stat failed: $!\n";
    return;
}
return unless $s[2] & 0x02;

Generally speaking, you should check the return value of system calls for errors.

The mask value of 2 is precisely correct for finding world-writable files. However, perhaps you also want to check for odd group-writable files where the group is something weird?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top