Security: media is publicly available, bypassing login

General discussions.

Moderator: moderators

Security: media is publicly available, bypassing login

Postby dest41 » Thu Jan 21, 2016 3:55 pm

I don't think this "feature" is desired: knowing the url of any Subsonic server, it is possible to download media from it with the following URL scheme:
http://server:port/stream?id=N
where N is the number of the song in the library. To dump a library, simply iterate over N.

Anybody can reproduce this behavior? If confirmed, a token should be provided with the request to authenticate the requester.
dest41
 
Posts: 10
Joined: Wed Apr 08, 2015 9:10 am

Re: Security: media is publicly available, bypassing login

Postby frnx » Thu Jan 21, 2016 10:08 pm

I can definitely reproduce this. I'm disabling external access until we know more, but did you send an email to Sindre about this? He may want to know about it rather sooner than later.

EDIT: Also, using an ID that does not exist when the Subsonic server was just restarted results in downloading (very slowly) a file full of ones (0xFF everywhere), then any subsequent accesses to the main page gives :

Code: Select all
Exception    java.lang.NullPointerException
Message    null
Java version    Oracle Corporation 1.8.0_72
Operating system    Linux 4.3.3-3-ARCH
Server    jetty-6.1.x
Memory    Used 43 of 112 MB
Stack trace    java.lang.NullPointerException
   at net.sourceforge.subsonic.service.SecurityService.getMusicFolderForFile(SecurityService.java:240)
   at net.sourceforge.subsonic.service.SecurityService.isInMusicFolder(SecurityService.java:235)
   at net.sourceforge.subsonic.service.SecurityService.isReadAllowed(SecurityService.java:203)
   at net.sourceforge.subsonic.service.MediaFileService.getMediaFile(MediaFileService.java:99)
   at net.sourceforge.subsonic.service.MediaFileService.getMediaFile(MediaFileService.java:81)
   at net.sourceforge.subsonic.controller.NowPlayingController.handleRequestInternal(NowPlayingController.java:54)
   at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
   at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
   at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
   at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
   at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
   at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
   at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
   at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1093)
   at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:265)
   at org.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:107)
   at org.acegisecurity.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:72)
   at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
   at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:166)
   at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
   at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
   at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
   at org.acegisecurity.ui.rememberme.RememberMeProcessingFilter.doFilter(RememberMeProcessingFilter.java:135)
   at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
   at org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:81)
   at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
   at org.acegisecurity.ui.basicauth.BasicProcessingFilter.doFilter(BasicProcessingFilter.java:173)
   at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
   at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:271)
   at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
   at org.acegisecurity.ui.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
   at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
   at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:249)
   at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
   at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:149)
   at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
   at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
   at net.sourceforge.subsonic.filter.RequestEncodingFilter.doFilter(RequestEncodingFilter.java:43)
   at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
   at net.sourceforge.subsonic.filter.ParameterDecodingFilter.doFilter(ParameterDecodingFilter.java:54)
   at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
   at net.sourceforge.subsonic.filter.BootstrapVerificationFilter.doFilter(BootstrapVerificationFilter.java:59)
   at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
   at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
   at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
   at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
   at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:712)
   at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
   at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139)
   at org.mortbay.jetty.Server.handle(Server.java:313)
   at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:506)
   at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:830)
   at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:514)
   at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
   at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:381)
   at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:396)
   at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:442)
frnx
 
Posts: 44
Joined: Sun May 31, 2015 8:30 pm

Re: Security: media is publicly available, bypassing login

Postby daneren2005 » Thu Jan 21, 2016 10:22 pm

There was another thread about it here somewhere so sindre probably already knows about it. I believe it's for the external playlist feature. But you are right it definitely should be authenticated with a token instead of just left wide open like that.
Developer of DSub for Android
daneren2005
 
Posts: 1709
Joined: Fri Jul 06, 2012 7:52 pm

Re: Security: media is publicly available, bypassing login

Postby frnx » Thu Jan 21, 2016 10:30 pm

Ah, it makes sense then, but it's definitely not ideal. It should at least be possible to disable the external playlist feature (I for one have never used it).
frnx
 
Posts: 44
Joined: Sun May 31, 2015 8:30 pm

Re: Security: media is publicly available, bypassing login

Postby dest41 » Fri Jan 22, 2016 10:36 am

Just to be sure, I just sent a mail to Sindre Mehus.
dest41
 
Posts: 10
Joined: Wed Apr 08, 2015 9:10 am

Re: Security: media is publicly available, bypassing login

Postby frnx » Fri Jan 22, 2016 8:02 pm

Thanks! The same thing appears to happen on coverArt.view. I'm going to look at all the routes and see if I can make a list.
frnx
 
Posts: 44
Joined: Sun May 31, 2015 8:30 pm

Re: Security: media is publicly available, bypassing login

Postby sindre_mehus » Sat Jan 23, 2016 12:52 pm

Thanks for bringing this up.

The stream and coverart endpoints are intentionally unauthenticated to make it work with external players (e.g., Sonos and Chromecast), but I will find a way to make it more secure.

Thanks
Sindre
Subsonic developer
User avatar
sindre_mehus
 
Posts: 1955
Joined: Tue Nov 29, 2005 6:19 pm
Location: Oslo, Norway

Re: Security: media is publicly available, bypassing login

Postby frnx » Sun Jan 24, 2016 3:39 pm

Thanks for the quick reply, and the quick commits! Using the file hash seems enough to prevent library iteration, I think that's all we needed. :)
frnx
 
Posts: 44
Joined: Sun May 31, 2015 8:30 pm

Re: Security: media is publicly available, bypassing login

Postby manwithaplan » Tue Feb 23, 2016 9:01 pm

Sindre or others,

I need to understand this better - couple questions:

1. Does this impact Subsonic 5.2.1?
2. Are we saying that even if you don't allow downloads as a user privilege for any of your users, that this vulnerability allows people to download every single song or album in your database?
3. Is there some workaround I can make in 5.2.1 to mitigate this access? (I have no problem doing custom file changes, but am not willing to upgrade off of 5.2.1 anytime soon).

Thanks all!
Subsonic 5.2.1 on 2009 Apple XServe w/ Yosemite Server 10.10.5; 96GB RAM. Lots of Music - High Rez, native DSD streaming, and otherwise.
manwithaplan
 
Posts: 153
Joined: Sun Nov 28, 2010 5:01 pm


Return to General

Who is online

Users browsing this forum: No registered users and 4 guests