perwendel / spark

A simple expressive web framework for java. Spark has a kotlin DSL https://github.com/perwendel/spark-kotlin
Apache License 2.0
9.64k stars 1.56k forks source link

One staticFiles.externalLocation overwrites another #1031

Closed vladp closed 6 years ago

vladp commented 6 years ago

Hello,

This is likely related to a similar issue https://github.com/perwendel/spark/issues/1005 Only in my case, I am running into this leftover bug --with externalLocation. externalLocations (at least in my case) cannot be subdirectories of each other -- as that introduces a security risk/exploit. So I could not make one location as a subdirectory of another as @tipsy recommend at some point to overcome this bug for /public resource folders.

Details (using spark 0.7.2 )

I have a setup where a single java instance of Spark, is servicing 2 separate small web apps, from 2 separate ports (of the same IP address).

I am leveraging the ignite method to setup to separate Services.

main () {

Service port4000 = Service.ignite();
port4000.port(4000);
port4000.staticFIles.location("/public");
port4000.staticFiles.externalLocation("/tmp/www/port4000app");
port4000.get (... )

Service port6000 = Service.ignite();
port6000.port(6000);
port6000.staticFIles.location("/public");
port6000.staticFiles.externalLocation("/tmp/www/port6000app");
port6000.get(...);
}

With the above configuration, I am getting an exception from DirectoryTravesal.java


    public static void protectAgainstForExternal(String path) {
        String nixLikePath = Paths.get(path).toAbsolutePath().toString().replace("\\", "/");
        if (!removeLeadingAndTrailingSlashesFrom(nixLikePath).startsWith(StaticFilesFolder.external())) {
            throw new DirectoryTraversalDetection("external");
        }
    }

Because when comparing the requested directory at port 4000, it is using StaticFilesFolder.external() , and that returns a directory associated with port 6000 (because it was setup last).

This is happening because, it appears, that Spark does not associate static folders with a particular Service instance, and instead, this is just simply a global value that can only be initialized once per application.

But then, this either seems to be a bug, or I am not understanding correctly how to initialize 2 separate Services within same main, using the ignite() function.

I scanned the docs but could not find guidance on this.

Presumably, this can also cause a security exploit, when a attacker can get access to capabilities that should not be available from a given port/service (because protectAgainstForExternal would not protect)

Thank you in advance,

PS: static instance of the staticFiles configuration here: https://github.com/perwendel/spark/blob/master/src/main/java/spark/staticfiles/StaticFilesConfiguration.java

tipsy commented 6 years ago

It's the same bug as in the issue you linked to.

vladp commented 6 years ago

@tipsy thx for the confirmation. Your continuous support through this forum, is very much appreciated.

Hoping this is something that could be addressed, as this bug is essentially forcing apps to use multiple JVMs, rather than efficient pool of threads in one JVM instance (when the framework is used to build web app back-ends).

perwendel commented 6 years ago

Fixed by #1036