A Perl script eliminates null session shares to secure remote systems
Early in my life as a network administrator, I fought many battles just trying to keep my network together. Because the original architects of the network never really planned for pesky tasks such as checking security, I had to implement cheap but effective methods to query settings on remote machines. So I did what all good administrators do: I wrote a script.
I wrote the script in Perl. For those who are unfamiliar with Perl, it's a powerful, extensible open-source scripting language. It has been ported to most platforms (e.g., UNIX, Macintosh, Win32, VMS), so you can use it to write scripts that can run on all your systems.The script interacts with the Win32 registry, which stores most of Win32's configuration information, to check some settings for security purposes. The script implements a simple form of autodiscovery to ensure that it inspects all machines on the network.
Scripting in Perl
Perl has been around for more than 10 years and has become the language of choice for most administrator who want to use one language across multiple platforms. You can download Perl precompiled binaries for the Win32 platform from ActiveState (http://www.activestate.com). You can find information about Perl, including details about obtaining and compiling the source code, on a number of Web sites. The Perl site that O'Reilly & Associates sponsors (http://www.perl.com) has all sorts of articles, columns, and other information that's useful for any Perl user.
One of Perl's most compelling advantages is its widespread support. You can go to one of many repository sites and download ready-made scripts, modules, and extensions. Modules are libraries of functions; extensions are DLLs that provide functionality above and beyond the language itself. Two such modules and extensions that are available for Win32 platforms are the Net::Ping module, which provides Internet Control Message Protocol (ICMP) and TCP ping functionality, and the Win32::Registry extension, which provides access to the Win32 registry. Both Net::Ping and Win32::Registry come with the ActivePerl distribution from ActiveState.
By combining this Perl module and extension, you can easily write a script that autodiscovers Win32 machines on the network and interacts with their registries. The code in Listing 1, page 42, shows how to use Net::Ping and Win32::Registry in tandem to elicit information about Windows machines across your network and to help secure them.
Discovering Machines
You can use one of several ways to determine what machines exist on your network. One way is to use Microsoft Active Directory Service Interfaces (ADSI) to query Active Directory (AD). In Perl, you can use COM to interact with ADSI, so you would load the Win32::OLE extension. (Alternatively, you can use the Lightweight Directory Access ProtocolLDAPbut I prefer to use ADSI for various authentication and authorization reasons.) However, you can't use ADSI for networks that don't use AD, such as Windows NT domains. Another way to discover a domain's machines is to use the Win32::AdminMisc extension's GetMachines() function or the Win32::Lanman extension's NetQueryDisplayInformation() function to query a domain controller (DC).
The problem with querying AD or a DC is that they give you a list of machines in a given domain. These machines might be offline, or they might not still be in use (think of machines that have long been removed from the domain but whose domain accounts still exist). Additionally, the list would include only machines in the specified domain, not machines in other domains or workgroups on the network.
To circumvent these problems, the script implements a form of autodiscovery. At callout C in Listing 1, the script creates a Net::Ping object that pings each IP address on a given subnet of your network. By default, Net::Ping uses the ICMP protocol for pinging; however, the object also supports TCP pinging. (Check the Net::Ping module's documentation for further details.) The code at callout E loops through the IP range specified in the code at callout A. The script pings each IP address and calls the ProcessHost() subroutine for each machine that responds.
Processing the Registry
The ProcessHost() subroutine uses the Win32::Registry extension to query a remote machine's registry. First, the subroutine attempts to connect to the remote machine. This connection fails if the remote machine isn't a Win32 platform. Likewise, the connection fails if a remote Win32 machine prevents access to its registry (e.g., if the person running the script doesn't have permissions to access the machine's registry) or if the remote registry service is disabled.
When the subroutine makes a connection, it attempts to access four registry values. When the subroutine successfully opens a registry subkey, it queries for a particular value, outputs the value to the screen, closes the subkey, and repeats the logic for the remaining values. The four values are the machine's network name, the last user to log on, the approximate speed of the machine in megahertz, and a list of null session shares.
Null session shares are shared directories that have no associated permissions; therefore, they don't require client authentication. Anyone can gain entry to these directories without being authenticated. Null session shares are a security exposure, so checking your systems for them and eliminating the ones that aren't necessary is a good idea. For more information about when null session shares are required, see the sidebar "Using Null Session Shares," page 46.