Three dots directory traversal with mv
There may be no directory with the name ...
in the current directory, but you're creating a file with that name. (Because it starts with a .
, it's hidden).
You can see such hidden files if using the -a
argument to ls
:
$ ls -a
. ..
$ touch file; mv file ...; ls -a
. .. ...
How can I put files into subdirectories based on the name of the file using bash?
You can do it simpler because mkdir -p path/to/yours
works just with one invocation. You do not have to recursively create subdirectories one by one.
Would you please try:
cd /directory/with/files # cd to directory where files are located
for file in *; do
[[ -f $file ]] || continue # skip non-file entries (just in case)
dir=${file%_*}
base=${file##*_}
dir=${dir//_/\/} # replace "_"s with "/"s
mkdir -p "$dir"
mv -- "$file" "$dir/$base"
done
[Strict Version]
The script below performs the validation of the filenames (with a help of jhnc).
for file in *; do
[[ -f $file ]] || continue # skip non-file entries (just in case)
dir=${file%_*}
base=${file##*_}
dir=${dir//_//} # replace "_"s with "/"s
# validate filenames
case "/$dir/" in
*/../* | */./* | //*) # $dir contains extra dot(s)
echo "skipping invalid filename: $file"
continue
;;
esac
if [[ -z $base ]]; then # the filename ends with "_"
echo "skipping invalid filename: $file"
continue
fi
mkdir -p "$dir"
mv -- "$file" "$dir/$base"
done
Result:
/directory/
└── with
└── files
└── 2020
├── Documents
│ ├── Bills
│ │ └── Water Bill.pdf
│ ├── Receipts
│ │ └── Store Name
│ │ └── Groceries.pdf
│ └── Taxes
│ └── W2.pdf
└── Pictures
└── Family Trip
└── California
└── Disney Land
└── Family Pic.jpg
Dot-dot removed from URL by Firefox
".." means a relative path and used for moving up in the hierarchy. So ".." is not a valid name for a folder therefore you cannot use it in the middle of URL. It just makes no sense.
So to answer your question: ".." is allowed in url but only in the beginning.
Directory traversal with chdir() instead of with absolute paths
I don't think you should expect a substantial time performance difference between the absolute path version and the chdir()
version. Rather, the pros and cons of both versions are as follows:
- The full pathname version might not be able to traverse very deep directory structures because the length of the full pathname eventually exceeds
PATH_MAX
. Thechdir()
version does not have this problem. - The
chdir()
version manipulates the pwd, which is generally considered bad practice if you can avoid it: it's not thread-safe, and the end user might expect it to be left alone. For example filenames given on the command line and used by a different part of the program might be relative to what the user thought the pwd was, which breaks when you change it. - The
chdir()
version might go out of control when backing up to a higher directory (chdir("..")
) if special care is not taken and the directory structure changes while it is being traversed. Then again the full pathname version might break in a different way under these circumstances...
The openat()
family of functions available on modern POSIX systems offer the best of both worlds. If these functions are available, openat()
together with fdopendir()
, fstatat()
, etc... make for a really nice implementation of directory walking.
Is directory traversal via request.url possible?
I was gonna say that you can be sure that it's not possible, then I tried and I have to say that no, it doesn't seem like the http module removes '/../'. The redirection you saw is done in the browser. So whether it's a security risk or not depends on how your static handler is implemented.
Proof of concept:
// Server
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(req.url);
}).listen(1337);
Curl it:
curl --path-as-is "http://localhost:1337/static/../app.js"
# /static/../app.js
So if you use a homebuilt static handler that just uses path.resolve() you're screwed. Hopefully popular ones like express.static have thought about this, but i haven't tried it.
Update
Express indeed responds with a 404 "Error: Forbidden".
How to deal with Path Traversal?
An easy way would be to validate the fileName through a regex that detects any ../
segments and returns an error if any are present.
if (fileName.match(/\.\.\//g) !== null) {
// return an api error
}
You could have quite a tight validation rule that prevents any forward slashes in fileName at all, making it only possible to point to a file directly in your desired directory.
Related Topics
How to Pass Local Shell Script Variable to Expect
How to Add External References in Monodevelop
Cuda - Confusion About The Visual Profiler Results of "Branch" and "Divergent Branch" (2)
Change The Escape Sequence Generated by Xterm for Key Combinations
Aosp Build Error: Unrecognized Module Type "Hidl_Package_Root"
Git Is Not Ignoring File Permission Changes
The Button.Connect Syntax in Genie
Run Random Command in Bash Script
Grep If The Next X Lines Doesn't Contain a Specific String
Command Execution with Nohup in Background
Convert a Base64 Ldif File to Plaintext (For Import)
Timeouting a While Loop in Linux Shell Script
Running a Program Through Ssh Fails with "Error Opening Terminal: Unknown."
Linux Tcp Connect with Select() Fails at Testserver
How to Export Daily Disk Usage to CSV Format in Shell Scripting