Skip to content

Commit 763f060

Browse files
authored
Create Ruby-tempfile-mktmpdir-PT.md
1 parent b44f4fd commit 763f060

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

Ruby-tempfile-mktmpdir-PT.md

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
## Path traversal in Ruby's Tempfile and mktmpdir on Windows
2+
3+
### The bug
4+
5+
While playing around Ruby we noticed that Ruby's Tempfile/mktmpdir were allowing `\` in Filename and extension which immediately made us wonder what happens when we do this on windows as the file separator on Windows is also `\`. To our surprise, it was working, we had a path traversal in Tempfile on Windows. But to our knowledge while reading source of Node, generally languages have file separator based on the OS you're running the language on. So we wondered what is Ruby doing to identify file sepaator here. It didn't work on `File.basename` which made it clear that Tempfile is doing something differet.
6+
7+
### CVE-2018-6914 Patch analysis
8+
9+
A similar issue was previously reported by @oooooo_q for Linux, where `/` could be used which made path traversal possible on both Linux and Windows. We looked at the patch of this bug, which was relatively straight forward, delete `/` (File::SEPARATOR) and `\` (File::ALT_SEPARATOR, set on windows only) from the input before creating the file.
10+
11+
```patch
12+
--- lib/tmpdir.rb
13+
+++ lib/tmpdir.rb
14+
@@ -114,10 +114,12 @@ def create(basename, tmpdir=nil, max_try: nil, **opts)
15+
end
16+
n = nil
17+
prefix, suffix = basename
18+
+ prefix = prefix.delete("#{File::SEPARATOR}#{File::ALT_SEPARATOR}")
19+
prefix = (String.try_convert(prefix) or
20+
raise ArgumentError, "unexpected prefix: #{prefix.inspect}")
21+
suffix &&= (String.try_convert(suffix) or
22+
raise ArgumentError, "unexpected suffix: #{suffix.inspect}")
23+
+ suffix &&= suffix.delete("#{File::SEPARATOR}#{File::ALT_SEPARATOR}")
24+
begin
25+
```
26+
27+
We run the above patch
28+
29+
![image](https://user-images.githubusercontent.com/21000421/113866846-6c88ec00-97cb-11eb-8214-d2c6f7af8e2a.png)
30+
31+
The patch here works as expected, where's the problem? why is the `\` not removed from the input then?
32+
33+
### Any changes that can regress this?
34+
35+
We opened the master branch and went through the code and found the code has recently changed, the change basically adds more characters and uses a constant now for this chars
36+
37+
```patch
38+
---
39+
lib/tmpdir.rb | 6 ++++--
40+
1 file changed, 4 insertions(+), 2 deletions(-)
41+
42+
diff --git a/lib/tmpdir.rb b/lib/tmpdir.rb
43+
index 87e53a8..05e74eb 100644
44+
--- a/lib/tmpdir.rb
45+
+++ b/lib/tmpdir.rb
46+
@@ -112,6 +112,8 @@ def tmpdir
47+
Dir.tmpdir
48+
end
49+
50+
+ UNUSABLE_CHARS = [File::SEPARATOR, File::ALT_SEPARATOR, File::PATH_SEPARATOR, ":"].uniq.join("").freeze
51+
+
52+
def create(basename, tmpdir=nil, max_try: nil, **opts)
53+
if $SAFE > 0 and tmpdir.tainted?
54+
tmpdir = '/tmp'
55+
@@ -123,10 +125,10 @@ def create(basename, tmpdir=nil, max_try: nil, **opts)
56+
prefix, suffix = basename
57+
prefix = (String.try_convert(prefix) or
58+
raise ArgumentError, "unexpected prefix: #{prefix.inspect}")
59+
- prefix = prefix.delete("#{File::SEPARATOR}#{File::ALT_SEPARATOR}")
60+
+ prefix = prefix.delete(UNUSABLE_CHARS)
61+
suffix &&= (String.try_convert(suffix) or
62+
raise ArgumentError, "unexpected suffix: #{suffix.inspect}")
63+
- suffix &&= suffix.delete("#{File::SEPARATOR}#{File::ALT_SEPARATOR}")
64+
+ suffix &&= suffix.delete(UNUSABLE_CHARS)
65+
66+
```
67+
68+
Commit - https://github.com/ruby/tmpdir/commit/5a70e9c27d29ebcb7a04a6c00400219ac62ec0af
69+
70+
### What's wrong? why `\` is not deleted?
71+
72+
The change were basically same to us, until we tried them by ourself.
73+
74+
![image](https://user-images.githubusercontent.com/21000421/113867036-a9ed7980-97cb-11eb-85b7-61f6d53d7bab.png)
75+
76+
Whoops, `.delete` expects `\` to be escaped, Was it intentional to write delete this way? or It's wrongly used here?
77+
78+
Ruby fixed it by changing the way delete has been used here - https://github.com/ruby/tmpdir/commit/adf294bc2d10cd223aa3ca488079ec313032c07b
79+
HackerOne Report - https://hackerone.com/reports/1131465
80+
81+
That's all, Thanks for reading.

0 commit comments

Comments
 (0)