Thanks for your input. In regards to filename, I'm assuming you are talking about the filename passed within the HTML, right?

If I know what you meant be that, I'd be more able to say.

So I'll dodge and try explaining it this way: Any script that could potentially be called by someone typing it's URL into their web browser is subject to getting input you don't want. If you accept file names directly in such scripts, there are several bad things that can happen: An attacker can gain information you may not want him or her to get about the structure of things in your site (ergo, by checking the status bar). Worse, an attacker could pass a complex path giving access to files you don't want him or her to be able to access. Another bad thing is that an attacker could pass a huge string that contains lots of escape characters to hide the complex path. (I regularly see zombies posting 32k parameter strings to my home server.) If I tried to put one of those strings into a limited space buffer (usually more of a problem in C than in perl), it could blow up my program or allow a buffer overrun attack.

I think what I will probably do is pass an ID number to the script and then process it that way.

If the file name contains the ID number or name string, you'll still need to clean the http parameters.


If you have a hash (not an array) that you use the ID to index into and get the real file name, that is one good way to clean the parameter. An if-ifels condition that compares the IDs to a (small) set of valid IDs could be another way.

But whatever you use to map the IDs to file names, you'll want to check for weirdness like escape characters and long strings, just to avoid stressing your machine.

I will still check for "../" andywhere the passed ID, as well as "/" at the beginning of the ID. You mentioned that "V is /". I"m afraid you lost me there. Can you explain?

The backslash is an escape character and can be used to hide things. For instance, "../" will go up one level in the directory, but so will "\.\.\/".


Have fun. I gotta go to work.


Thanks,

Mark

On Aug 25, 2004, at 8:16 AM, Joel Rees wrote:

Just a few nosy comments --

<html>
<head>
<title>Untitled Page</title>
</head>
<body>
<a href="javascript:window.location='cgi-bin/ download.cgi?picname=Upload-Background.gif'">picture link</a>

Not sure why you want to bother with javascript in there. ICBW, but I don't think it buys you anything. And some of your family may decide to turn javascript in their browsers off.


</body>
</html>

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

#!/usr/bin/perl -w

use strict;
use CGI ':standard';

I didn't notice that you had used anything from CGI in the script. Might as well comment it out.


my $filename = param('picname');

Did you follow what was said about ../../ someodd with /etc at the end?


It's a good way to dump all sorts of things about your machine into someone else's browser, including user names and ids, the entire httpd.conf file, and so forth.

That's why I don't usually accept filenames in scripts. But if you do, you need to check for / at the top or ../ anywhere, and balk if you get those. It can get kind of tricky, since \/ is /.

my $path = "/images/$filename";

For instance, somebody puts this in their browser:

http://your.domain.com/cgi-bin/download.cgi?picname=../etc/httpd/ httpd.conf


binmode STDOUT; print "Content-Disposition: attachment;filename=$filename\n"; print "Content-Type: application/octet-stream\n\n";

If you _had_ been using CGI, the above two lines could have created some subtle conflicts.


open (FILE, "> $path") || die("Can't open($filename): $!");

This is why you got the attempted download that stalled, of course. That die statement won't do much useful. Well, if it were going out STDOUT, it might have shown up as your downloaded file.


You'll want to look into using a logging file or the http version of carp.

my $data = <FILE>;
close (FILE);

print $data;

exit;

-- Joel Rees Nothing to say today so I'll say nothing: Nothing.





Reply via email to