Skip to content

STORM-269: prevent logviewer from serving files outside the log directory#91

Merged
asfgit merged 4 commits intoapache:masterfrom
ptgoetz:STORM-269
Apr 29, 2014
Merged

STORM-269: prevent logviewer from serving files outside the log directory#91
asfgit merged 4 commits intoapache:masterfrom
ptgoetz:STORM-269

Conversation

@ptgoetz
Copy link
Copy Markdown
Member

@ptgoetz ptgoetz commented Apr 25, 2014

This is a quick fix to prevent the log viewer from serving files outside of the log directory. It simply checks that the requested file has the root log directory as a parent. If this is not the case, it will not serve the file.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The string check will not prevent log-dir/../../../../etc/passwd I don't think.

Can we try something like this?

(let [file (.getCanonicalFile (File. LOG-DIR fname))
      path (.getCanonicalPath file)]
    (if (= (File. LOG-DIR) (.getParentFile file))

Indentation looks a little weird too, after the if was added. Not sure if that's a tabs vs. spaces issue.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The path to the requested file (String) comes from File.getCanonicalPath() further down in the code. so all the relative portions of the path will have been resolved.

I'll check the indentation. I'm open to either approach.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, you're right, it is resolved. But then I also noticed root-dir is given by the request.

Would a request like this also succeed?

/log?tail=99999999&file=passwd&log-root=/etc

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, good catch. This thing is an open http server for the entire file system. Thankfully it doesn't support POST or PUT.

There's no reason we should allow the root-dir to be specified as a request parameter. That's insane. I pity the fool running this as root.

Whatever the fix, I think it needs to be a high priority. I would also consider back porting the fix to earlier releases.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@d2r I think we're okay with this patch. I tried a couple of things and it looks like you can't override root-dir in the request since the conf-middleware function associates it with the request, so it is ignored if supplied as a request parameter.

I tried the following url:

http://supervisor:8000/log?file=hosts&log-root=/etc/

And nothing was returned. I got the following in logviewer.log:

2014-04-27 14:07:23 o.m.log [WARN] /log?file=hosts&log-root=/etc/
java.io.FileNotFoundException: /var/log/storm/hosts (No such file or directory)

(Note that in this installation, storm is configured to log to /var/log/storm/)

@lucky
Copy link
Copy Markdown

lucky commented Apr 25, 2014

Root or not, any file readable by storm is accessible, including configuration files which means this has the potential for exposing credentials.

@ptgoetz
Copy link
Copy Markdown
Member Author

ptgoetz commented Apr 25, 2014

@lucky Agreed. Until this is fixed, I think we need to recommend that the logviewer daemon not be run unless appropriate safeguards are in place.

@harshach
Copy link
Copy Markdown
Contributor

I don't think log-root can be sent as http param its being read from storm config .
https://github.com/apache/incubator-storm/blob/master/storm-core/src/clj/backtype/storm/daemon/logviewer.clj#L108
with @ptgoetz fix logviewer not able to read any other files apart from the ones in storm.log.dir and log-root is not accepted via http param. I tested the fix in centos 6.3 and windows 7, os x it works in plugging the security hole.

@ptgoetz
Copy link
Copy Markdown
Member Author

ptgoetz commented Apr 27, 2014

I updated the patch to fix the formatting. I also added an extra conversion of the log-root to a canonical path to ensure we are comparing full paths.

@d2r
Copy link
Copy Markdown

d2r commented Apr 28, 2014

@harshach, @ptgoetz OK, good to know it is not as open as I feared.

With the String compare instead of File compare, do we know whether this will give a string with a trailing slash?

(.getCanonicalPath (File. root-dir))

If it does, we should be OK. If not, then a user could get to certain sibling directories. (e.g., if root-dir was a directory named "foo", then a user could read from a sibling directory "foobar").

@ptgoetz
Copy link
Copy Markdown
Member Author

ptgoetz commented Apr 28, 2014

@d2r You're right. I switched over to using File to do the comparison. This will also prevent users from accessing files in subdirectories log directory.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be (.getCanonicalFile (File. root-dir))?
I am not sure whether FileAppender#getFile will give the canonical path. If it does not, and if the Appender's path has a symlink, then the new condition could fail even for legitimate requests.

@ptgoetz
Copy link
Copy Markdown
Member Author

ptgoetz commented Apr 28, 2014

@d2r -- updated per your comments.

@d2r
Copy link
Copy Markdown

d2r commented Apr 28, 2014

  • Tested with ../ -> File not found
  • Tested with /etc/passwd -> File not found
  • Tested above with logback pointing to a file with symlink in the path -> File not found
  • Tested with file under sibling directory (logsfoo/foobar) -> File not found
  • Tested normal case (logviewer.log) -> OK

Looks good.

+1

@lucky
Copy link
Copy Markdown

lucky commented Apr 28, 2014

@d2r Did you test with the example I gave in the bug report?

../../../../../../../../../../etc/passwd

@d2r
Copy link
Copy Markdown

d2r commented Apr 28, 2014

Just did -> File not found.

@lucky
Copy link
Copy Markdown

lucky commented Apr 28, 2014

Awesome, thanks!

@revans2
Copy link
Copy Markdown
Contributor

revans2 commented Apr 29, 2014

looks good to me too +1.

@ptgoetz
Copy link
Copy Markdown
Member Author

ptgoetz commented Apr 29, 2014

Awesome. Thanks for the review guys.

@asfgit asfgit merged commit 6904862 into apache:master Apr 29, 2014
@xiaokang
Copy link
Copy Markdown
Contributor

It's really a serious security hole. Thanks all guys to find and fix it. I'm really sorry to have introduced the problem when contributing the logviewer code.

@nothinking
Copy link
Copy Markdown
Contributor

To someone like me.

If you want to change log dir, add to storm.yaml this line.

storm.log.dir=/some/real/dir/path

Remember! No Symbolic Path!!

knusbaum pushed a commit to knusbaum/incubator-storm that referenced this pull request Feb 11, 2015
Add in transitive dependencies to yinst
arunmahadevan pushed a commit to arunmahadevan/storm that referenced this pull request Apr 7, 2016
EAR-3293: If a code distributor entry is left behind nimbus should no…
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants