Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Run arbitrary UNIX commands on webserver without telnet

by dmmiller2k (Chaplain)
on Oct 30, 2001 at 18:55 UTC ( #122087=perlcraft: print w/ replies, xml ) Need Help??

   1: #!/usr/bin/perl -w
   2: 
   3: use strict;
   4: 
   5: # This is a RIDUCULOUSLY simple script which I often use
   6: # with ISP's that prohibit telnet access.  It simply runs
   7: # an arbitrary UNIX command and captures its output to a
   8: # web page.
   9: 
  10: # I won't debate whether or not it belongs here; that's for
  11: # exalted others to decide; I merely present something I
  12: # have found to be useful.
  13: 
  14: # Be Warned: this appends sh redirection (of stderr to
  15: # stdout: '2>&1') to the command entered, so arbitrary
  16: # redirection entered as part of any command may not
  17: # work as expected!
  18: 
  19: # DISCLAIMER: Do NOT leave this script in an accessible
  20: # location on any active web server!! It is VERY insecure!
  21: # At least chmod the 'x' bit off when not in use!
  22: 
  23: use CGI qw( :standard *table *Tr *pre );
  24: use CGI::Carp qw( fatalsToBrowser );
  25: use File::Basename;
  26: 
  27: my $title = 'UNIX Command';
  28: 
  29: my $command = param('command'); # get command entered
  30: # append command name, if any, to title
  31: $title .= ': '. basename( (split /\s/, $command)[0] ) if $command;
  32: 
  33: # display control panel
  34: print join( "\n", header,
  35: 		  start_html($title),
  36: 		  strong(h1($title)),
  37: 		  start_form({ -method=>'get' }),
  38: 		  start_table({-width=>'100%',-borders=>0}),
  39: 		  start_Tr,
  40: 		  td( 'Command:' ),
  41: 		  td( textfield({-size=>100,-name=>'command'}) ),
  42: 		  td( submit('run')),
  43: 		  end_Tr,
  44: 		  end_table,
  45: 		  end_form ), "\n";
  46: 
  47: # if command was entered, run it in a pipe and display its output
  48: if ($command) {
  49:   open( CMD, "$command 2>&1|" ) or die "$!: running command: '$command'";
  50:   print start_pre, "\n";
  51:   print while (<CMD>);
  52:   print end_pre, "\n";
  53:   close CMD;
  54: }
  55: 
  56: print join( "\n",
  57:             end_html ),"\n";

Comment on Run arbitrary UNIX commands on webserver without telnet
Download Code
Re: Run arbitrary UNIX commands on webserver without telnet
by tommyw (Hermit) on Oct 30, 2001 at 19:22 UTC

    If I found this on my webserver, I'd start taking steps to close the account down...

    --
    Tommy
    Too stupid to live.
    Too stubborn to die.

      I agree, wholeheartedly!

      I don't install this as a Permanent feature of a site, just as a TEMPORARY tool to assist with getting one up and running. I should have qualified my posting with the following caveat:

      DELETE THIS AFTER USING ON ANY SITE!

      dmm

      
      You can give a man a fish and feed him for a day ...
      Or, you can teach him to fish and feed him for a lifetime
      
      There'd be no steps for me. I'd tar up the directory, delete it, lock the account, and explain why later.
Re (tilly) 1: Run arbitrary UNIX commands on webserver without telnet
by tilly (Archbishop) on Oct 30, 2001 at 19:39 UTC
    I far prefer the tried and true:
    use CGI qw(:standard); # Time passes open(IN, param("input_file")); # and do the rest of the apparently innocuous program
    The proper usage of this handy command runner I leave to your imagination, a close read of open's semantics, and a reminder that if you know how to do a URI encoding, you can put pipes etc into the filename.

    Yes. This is a warning about a basic security mistake that you may be making without realizing it...

      Very stealthy. And concise.

      dmm

      
      You can give a man a fish and feed him for a day ...
      Or, you can teach him to fish and feed him for a lifetime
      
Re: Run arbitrary UNIX commands on webserver without telnet
by ajt (Prior) on Oct 30, 2001 at 19:43 UTC
    While I think we can all agree that telnet is NOT perfect, I don't think it's wise to allow people to post to a CGI script, and then running arbitary commands on a server.

    Even if you are using authenication/authorisation to restrict people from using this script, and the script runs with limited priviledges, and is sandboxed off from the rest of the web server, I still think it's not wise.

    If your hosting company doesn't allow SSH or Telnet then I think a better host is a better solution than a script like this.

    I've just seen your caveat, I'm pleased you think it's dangerous, I still thinks it's a dangerous thing to do, even if only temporarily.

      While I think we can all agree that telnet is NOT perfect, I don't think it's wise to allow people to post to a CGI script, and then running arbitary commands on a server.

      First, with all its warts, if telnet were available I would never have resorted to this approach.

      Second, please read my reply to jeffa (below, I think), regarding ``allowing people ... running arbitrary commands on a server.''

      Finally, when you are working for actual paying clients, you don't always get a say in which hosting company they choose.

      In short,

      • Dangerous? Yes.
      • Necessary? Occasionally.
      • Ever leave accessible and executable after logging off? Never
      • Allow users (even friendly ones) to use it? Never, on penalty of losing Web Developer license

      dmm

      
      You can give a man a fish and feed him for a day ...
      Or, you can teach him to fish and feed him for a lifetime
      
        Finally, when you are working for actual paying clients, you don't always get a say in which hosting company they choose.

        If the paying client cares about the quality of work, they'll use a hosting company or buy extra services needed to get the work done. My experience is that the clients that are too cheap with their money to buy basic services and software should be avoided.

        (Yes, there are cases where the client can't afford a lot of extras and you have to go through hoops, but there's a minimum set of tools you need.)

        And if I were a client and found out my consultant was using hacks which could jeopardize the security of my web site and potentially get my web site taken down by angry sysadmins... well, the consultant would be out on his/her arse in no time and I'd be in contact with some lawyers.

(jeffa) Re: Run arbitrary UNIX commands on webserver without telnet
by jeffa (Chancellor) on Oct 30, 2001 at 20:59 UTC
    This sounds like a job for SOAP. Also notice the use of the lookup table - instead of allowing the user to send arbitrary commands, only allow them a handlful of tokens that you consider safe:
    package RPC; sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = { ls => 'ls -la' top => 'top -b -n1' who => 'w' }; return bless $self, $class; } sub exec { my ($self,$cmd) = @_; $cmd = $self{$cmd} || return "bad command\n"; `$cmd`; }
    Take a gander at SOAP::Lite for more info, also check out $code or die's review on the module.

    Update: I should mention that if you actually want the user to be able to have 'state', then you need to add sessions - check out Apache::Session. For example, if the user issues 'cd /' and then 'pwd' - the result of the 'pwd' will show that they are back at their home directory, and not root.

    But, if they need that - then you really should just use ssh. :)

    jeffa

      I can see this discussion has somehow gone off on a tangent.

      This approach was NOT (repeat: NOT) ever meant for USERS to see, much less use.

      It is, temporarily, a way to:
      • find out the cwd (e.g., by running 'pwd'), for example, in order to install some script you got from somewhere that needs to know where it is installed,
      • unpack a gzipped tarball you just FTP'ed onto a site ('zcat whatever.tar.gz|tar -xvf -'),
      • determine the version of perl you're running ('perl -V')
      • etc.

      Once again, this is not for users. It is for me, the developer!

      dmm

      
      You can give a man a fish and feed him for a day ...
      Or, you can teach him to fish and feed him for a lifetime
      
        Ah, okay - i see the difference now. But remember this, it is for you AND anyone who hacks your packets while you run this.

        jeffa

        You can give a man a fire and warm him for a day . . .
        or you could set the man on fire and keep him warm for a lifetime

        (quote stolen from boo_radley)

