views:

176

answers:

3

If I choose lots of files tactics,
then I become to have directory
traversal security problem?

I need to write login system,
and lots of file tactics means

make lots of id files and use scandir.

so the directory would have

aaa.txt (contents is aaa_pass)
bbb.txt (contents is bbb_pass)
ccc.txt (contents is ccc_pass)

and when someone enter his id,
the system scandir the directory,
then find the id files.

but hey, what if he enters as

"../../important.txt" ?

then he could access to the ../../important.txt ?

+1  A: 

At first glance, it seems like you are going down a somewhat strange path for writing a login system. I'm not sure plain text files in a directory on the filesystem is a wise path to take if for no other other reason than that it's abnormal and you'rer likely to overlook many of the subtleties that are already thought through in more common authentication systems. If you wanted to store the passwords hashed and salted, for instance, you'd need to think through how to implement that in your scheme and you could make a mistake that would lead to a security problem. Using a good PEAR library or even the Zend_Auth component from Zend Framework, though, would give you a clear and well-documented starting point.

Anyway, assuming you have your reasons for the arrangement you describe in your question, the basename() function is likely what you want in this case. It will strip everything but the filename itself so that they can't do a directory traversal attack like you describe in your question.

So if the input from the user is:

../../important

You can run:

$cleanUsername = basename($input);
$filename      = '/path/to/password/files/' . $cleanUsername . '.txt';

if (file_exists($filename)) {
    [...]
}

Make sense?

Brad G.
ah....Do I need sanitize? and it measn lots of files tactics have directory traversal security problem?
Jonathan itou
Calling basename() on the user's input will prevent them from reading files from other directories, so that degree of sanitizing is definitely needed, yes. So long as you ensure that the usernames conform to a subset of characters that is safe for filenames in your operating system (alpha-numeric would probably be a safe bet, maybe including underscores, if needed), that should be all you really need. You'd just get the input, pass it through basename() and then iterate through the files to see if a matching file exists.
Brad G.
+1  A: 

You could perform some validation of the username before you use it as part of a path - for example to only allow letters and numbers you could do something like this using a regular expression:

if (!preg_match('/^[a-zA-Z0-9]+$/', $username)) {
    //username is not valid
} else {
    //username is ok to use
}

Another way you could do it is to hash the username before you read or write it, for example:

$hash = sha1($username);

This way, the user can have anything as their username and there will be no danger of them manipulating the behaviour of your file lookup. A username of "../../important.txt" would give you a hash of "48fc9e70df592ccde3a0dc969ba159415c62658d", which is safe despite the source string being nasty.

Tom Haigh
oh, hash tactics sounds good!
Jonathan itou
+1  A: 

If you have no other choice than to use this file-password system (assuming you have to for one reason or another), in addition to creating some kind of obfuscated file names, you may also want create files with the same extension as your server-side language just in case - for example, if you are using PHP, your file name would be john.php (or obfuscated 'john'), and contents might be something like this:

<?php
    exit; // or maybe even a header redirect --
    /*password goes here*/
?>

Of course your file-read routine will need to parse our the phrase inside the comment block.

This way, if someone DOES somehow arrive at that file, it will never render.

OneNerd