I believe Dmitry's solution will only work for assets on the classpath
(under src/main/resources/META-INF/assets), because it is a
ClasspathAssetProtectionRule. However, the same directory listing problem
seems to exist for context asset directories (subdirectories under
src/main/webapp), so a different solution is needed there.

ContextAssetRequestHandler is an internal Tapestry service, but it's a very
small class that one could maybe override by contributing a new
AssetRequestHandler implementation for the RequestConstants.CONTEXT_FOLDER
folder. I haven't tried, though.

On Fri, Jan 17, 2020, 4:40 AM Dmitry Gusev <dmitry.gu...@gmail.com> wrote:

> My previous rule didn't work for JAR resources, here's an improved version
> of regex pattern rule:
>
> import org.apache.tapestry5.SymbolConstants;
> import org.apache.tapestry5.ioc.annotations.Symbol;
> import org.apache.tapestry5.services.ClasspathAssetProtectionRule;
>
> import java.util.regex.Matcher;
> import java.util.regex.Pattern;
>
> public class DirectoryListingAssetProtectionRule implements
> ClasspathAssetProtectionRule
> {
>     public static final Pattern LAST_SEGMENT_PATTERN =
> Pattern.compile("[^/\\\\]+$");
>
>     private final String modulePathPrefixGZ;
>
>     public DirectoryListingAssetProtectionRule(
>             @Symbol(SymbolConstants.MODULE_PATH_PREFIX) String
> modulePathPrefix)
>     {
>         this.modulePathPrefixGZ = modulePathPrefix.toLowerCase() + ".gz";
>     }
>
>     @Override
>     public boolean block(String path)
>     {
>         final Matcher matcher = LAST_SEGMENT_PATTERN.matcher(path);
>
>         if (!matcher.find())
>         {
>             //  Empty last segment?
>             return true;
>         }
>
>         final String match = matcher.group().toLowerCase();
>
>         return match.equals(modulePathPrefixGZ) || !match.contains(".");
>     }
> }
>
>
> On Thu, Jan 16, 2020 at 1:35 PM Dmitry Gusev <dmitry.gu...@gmail.com>
> wrote:
>
> > Looking a bit further, it does make sense to me to block all directory
> > requests in ClasspathAssetRequestHandler by default,
> > as directory listing is not something you'd expect to receive via HTTP.
> >
> > That workaround won't work if you have folder with dot in the name
> though,
> > so something more type-safe may be required.
> >
> > At first glance I couldn't find any existing API that would expose
> > underlying File object from an instance of Resource, but for
> > ClasspathResource (and maybe some other resources, like FileResource,
> > ContextResource, etc.) this implementation could probably work better
> (not
> > tested):
> >
> > @Contribute(ClasspathAssetProtectionRule.class)
> > public static void contributeClasspathAssetProtectionRule(
> >         OrderedConfiguration<ClasspathAssetProtectionRule> configuration,
> >         AssetSource assetSource)
> > {
> >     configuration.add("DirectoryListing", path ->
> >     {
> >         Resource resource = assetSource.resourceForPath(path);
> >
> >         if (resource == null)
> >         {
> >             //  Nothing to serve
> >             return true;
> >         }
> >
> >         URL resourceUrl = resource.toURL();
> >
> >         if (resourceUrl != null)
> >         {
> >             try
> >             {
> >                 return
> Path.of(resourceUrl.toURI()).toFile().isDirectory();
> >             }
> >             catch (URISyntaxException e)
> >             {
> >                 throw new RuntimeException(e);
> >             }
> >         }
> >
> >         return false;
> >     });
> > }
> >
> >
> > On Thu, Jan 16, 2020 at 1:19 PM Nicolas Bouillon <nico...@bouillon.net>
> > wrote:
> >
> >> Hi,
> >> Thank you for the quick reply, I've added the following rule in my
> >> AppModule.
> >>
> >> @Contribute(ClasspathAssetProtectionRule.class)
> >> public static void contributeClasspathAssetProtectionRule(
> >>         OrderedConfiguration<ClasspathAssetProtectionRule>
> configuration)
> >> {
> >>     ClasspathAssetProtectionRule fileWithDot = (s) ->
> >> !s.toLowerCase().matches(".*\\.[^/]+");
> >>     configuration.add("DirectoryListing", fileWithDot);
> >> }
> >>
> >> Note that the directory listing is displayed even without any ending
> >> forwarding slash. Then I've forced the requested file name to end with
> >> a . followed by some chars (anything but a forward slash).
> >>
> >> I wonder if that configuration should be put by default, or activable
> >> using a configuration switch described in
> >> https://tapestry.apache.org/security.html
> >>
> >> Thank you again.
> >> Nicolas.
> >>
> >> Le jeu. 16 janv. 2020 à 10:43, Dmitry Gusev <dmitry.gu...@gmail.com> a
> >> écrit :
> >> >
> >> > Hi,
> >> >
> >> > I wasn't aware of it, thanks for bringing it up.
> >> >
> >> > From what I found in code, AssetsModule contributes three asset
> >> protection
> >> > rules: for .xml, .class, and .properties files:
> >> >
> >> > public static void contributeClasspathAssetProtectionRule(
> >> >         OrderedConfiguration<ClasspathAssetProtectionRule>
> >> configuration)
> >> > {
> >> >     ClasspathAssetProtectionRule classFileRule = (s) ->
> >> > s.toLowerCase().endsWith(".class");
> >> >     configuration.add("ClassFile", classFileRule);
> >> >     ClasspathAssetProtectionRule propertiesFileRule = (s) ->
> >> > s.toLowerCase().endsWith(".properties");
> >> >     configuration.add("PropertiesFile", propertiesFileRule);
> >> >     ClasspathAssetProtectionRule xmlFileRule = (s) ->
> >> > s.toLowerCase().endsWith(".xml");
> >> >     configuration.add("XMLFile", xmlFileRule);
> >> > }
> >> >
> >> > So as a possible workaround you could contribute another rule that
> >> vetoes
> >> > asset requests that have no file extension (or end with forward
> slash),
> >> > which should cover directory entries.
> >> >
> >> > On Thu, Jan 16, 2020 at 12:22 PM Nicolas Bouillon <
> nico...@bouillon.net
> >> >
> >> > wrote:
> >> >
> >> > > Hi all,
> >> > >
> >> > > Following a pen-test of our application, it has been raised that the
> >> > > list of assets if visible as a directory listing.
> >> > >
> >> > > For example, we have a javascript file available at this location
> >> > > /assets/meta/z58f7f3d4/javascript/library.js but when we access
> >> > > /assets/meta/z58f7f3d4/javascript/ the web server lists all files
> >> > > available in META-INF.assets.javascript directory of the project.
> >> > >
> >> > > Do you know how to prevent this listing?
> >> > >
> >> > > Looks like to me it's happening in
> >> > >
> >> > >
> >>
> org.apache.tapestry5.internal.services.assets.ClasspathAssetRequestHandler#handleAssetRequest
> >> > > and then in
> >> > >
> >>
> org.apache.tapestry5.internal.services.ResourceStreamerImpl#streamResource(org.apache.tapestry5.ioc.Resource,
> >> > > org.apache.tapestry5.services.assets.StreamableResource,
> >> > > java.lang.String,
> >> > >
> >> > >
> >>
> java.util.Set<org.apache.tapestry5.internal.services.ResourceStreamer.Options>)
> >> > >
> >> > > Thank you,
> >> > > Nicolas.
> >> > >
> >> > >
> ---------------------------------------------------------------------
> >> > > To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
> >> > > For additional commands, e-mail: users-h...@tapestry.apache.org
> >> > >
> >> > >
> >> >
> >> > --
> >> > Dmitry Gusev
> >> >
> >> > AnjLab Team
> >> > http://anjlab.com
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
> >> For additional commands, e-mail: users-h...@tapestry.apache.org
> >>
> >>
> >
> > --
> > Dmitry Gusev
> >
> > AnjLab Team
> > http://anjlab.com
> >
>
>
> --
> Dmitry Gusev
>
> AnjLab Team
> http://anjlab.com
>

Reply via email to