Re: Run arbitrary UNIX commands on webserver without telnet
by merlyn (Sage) on Oct 31, 2001 at 01:50 UTC
    Far too much overkill. If you can upload that script, you can upload this:
    #!/bin/sh echo content-type: text/plain echo ... put ... your ... command ... here
    No point in even using an input form (or Perl!) for this. How silly. How insecure. How overkill.

    -- Randal L. Schwartz, Perl hacker

      You're right, of course...

      Funny, this script started out as a hard-coded script that I would clone for each new command. See this node, for a prettied up version.

      It was only after the bright idea of posting it occurred to me that I even thought of adding the form. I suppose the idea just got away from me. Thanks for bringing it down to earth.

      dmm

      >Far too much overkill

      I love this idea! And I want tips from more experienced monks on how to decide exactly how much overkill I need to put in my CGI scripts ;->

      Cheerio!
      Osfameron
Re: Run arbitrary UNIX commands on webserver without telnet
by DrManhattan (Chaplain) on Nov 12, 2001 at 20:02 UTC
    Here's a script I use. It adds a password check.
    #!/usr/bin/perl use strict; use CGI qw(header param); $| = 1; print header(); # Crypted password my $HASH = "azEehXEsKGpt6"; # Fetch CGI input my $password = param('password'); my $command = param('command'); # Output HTML print << "END"; <form method="post"> <input type="password" name="password" value="$password"><br> <input type="text" name="command"><br> <input type="submit"> </form> <pre> END # If the password is correct, execute the command if (crypt($password, $HASH) eq $HASH) { system($command); }
    Caveats: <list>
  • You'll have to generate the crypted password using the same crypt() routine as the system to which you're uploading the CGI script.
  • The clear text of the password is left in the HTML source of the output page, so don't leave browser windows open to it.
  • </list>

    -Matt

