CGI and Perl

Listing 16.3. A Web-based command shell.

#!/usr/local/bin/perl
 use CGI::Form;
 $q = new CGI::Form;
 print $q->header();
 print $q->start_html(-title=>`A Web-based Command Shell');
 print "<H1>A Web-based Command Shell</H1>\n";
 if ($q->cgi->var(`REQUEST_METHOD') eq `GET') {
    &loginForm($q);
 } else {
    if ($q->param(`Action') eq "Login") {
       $uid=$q->param(`uid');
       $pw=$q->param(`pw');
       if (&validateLogin($uid,$pw)) {
          $history="";
          &shellForm($q,$history);
       } else {
          &unauthorized($q);
       }
    } elsif ($q->param(`Action') eq "Doit") {
       $history=$q->param(`cmdHistory');
       $command=$q->param(`command');
       if ($command ne "") {
          $history.=&doCommand($q,$command);
          }
       $q->param(`cmdHistory',$history);
       &shellForm($q,$history);
    } else {
       &unauthorized($q);
    }
 }
 print $q->end_html();
 sub validateLogin {
    my($userid,$pw)=@_;
    my($retval)=0;
    if (open(PASSWD,"/etc/passwd")) {
       while (<PASSWD>) {
          chop;
          my($login,$passwd,$uid,$gid,$rest)=split(/:/);
          if ($login eq $userid && crypt($pw,$passwd) eq $passwd) {
             $retval=1;
             last;
          }
       }
       close(PASSWD);
    }
    return $retval;
 }
 sub unauthorized {
    my($q)=@_;
    print "<STRONG>Sorry! You are not authorized to enter this area!</STRONG><BR>\n";
    print "<A HREF=/cgi-bin/cmdshell.pl>Try again</A>";
 }
 sub loginForm {
    my($q)=@_;
    print "<P>Please enter your userid and password:<P>\n";
    print $q->start_multipart_form();
    print $q->textfield(-name=>`uid');
    print "<BR>";
    print $q->password_field(-name=>`pw');
    print "<BR>";
    print $q->submit(-name=>`Action',-value=>`Login');
    print $q->reset;
    print $q->endform;
 }
 sub shellForm {
    my($q,$history)=@_;
    print $q->start_multipart_form();
    print $q->hidden(-name=>`cmdHistory',-value=>$history);
    print $q->textfield(-name=>`command');
    print "<BR>";
    print $q->submit(-name=>`Action',-value=>`Doit');
    print " ";
    print $q->reset;
    print $q->endform;
    print "<P>Command History:<P>\n";
    print "<PRE>$history<\PRE>";
 }
 sub doCommand {
    my($q,$cmd)=@_;
    my($hist)="$cmd\n";
    $hist.=`$cmd`;
    return "$hist\n";
 }

You can see how the login form would look in Figure 16.3. Once the user has logged in and issued a few commands, the shell would look as shown in Figure 16.4.

Figure 16.3. The command shell login form.

Figure 16.4. The command shell with history.

You will notice in this example that we keep a running history of command output. When the output exceeds a certain limit, in this case 1,024 characters, it will be truncated. The session is maintained as long as continuous POST requests are made. As soon as the user leaves this CGI session, it will reinitialize on the GET request.