Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Avoiding a GET CGI hack attack

Reply
Thread Tools

Avoiding a GET CGI hack attack

 
 
Robert Stelmack
Guest
Posts: n/a
 
      07-16-2004
I posted this message also at: comp.inforsystems.www.authoring.cgi, but
after one day it did not show up, so I try here since it both a CGI and a
Perl question.

I am trying to make my Perl CGI script secure. Our non-profit web site was
hacked and the index page changed. This in itself is just an annoyance, but
it could have just as easily to alter or delete any file.

The web host system administration was kind enough to look over some logs
and identified the method used to hack the site. This was do to a "bug" in
the script ~/www/cgi-bin/index.cgi This CGI script is something I built and
functionally does what I want it to, but obviously poorly written. I have
blocked the script for the time being with a chmod 000 to disallow any
access.

Here is the way that the system administrator said that the script was
compromised:

xxx.xxx.xxx.xxx - - [09/Jul/2004:06:07:43 -0500] "GET
/cgi-bin/index.cgi?path=|echo%20\"<html><head><title>H@ck3d !</title></head><
body%20bgcolor=black%20text=yellow><h1>Hacked!%20W hat%20such%20a%20weak%20si
te!%20Please%20fix%20this%20as%20soon%20as%20possi ble!%20Or%20your%20site%20
will%20be%20more%20vunerable!</h1><center><h3><i>Nowhere%20Man</i></h3></cen
ter></body></html>\"%20>%20../index.htm|

He said that I would need additional input checking to prevent this from
happening again.

Here is the script, pared down to show what it basically does. Yes, and
before anyone says anything: it is a crap script, I didn't RTFM, and there
is a better way to do it

#!/usr/bin/perl

open(STDERR,'>&STDOUT'); ## Assign error messages to STDOUT to view

$| = 1;

print "Content-Type: text/html\n\n"; #live feed to browser

push(@INC, "../"); ## Location of cgi-lib.pl (located in this directory)

require "cgi-lib.pl" || die "Can't find cgi-bin.pl REASON: $! ";

## Looks up the files in the passed directory name with the suffix ".dbf"

&ReadParse(*input);

$PATH = @input{'path'}; ## The Name of the DIRECTORY

print "<html><head><title>Index Page</title></head><body>";

