https://issues.apache.org/bugzilla/show_bug.cgi?id=52988
Bug #: 52988
Summary: ExpandWar::deleteDir() traverses symlinked
directories, deleting files outside of appBase
Product: Tomcat 7
Version: 7.0.16
Platform: Other
OS/Version: Linux
Status: NEW
Severity: normal
Priority: P2
Component: Catalina
AssignedTo: [email protected]
ReportedBy: [email protected]
CC: [email protected]
Classification: Unclassified
Overview:
When Tomcat fails to expand a WAR file, it attempts to clean up after itself by
running deleteDir(docBase). This function contains a problematic if-condition
that allows Tomcat to traverse symlinked directories and recursively delete
files behind them, even if those files are outside 'docBase'.
Steps to Reproduce:
1) Explode a WAR successfully into webapps/.
2) Add a symlink in that WAR's docbase to a directory outside of webapps/. As
far as I can tell, it can be anywhere on the machine (ours traversed a mount,
for example).
3) Redeploy a WAR, but make it fail somehow (I witnessed it while deploying a
corrupted zip archive), thus activating these lines of ExpandWar.java:
158 if (!success) {
159 // If something went wrong, delete expanded dir to keep
things.
160 // clean
161 deleteDir(docBase);
162 }
Actual Results:
deleteDir() traversed the directory symlinks in 'docBase', allowing Tomcat to
incorrectly delete files outside of docBase. It appears the problem is line 374
of ExpandWar.java. Despite internet sources claiming otherwise, I was able to
verify the isDirectory() method returns 'true' for symlinked directories using
my version, build, and platform:
366 public static boolean deleteDir(File dir, boolean logFailure) {
367
368 String files[] = dir.list();
369 if (files == null) {
370 files = new String[0];
371 }
372 for (int i = 0; i < files.length; i++) {
373 File file = new File(dir, files[i]);
374 if (file.isDirectory()) {
375 deleteDir(file, logFailure);
376 } else {
377 file.delete();
378 }
Expected Results:
ExpandWar.java should delete symlinks without following them. One could either
check the absolute vs. canonical path, or use something like the isSymlink()
method already present in Apache Commons:
http://stackoverflow.com/a/813730/877115
Build Date and Platform:
Sun java 1.6.0_20 running on RHEL 6.1. First discovered in 7.0.16, but I
checked trunk and the troubled logic is unchanged there.
Additional information:
We used symlinks to link client assets inside docBase for legacy code purposes.
We've refactored this code out after encountering this bug, as maintaining
symlinks inside exploded WARs is difficult, a bad practice, and this bug makes
them a time bomb. All the same, I can't imagine any conditions under which
Tomcat's WAR logic should be able to delete files outside of 'docBase', even if
the user was foolish like me. Hence this filing.
--
Configure bugmail: https://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]