secure file writing (escaping characters from the file name)

  • Thread starter Constantin Gavrilescu
  • Start date
C

Constantin Gavrilescu

I have a cgi script that writes files on the filesystem. The files are
provided by the users. I need to save them with (almost) the same name
as the user requests. What characters I need to escape?

This is on linux. Right now the file: "Mick Jagger / Chris Jagger -
Racketeer Blues" does not get saved because of the "/" character. I
don't escape any characters now. I want to keep as many of the original
characters in the file name as I can. For the characters that cannot be
escaped, I suppose I need a translation table... to figure out what was
the original filename.

Any pointers? More importantly about escaping special characters, and
avoiding directory traversal.
 
L

Luis Parravicini

I have a cgi script that writes files on the filesystem. The files are
provided by the users. I need to save them with (almost) the same name
as the user requests. What characters I need to escape?

This is on linux. Right now the file: "Mick Jagger / Chris Jagger -
Racketeer Blues" does not get saved because of the "/" character. I
don't escape any characters now. I want to keep as many of the original
characters in the file name as I can. For the characters that cannot be
escaped, I suppose I need a translation table... to figure out what was
the original filename.

Any pointers? More importantly about escaping special characters, and
avoiding directory traversal.

Hi Constantin,

Maybe instead of escaping/removing any character in the filename you
can store the file with a unique name and have an index with the user
supplied filename and the name of the file in the file system?
 
C

Constantin Gavrilescu

Luis said:
Hi Constantin,

Maybe instead of escaping/removing any character in the filename you
can store the file with a unique name and have an index with the user
supplied filename and the name of the file in the file system?


The files are also shared over the network with samba, so they need to
have a meaningful name. That's why I need to escape just the "bad
characters" and keep most of the other info in.
 
J

Jonas Roberto de Goes Filho (sysdebug)

Constantin said:
The files are also shared over the network with samba, so they need to
have a meaningful name. That's why I need to escape just the "bad
characters" and keep most of the other info in.

The unique caracter not acceptable for the filename in unix is /. So,
why you not replace this caracter '/' to, for example, a blank caracter ''?
 
C

Constantin Gavrilescu

Felix said:
If you only need this to work on POSIX compatible filesystems, all you
need
to remove are "/" (slash character, as it separates path components) and
\000 (nul, as it terminates strings in many languages) as POSIX file
names
can accept all other ASCII characters.

<snip>

That's interesting...

irb(main):001:0> File.open("aa.php\000continue.jpg", "w")
=> #<File:aa.php>

Creates the file aa.php. Welcome remote code execution vulnerabilities.

irb(main):002:0> File.open("../aaa", "w")
=> #<File:../aaa>

Directory traversal. Creates "aaa" in the parent directory.

irb(main):002:0> File.open("bbb\\bbb.tst", "w")
=> #<File:bbb\bbb.tst>

Linux accepts it. I guess it can be a directory traversal in windows.
Samba exports it as BRRFFZ~N.TST
 
C

Carlos

I have a cgi script that writes files on the filesystem. The files are
provided by the users. I need to save them with (almost) the same name
as the user requests. What characters I need to escape?

This is on linux. Right now the file: "Mick Jagger / Chris Jagger -
Racketeer Blues" does not get saved because of the "/" character. I
don't escape any characters now. I want to keep as many of the original
characters in the file name as I can. For the characters that cannot be
escaped, I suppose I need a translation table... to figure out what was
the original filename.

Any pointers? More importantly about escaping special characters, and
avoiding directory traversal.

You can "semi-URL-escape" the filenames. I mean, use the same method as
CGI::escape, but with more characters allowed. Just adapt the original
function, adding more characters to the regex to allow them, and taking out
the last #tr (spaces to "+")). It is in cgi.rb:

def CGI::escape(string)
string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do
'%' + $1.unpack('H2' * $1.size).join('%').upcase
end.tr(' ', '+')
end

Later, you can easily restore the original filename with CGI::unescape.

For Unix/Linux you can let pass any character except "/" and "\000"; for
Windows/Mac OS, here is a list of forbidden characters:
http://www.xvsxp.com/files/forbidden.php

Good luck.
--
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top