Solr
  1. Solr
  2. SOLR-7966

Solr Admin pages should set X-Frame-Options to DENY

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Trivial Trivial
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 5.4, 6.0
    • Component/s: None
    • Labels:
      None

      Description

      Security scan software reported that Solr's admin interface is vulnerable to clickjacking, which is fixable with the X-Frame-Options HTTP header.

      1. SOLR-7966.patch
        3 kB
        Yonik Seeley
      2. SOLR-7966.patch
        3 kB
        Yonik Seeley

        Activity

        Hide
        Uwe Schindler added a comment - - edited

        Hi Yonik, good idea. This should be possible with a simple ServletFilter adding the header before delegating (I think Jetty has one available). Otherwise just set the header in SolrDispatchFilter if URI path matches admin interface.

        In general, I don't think this is a big problem. OK, one could create a webpage and include a frame/iframe with http://localhost:8983/solr/admin into a web page and browser would load that, but its unlikely that this wil cause any harm.

        I think what we would really need is to send some header to prevent Solr's RequestHandlers to be loaded as images or scripts into HTML - unfortunately there is no header for that (and it won't work because the action is done already after the HTTP request). Simple example is the web page I always show to my customers: http://www.thetaphi.de/nukeyoursolrindex.html (this loads the update handler, sends a delete xml body via url param to the default core by a simple GET request, triggered through an <img src=.../> in the HTML). FYI: This no longer works with Solr 5, because we no longer have a default core, but you can easily modify the IMG element in this page

        Show
        Uwe Schindler added a comment - - edited Hi Yonik, good idea. This should be possible with a simple ServletFilter adding the header before delegating (I think Jetty has one available). Otherwise just set the header in SolrDispatchFilter if URI path matches admin interface. In general, I don't think this is a big problem. OK, one could create a webpage and include a frame/iframe with http://localhost:8983/solr/admin into a web page and browser would load that, but its unlikely that this wil cause any harm. I think what we would really need is to send some header to prevent Solr's RequestHandlers to be loaded as images or scripts into HTML - unfortunately there is no header for that (and it won't work because the action is done already after the HTTP request). Simple example is the web page I always show to my customers: http://www.thetaphi.de/nukeyoursolrindex.html (this loads the update handler, sends a delete xml body via url param to the default core by a simple GET request, triggered through an <img src=.../> in the HTML). FYI: This no longer works with Solr 5, because we no longer have a default core, but you can easily modify the IMG element in this page
        Hide
        Yonik Seeley added a comment -

        OK, here's a patch that works fine via testing by hand,
        but unfortunately I'm not sure how to do a unit test.
        I don't even seem to be able to retrieve the main admin page itself.

        Something like
        http://localhost:8983/solr/#/
        works fine by hand.

        Anyone have pointers how to test this stuff?

        Show
        Yonik Seeley added a comment - OK, here's a patch that works fine via testing by hand, but unfortunately I'm not sure how to do a unit test. I don't even seem to be able to retrieve the main admin page itself. Something like http://localhost:8983/solr/#/ works fine by hand. Anyone have pointers how to test this stuff?
        Hide
        Yonik Seeley added a comment -

        OK, I've got the servlet running, but it fails trying to retrieve /admin.html
        Does anyone know how to get our embedded jetty to pick up a file via getServletContext().getResourceAsStream()?

        Show
        Yonik Seeley added a comment - OK, I've got the servlet running, but it fails trying to retrieve /admin.html Does anyone know how to get our embedded jetty to pick up a file via getServletContext().getResourceAsStream()?
        Hide
        Uwe Schindler added a comment -

        The embedded Jetty in the test framework does not see the web.xml or the webapp at all (there is no webapplication configured). Its configured hardcoded with a random URI prefix, but does not provide the LoadAdminUIServlet at all.

        Currently you cant test this easily with unit tests. You would need to setup UI testing, but there is another issue about that.

        You can quickly mock a test without jetty like done in SolrRequestParserTest. It uses Mock ServletRequest/Response obects and just validates if the called servlet did everything right.

        Show
        Uwe Schindler added a comment - The embedded Jetty in the test framework does not see the web.xml or the webapp at all (there is no webapplication configured). Its configured hardcoded with a random URI prefix, but does not provide the LoadAdminUIServlet at all. Currently you cant test this easily with unit tests. You would need to setup UI testing, but there is another issue about that. You can quickly mock a test without jetty like done in SolrRequestParserTest. It uses Mock ServletRequest/Response obects and just validates if the called servlet did everything right.
        Hide
        Yonik Seeley added a comment -

        Ah, I found a test which apparently does create the full webapp.
        Here's the patch with passing test.

        Show
        Yonik Seeley added a comment - Ah, I found a test which apparently does create the full webapp. Here's the patch with passing test.
        Hide
        Uwe Schindler added a comment -

        New patch looks good (have not tried). I did not know this test

        Show
        Uwe Schindler added a comment - New patch looks good (have not tried). I did not know this test
        Hide
        ASF subversion and git services added a comment -

        Commit 1698341 from Yonik Seeley in branch 'dev/trunk'
        [ https://svn.apache.org/r1698341 ]

        SOLR-7966: set X-Frame-Options to DENY for admin ui

        Show
        ASF subversion and git services added a comment - Commit 1698341 from Yonik Seeley in branch 'dev/trunk' [ https://svn.apache.org/r1698341 ] SOLR-7966 : set X-Frame-Options to DENY for admin ui
        Hide
        ASF subversion and git services added a comment -

        Commit 1698343 from Yonik Seeley in branch 'dev/branches/branch_5x'
        [ https://svn.apache.org/r1698343 ]

        SOLR-7966: set X-Frame-Options to DENY for admin ui

        Show
        ASF subversion and git services added a comment - Commit 1698343 from Yonik Seeley in branch 'dev/branches/branch_5x' [ https://svn.apache.org/r1698343 ] SOLR-7966 : set X-Frame-Options to DENY for admin ui
        Hide
        Steve Rowe added a comment -

        My Jenkins found a JettyWebappTest failure http://jenkins.sarowe.net/job/Lucene-Solr-tests-5.x-Java8/1574/ that reproduces for me on OS X:

           [junit4]   2> NOTE: reproduce with: ant test  -Dtestcase=JettyWebappTest -Dtests.method=testAdminUI -Dtests.seed=5567901EF3993FC2 -Dtests.slow=true -Dtests.linedocsfile=/home/jenkins/lucene-data/enwiki.random.lines.txt -Dtests.locale=ga -Dtests.timezone=Asia/Dubai -Dtests.asserts=true -Dtests.file.encoding=US-ASCII
           [junit4] ERROR   6.73s | JettyWebappTest.testAdminUI <<<
           [junit4]    > Throwable #1: java.lang.IllegalStateException: Scheme 'http' not registered.
           [junit4]    > 	at __randomizedtesting.SeedInfo.seed([5567901EF3993FC2:6DB5734D94F2A47D]:0)
           [junit4]    > 	at org.apache.http.conn.scheme.SchemeRegistry.getScheme(SchemeRegistry.java:74)
           [junit4]    > 	at org.apache.http.impl.conn.ProxySelectorRoutePlanner.determineRoute(ProxySelectorRoutePlanner.java:140)
           [junit4]    > 	at org.apache.http.impl.client.DefaultRequestDirector.determineRoute(DefaultRequestDirector.java:762)
           [junit4]    > 	at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:381)
           [junit4]    > 	at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:882)
           [junit4]    > 	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
           [junit4]    > 	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
           [junit4]    > 	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55)
           [junit4]    > 	at org.apache.solr.client.solrj.embedded.JettyWebappTest.testAdminUI(JettyWebappTest.java:113)
           [junit4]    > 	at java.lang.Thread.run(Thread.java:745)
           [junit4]   2> 6769 INFO  (SUITE-JettyWebappTest-seed#[5567901EF3993FC2]-worker) [    ] o.a.s.SolrTestCaseJ4 ###deleteCore
           [junit4]   2> NOTE: leaving temporary files on disk at: /Users/sarowe/svn/lucene/dev/branches/branch_5x/solr/build/solr-solrj/test/J0/temp/solr.client.solrj.embedded.JettyWebappTest_5567901EF3993FC2-001
           [junit4]   2> NOTE: test params are: codec=HighCompressionCompressingStoredFields(storedFieldsFormat=CompressingStoredFieldsFormat(compressionMode=HIGH_COMPRESSION, chunkSize=1, maxDocsPerChunk=10, blockSize=10), termVectorsFormat=CompressingTermVectorsFormat(compressionMode=HIGH_COMPRESSION, chunkSize=1, blockSize=10)), sim=RandomSimilarityProvider(queryNorm=false,coord=yes): {}, locale=ga, timezone=Asia/Dubai
           [junit4]   2> NOTE: Mac OS X 10.10.5 x86_64/Oracle Corporation 1.8.0_20 (64-bit)/cpus=8,threads=1,free=229789480,total=277872640
           [junit4]   2> NOTE: All tests run in this JVM: [JettyWebappTest]
           [junit4] Completed [1/1] in 8.44s, 1 test, 1 error <<< FAILURES!
        
        Show
        Steve Rowe added a comment - My Jenkins found a JettyWebappTest failure http://jenkins.sarowe.net/job/Lucene-Solr-tests-5.x-Java8/1574/ that reproduces for me on OS X: [junit4] 2> NOTE: reproduce with: ant test -Dtestcase=JettyWebappTest -Dtests.method=testAdminUI -Dtests.seed=5567901EF3993FC2 -Dtests.slow=true -Dtests.linedocsfile=/home/jenkins/lucene-data/enwiki.random.lines.txt -Dtests.locale=ga -Dtests.timezone=Asia/Dubai -Dtests.asserts=true -Dtests.file.encoding=US-ASCII [junit4] ERROR 6.73s | JettyWebappTest.testAdminUI <<< [junit4] > Throwable #1: java.lang.IllegalStateException: Scheme 'http' not registered. [junit4] > at __randomizedtesting.SeedInfo.seed([5567901EF3993FC2:6DB5734D94F2A47D]:0) [junit4] > at org.apache.http.conn.scheme.SchemeRegistry.getScheme(SchemeRegistry.java:74) [junit4] > at org.apache.http.impl.conn.ProxySelectorRoutePlanner.determineRoute(ProxySelectorRoutePlanner.java:140) [junit4] > at org.apache.http.impl.client.DefaultRequestDirector.determineRoute(DefaultRequestDirector.java:762) [junit4] > at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:381) [junit4] > at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:882) [junit4] > at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) [junit4] > at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107) [junit4] > at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55) [junit4] > at org.apache.solr.client.solrj.embedded.JettyWebappTest.testAdminUI(JettyWebappTest.java:113) [junit4] > at java.lang.Thread.run(Thread.java:745) [junit4] 2> 6769 INFO (SUITE-JettyWebappTest-seed#[5567901EF3993FC2]-worker) [ ] o.a.s.SolrTestCaseJ4 ###deleteCore [junit4] 2> NOTE: leaving temporary files on disk at: /Users/sarowe/svn/lucene/dev/branches/branch_5x/solr/build/solr-solrj/test/J0/temp/solr.client.solrj.embedded.JettyWebappTest_5567901EF3993FC2-001 [junit4] 2> NOTE: test params are: codec=HighCompressionCompressingStoredFields(storedFieldsFormat=CompressingStoredFieldsFormat(compressionMode=HIGH_COMPRESSION, chunkSize=1, maxDocsPerChunk=10, blockSize=10), termVectorsFormat=CompressingTermVectorsFormat(compressionMode=HIGH_COMPRESSION, chunkSize=1, blockSize=10)), sim=RandomSimilarityProvider(queryNorm=false,coord=yes): {}, locale=ga, timezone=Asia/Dubai [junit4] 2> NOTE: Mac OS X 10.10.5 x86_64/Oracle Corporation 1.8.0_20 (64-bit)/cpus=8,threads=1,free=229789480,total=277872640 [junit4] 2> NOTE: All tests run in this JVM: [JettyWebappTest] [junit4] Completed [1/1] in 8.44s, 1 test, 1 error <<< FAILURES!
        Hide
        ASF subversion and git services added a comment -

        Commit 1698414 from Yonik Seeley in branch 'dev/trunk'
        [ https://svn.apache.org/r1698414 ]

        SOLR-7966: tests - use HttpClients instead of HttpClientUtil to create a client guaranteed to have http registered

        Show
        ASF subversion and git services added a comment - Commit 1698414 from Yonik Seeley in branch 'dev/trunk' [ https://svn.apache.org/r1698414 ] SOLR-7966 : tests - use HttpClients instead of HttpClientUtil to create a client guaranteed to have http registered
        Hide
        ASF subversion and git services added a comment -

        Commit 1698415 from Yonik Seeley in branch 'dev/branches/branch_5x'
        [ https://svn.apache.org/r1698415 ]

        SOLR-7966: tests - use HttpClients instead of HttpClientUtil to create a client guaranteed to have http registered

        Show
        ASF subversion and git services added a comment - Commit 1698415 from Yonik Seeley in branch 'dev/branches/branch_5x' [ https://svn.apache.org/r1698415 ] SOLR-7966 : tests - use HttpClients instead of HttpClientUtil to create a client guaranteed to have http registered
        Hide
        Yonik Seeley added a comment -

        OK, should be fixed now. I use HttpClients instead of our own HttpClientUtil to ensure that the returned client supports http.

        Show
        Yonik Seeley added a comment - OK, should be fixed now. I use HttpClients instead of our own HttpClientUtil to ensure that the returned client supports http.

          People

          • Assignee:
            Yonik Seeley
            Reporter:
            Yonik Seeley
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development