Re: Run arbitrary UNIX commands on webserver without telnet
by chip (Curate) on Nov 13, 2001 at 10:36 UTC
    And the reason why a sane person would install this script is ... ?

        -- Chip Salzenberg, Free-Floating Agent of Chaos

      Not install, per se, but copy to an htaccess-protected directory, use it and remove it.

      Occasionally, I need perl modules built which the ISP cannot or will not install into the system-wide perl directory; with this I could PERL5LIB={local lib directory} perl Makefile.PL LIB={local lib directory}; make; make test; make install to install into a local lib directory of a site I am working on.

      Some canned scripts (I admit it, I sometimes use them) require a variable set to the absolute path of some directory they need; running a simple pwd gives me the prefix of the chroot'ed site.

      You cannot always spec out an ISP that permits telnet access; sometimes, while building a rep with clients, you have to work with what they've got. THEN, when they trust you enough to follow your advice, move them to another ISP

      dmm

        OK, installed temporarily with .htaccess protection, I might consider not sacking someone who used the script in question. Maybe.

            -- Chip Salzenberg, Free-Floating Agent of Chaos

        I would recommend firing a consultant who specced out an ISP with telnet access.

        Shell access? Perfectly reasonable using ssh.

        But telnet access?

Re: Run arbitrary UNIX commands on webserver without telnet
by mattr (Curate) on Nov 13, 2001 at 13:50 UTC
    It is also very dangerous because you could have admins preserving this security hole in automatic backups, or you could have a disgruntled employee use it. Maybe you can compromise important passwords (db server? other hosts?) by showing them to other people through the shell environment variable.

    What would be really dangerous is for it to be pushed from a staging server to live server in a general upload that the corporate hosting service does for you. You may not ever be able to tell what is in that directory yourself, and like one large hosting service I know, there may be nobody with brainpower in the loop on their side either.

    If you really needed to know something about your server I don't see why you wouldn't just modify your main cgi program to print the data out, then erase that debugging code later.

    Of course I tell clients to only use telnetable systems, or to switch to a cheaper provider which has them.. at the very least you will be very sorry when you suddenly need to use compiled C code.

    I can imagine a situation where you might want to do something in 5 minutes and you are in trouble, but there is no justification for making a general shell exploit and posting it on perlmonks. I can't see a lot of use for it except as a way to do mischief.

      Point taken. See my reply to merlyn.

      dmm

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlcraft [id://122087]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (6)
As of 2014-11-23 21:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My preferred Perl binaries come from:














    Results (134 votes), past polls