{foreach $file (<$PATH/*.dbf>)

{

$_ = $file;

print "PWD for files found: $_<br>\n";

}

}

print "</body></html>";

I have read several Perl and security references and I would like to see if
this is all I need to do:

&ReadParse(*input);

$PATH = @input{'path'}; ## The Name of the DIRECTORY

if ( $PATH =~ /[`\$\\"';&>]/ ) {die} ## Die if special characters are used

Not sure if the reg expression is correct, but is this the input checking
the system administrator was referring to? Or, do you have a good generic
suggestion to prevent this type of hacking that a simple user could
implement?

There were other ways to secure the script, but many of then required system
administrative access that I don't have.

I will add the -w -T for the perl execution and the "use strict; use
warnings;" once I clean up the script and use some of the OOP in the CGI.pm
module. And I will try to understand the scope (ie. "my variable") and
properly code the variables.

I will also add this, as suggested by perlsec:

delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safe

----------------------------------------

References used:

http://www.oreilly.com/catalog/cgi2/chapter/ch08.html

http://search.cpan.org/~jhi/perl-5.8.0/lib/CGI.pm

perlsec



 
Reply With Quote
 
 
 
 
Gunnar Hjalmarsson
Guest
Posts: n/a
 
      07-16-2004
Robert Stelmack wrote:
> I posted this message also at: comp.inforsystems.www.authoring.cgi,
> but after one day it did not show up,


Please see http://www.thinkspot.net/ciwac/howtopost.html for info
about a first time post to ciwac.

<snip>

> Here is the script, pared down to show what it basically does.
> Yes, and before anyone says anything: it is a crap script, I didn't
> RTFM, and there is a better way to do it


Since you realize that, you posted here prematurely. You should have
made an effort to improve the script first.

> &ReadParse(*input);
>
> $PATH = @input{'path'}; ## The Name of the DIRECTORY


At this point, $PATH may contain basically anything.

> {foreach $file (<$PATH/*.dbf>)


And here you pass $PATH to a construct that invokes system commands.

This is a good example of what tainted mode is good for. If -T had
been enabled, Perl would have complained.

> I have read several Perl and security references and I would like
> to see if this is all I need to do:
>
> &ReadParse(*input);
>
> $PATH = @input{'path'}; ## The Name of the DIRECTORY
>
> if ( $PATH =~ /[`\$\\"';&>]/ ) {die} ## Die if special characters
> are used
>
> Not sure if the reg expression is correct, but is this the input
> checking the system administrator was referring to? Or, do you
> have a good generic suggestion to prevent this type of hacking that
> a simple user could implement?


Well, you missed one of the most important advices in "perldoc
perlsec": "It's better to verify that the variable has only good
characters (for certain values of ``good'') rather than checking
whether it has any bad characters. That's because it's far too easy to
miss bad characters that you never thought of."

Also, the above does not untaint $PATH.

What you should have done is ensuring that $PATH only contains 'safe'
characters, for instance like this:

if ( $PATH =~ /^([-/\w])$/ ) {
$PATH = $1;
} else {
die "Unsafe character(s) in \"path\"";
}

Then you would have been able to run the script in taint mode, and the
hack you let us know about would not have been possible.

> I will add the -w -T for the perl execution and the "use strict;
> use warnings;" once I clean up the script and use some of the OOP
> in the CGI.pm module. And I will try to understand the scope (ie.
> "my variable") and properly code the variables.
>
> I will also add this, as suggested by perlsec:
>
> delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safe


That sounds good. But why didn't you do that before posting?

--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl
 
Reply With Quote
 
 
 
 
Gunnar Hjalmarsson
Guest
Posts: n/a
 
      07-16-2004
Gunnar Hjalmarsson wrote:
>
> if ( $PATH =~ /^([-/\w])$/ ) {


Make that:

if ( $PATH =~ /^([-\/\w])$/ ) {
-----------------------^

--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl
 
Reply With Quote
 
Joe Smith
Guest
Posts: n/a
 
      07-16-2004
Gunnar Hjalmarsson wrote:

> What you should have done is ensuring that $PATH only contains 'safe'
> characters, for instance like this:
>
> if ( $PATH =~ /^([-\/\w])$/ ) {
> $PATH = $1;
> } else {
> die "Unsafe character(s) in \"path\"";
> }


I'd like to point out to Robert that he should be aware of attacks
that use "../", as in "../../../../../etc/passwd". Since the
above regex (corrected) does not accept periods, it foils that
particular attack.
-Joe
 
Reply With Quote
 
Gunnar Hjalmarsson
Guest
Posts: n/a
 
      07-16-2004
Joe Smith wrote:
> Gunnar Hjalmarsson wrote:
>> What you should have done is ensuring that $PATH only contains
>> 'safe' characters, for instance like this:
>>
>> if ( $PATH =~ /^([-\/\w])$/ ) {
>> $PATH = $1;
>> } else {
>> die "Unsafe character(s) in \"path\"";
>> }

>
> I'd like to point out to Robert that he should be aware of attacks
> that use "../", as in "../../../../../etc/passwd". Since the above
> regex (corrected) does not accept periods, it foils that particular
> attack.


True, but note that the OP has

foreach $file (<$PATH/*.dbf>)

, so nothing prevents you from simply stating the path '/etc'. I
suppose that the best protection in this case against that kind of
illegitimate access is the file extension '.dbf'.

--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl
 
Reply With Quote
 
krakle
Guest
Posts: n/a
 
      07-16-2004
"Robert Stelmack" <robert.h.stelmack*REMOVE*@boeing.com> wrote in message news:<(E-Mail Removed)>...
> #!/usr/bin/perl


Always run perl scripts under the 'T' and 'w' switches using the
strict pragma. Warnigns help too.. It forces you to write "clean" perl
by scoping variables and prevents you from certain dangerious coding
methods.

#!/usr/bin/perl -Tw
use strict;
use warnings;

Ofcourse your script will have to be re-written.. But let's say you
decide not to do that.. You can patch up that bug with the
following...

> {foreach $file (<$PATH/*.dbf>)
>
> {
>
> $_ = $file;
>
> print "PWD for files found: $_<br>\n";
>
> }
>
> }


Firstly I would of thought the first line would of caused an error
since it doesn't exactly go by coding standards... I assume each .dbf
(DataBase File) located at the path ($path) contain a plaintext
password and this script loops through the path and displays all
passwords... IF all the .dbf files are in a single location cut out
the parameter passed to the script and just use a non-user defined
variable in the script. IF, the .dbf files are in multiple directories
(but a set number) just store the paths in a HASH (path as value.. a
keyname as the name) and pass a parameter through the script wiht just
the keyname and fetch the path that way. IF the .dbf files are
dynamically made in random locations you may want to use the "open"
command and do some regex's on the parameter passed...

> $PATH = @input{'path'}; ## The Name of the DIRECTORY
>
> if ( $PATH =~ /[`\$\\"';&>]/ ) {die} ## Die if special characters are used


Your script allowes for anyone to execute unix commands.. so it
seems.. Sure you can STRIP all non A-Z 0-9 characters all you want BUT
that doesn't stop anyone from using unix commands to delete files...or
do anything such as 'cat' dbf files to get passwords...
 
Reply With Quote
 
Gunnar Hjalmarsson
Guest
Posts: n/a
 
      07-16-2004
krakle wrote:
> Your script allowes for anyone to execute unix commands.. so it
> seems.. Sure you can STRIP all non A-Z 0-9 characters all you want
> BUT that doesn't stop anyone from using unix commands to delete
> files...or do anything such as 'cat' dbf files to get passwords...


Sounds scaring. Could you please show us how you delete a file through

foreach $file (<$PATH/*.dbf>)

if $PATH only may contain letters and digits.

--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[SEC] Mongrel Temporary Fix For cgi.rb 99% CPU DoS Attack Zed A. Shaw Ruby 4 10-25-2006 08:03 PM
Symantec raises alarm on Microsoft Word hack attack Au79 Computer Support 0 05-21-2006 11:21 PM
Avoiding multiple cgi instances brendan Perl Misc 2 10-29-2003 04:53 AM
CGI Programmers needed to hack around at our CGI Scripts James Perl Misc 1 08-04-2003 09:27 AM
Any one do a mini-few-sec digital handheld videocam for re-attack after violent road rage attack? dorothy.bradbury Digital Photography 15 07-20-2003 11:58 PM



Advertisments