C#, Programmers Latrinalia

[C#] Be careful with Path.Combine()!

If you are old enough to have experience in .net framework (and I hope you do, otherwise I will feel really old myself!), there is a high probability that you were concatenating directory paths wrong all the time! And that’s all because some time ago, somebody at Microsoft had, let’s say, not a best idea :P.

But what’s the problem?

Path.Combine can be used with one, two, three or even four arguments. In an ideal world the first argument should be passed as an absolute path and the remaining arguments (if exist) should be relative paths. Just like in the following code:
Path.Combine("c:\\Some\\Other", "Subfolder", "file.txt");

But the ideal world doesn’t exist 😉. And in some edge scenario (the scenario we haven’t even expected), we may end up calling Path.Combine like this:
Path.Combine("c:\\Some\\Other", "d:\\Subfolder\\WithPasswords\\super_secret.txt");

Let’s play a little game here. What do you think is the result of the above line?
.
.
.
And the answer is…
"d:\\Subfolder\\WithPasswords\\super_secret.txt”
You may wonder what just happened? Path.Combine takes a first argument and concatenates it with the remaining arguments BUT only when the remaining arguments are relative paths! If one of the later arguments is an absolute path, it concatenates starting from this argument (ignoring the previews ones).
Of course, you will probably never pass an absolute path as a second (or later) argument deliberately. But imagine a situation when you concatenate directory paths and the last part goes from the user, ex.:
Path.Combine(usersFilesPath, userLogin);
Normally, it would return a path like this: “C:\Shop\UsersFiles\johny_123”. But what if one of your users is a sneaky guy and created an account with login name like this: “C:\inetpub\wwwroot\Shop\web.config”
Yeah! We will create a path to the file we would rather try to hide!

Of course it is an edge scenario and all depends on what you are doing with this concatenated path later. But it’s reasonable to consider it as an application vulnerability.

What to do? How to live?

If you use .net core, you should use Path.Join (or Path.TryJoin) instead of the Path.Combine. If you are one of these unlucky guys, and still have to support some .net framework app, make sure that you validate arguments passed to Path.Combine to avoid puting there an absolute path!

Photo by Kai Dörner on Unsplash

Share this: