Pantek Library
Hosting Provided By
CybrHost
High Speed Hosting

Re: Can System() of Perl be bypassed?

From: Brian Hatch <secprog(at)ifokr.org>
Date: Wed Jan 22 2003 - 16:58:01 EST

> In my PERL code,I am using user's input as command line argument for the
> program being executed by System().
> Can user run command of his choice by giving malicious input?
> Is PERL's -T (Taint mode) the solution for this?

Using Taint mode is a good thing. However you can still easily untaint inappropriately:

	$user_filename = $q->param('filename');
	$user_filename =~ /^ (.*) $/x;

	$filename = $1;

	system "/bin/ls $filename";

Sure, the filename submitted by the user was untainted and put into $filename. But since the untainting didn't do anything to actually check the input (it was just extracted via $1, no checks or munging whatsoever) a user could easily supply "/etc/passwd; rm -rf /" as a filename and system will happily process it.

Lesson 1: do real untainting. Make sure the filename looks exactly like you want it:

        $user_filename =~ /^ ([a-zA-Z]+) $/x;

This would allow files that are 100% alphabetic, for example. No shell metacharacters, no parent (..) directories, or any directory (/) stuff at all.

Do you need help?X

Naturally, what a 'valid' value is depends on your needs.

Lesson 2: say what is valid, don't decide what isn't valid.

The best untainting is when you explicitly say what is all right. If you were trying to extract a suitable filename (anywhere on the filesystem, including the use of .. and /'s) you'd want something like this:         

        /^ ( [\w./]+ ) $/x;

which details exactly what you'd consider valid. If instead you try to get rid of 'bad' data, such as shell expansion characters:

        /^ ( [^;\$&]+ ) $/x;

Then you're liable to miss some. For example "*" is missing from the above list.

Lesson 3: always use the array form of system in perl.

Do you need more help?X

System will pass your command to /bin/sh if it thinks there are shell metacharacters to expand. If you're using user input, don't do this. (Heck, never do this - it's poor form anyway.) Instead, use the array version, which will do a fork/exec of your command explicitly, and never run the shell. Thus you'd want to have

        system( "/bin/ls", $filename);

If somehow your untainting failed, and the user was allowed to supply "/etc/passwd; rm -rf /" for the filename, you would end up running

        ls "/etc/passwd; rm -rf /"

And, assuming you don't have a file named "/etc/passwd; rm -rf /" ls will simply complain that no such file exists.

Short answer: unless you program with lots of paranoia, any programming language can be abused, perl included.

--
Brian Hatch                  "I've got as much chance of
   Systems and                doing that as seeing a
   Security Engineer          Vorlon doing strip-tease."
http://www.ifokr.org/bri/

Every message PGP signed

  • application/pgp-signature attachment: stored
Received on Wed Jan 22 17:27:47 2003

This archive was generated by hypermail 2.1.8 : Wed Aug 23 2006 - 14:02:45 EDT

Can we help you?X

Contact Us  Legal Notices  Order Services Online 
Pantek Home  Privacy Policy  IT news  Site Map  Pantek Library